mirror of
https://github.com/GTNewHorizons/Angelica.git
synced 2026-11-15 01:34:48 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4630bc4fd8 | ||
|
|
ce32a3d3df | ||
|
|
1991dc58ec | ||
|
|
ae19236e1a | ||
|
|
7ad368c937 | ||
|
|
5c86c87bcf | ||
|
|
99ba7fa775 | ||
|
|
5ae4ab8c5c | ||
|
|
ddd68e023f | ||
|
|
f78cfdd5fb | ||
|
|
183bcfbf41 |
No files matched your search
@@ -194,10 +194,6 @@ public class GLStateManager {
|
||||
RENDER_BACKEND.vertexAttrib4f(Usage.COLOR.getAttributeLocation(), color.getRed(), color.getGreen(), color.getBlue(), color.getAlpha());
|
||||
dirtyColorAttrib = false;
|
||||
}
|
||||
if (dirtyLightmapAttrib && (vertexFlags & VertexFlags.BRIGHTNESS_BIT) == 0) {
|
||||
RENDER_BACKEND.vertexAttrib4f(Usage.SECONDARY_UV.getAttributeLocation(), GLSMConfig.lastBrightnessX, GLSMConfig.lastBrightnessY, 0.0f, 1.0f);
|
||||
dirtyLightmapAttrib = false;
|
||||
}
|
||||
if (dirtyNormalAttrib && (vertexFlags & VertexFlags.NORMAL_BIT) == 0) {
|
||||
final var n = ShaderManager.getCurrentNormal();
|
||||
RENDER_BACKEND.vertexAttrib3f(Usage.NORMAL.getAttributeLocation(), n.x, n.y, n.z);
|
||||
@@ -208,6 +204,10 @@ public class GLStateManager {
|
||||
RENDER_BACKEND.vertexAttrib4f(Usage.PRIMARY_UV.getAttributeLocation(), tc.x, tc.y, tc.z, tc.w);
|
||||
dirtyTexCoordAttrib = false;
|
||||
}
|
||||
if (dirtyLightmapAttrib) {
|
||||
RENDER_BACKEND.vertexAttrib4f(Usage.SECONDARY_UV.getAttributeLocation(), GLSMConfig.lastBrightnessX, GLSMConfig.lastBrightnessY, 0.0f, 1.0f);
|
||||
dirtyLightmapAttrib = false;
|
||||
}
|
||||
}
|
||||
|
||||
// Highest texture unit index that has ever had a non-zero binding; limits onDeleteTexture scan range
|
||||
@@ -1860,6 +1860,7 @@ public class GLStateManager {
|
||||
suspendPixelUnpackBuffer();
|
||||
RENDER_BACKEND.texImage2D(target, level, internalformat, width, height, border, format, type, pixels);
|
||||
restorePixelUnpackBuffer();
|
||||
maybeGenerateMipmap(target, level);
|
||||
}
|
||||
|
||||
public static void glTexImage2D(int target, int level, int internalformat, int width, int height, int border, int format, int type, FloatBuffer pixels) {
|
||||
@@ -1875,6 +1876,7 @@ public class GLStateManager {
|
||||
suspendPixelUnpackBuffer();
|
||||
RENDER_BACKEND.texImage2D(target, level, internalformat, width, height, border, format, type, pixels);
|
||||
restorePixelUnpackBuffer();
|
||||
maybeGenerateMipmap(target, level);
|
||||
}
|
||||
|
||||
public static void glTexImage2D(int target, int level, int internalformat, int width, int height, int border, int format, int type, DoubleBuffer pixels) {
|
||||
@@ -1890,6 +1892,7 @@ public class GLStateManager {
|
||||
suspendPixelUnpackBuffer();
|
||||
RENDER_BACKEND.texImage2D(target, level, internalformat, width, height, border, format, type, pixels);
|
||||
restorePixelUnpackBuffer();
|
||||
maybeGenerateMipmap(target, level);
|
||||
}
|
||||
|
||||
public static void glTexImage2D(int target, int level, int internalformat, int width, int height, int border, int format, int type, ByteBuffer pixels) {
|
||||
@@ -1905,6 +1908,7 @@ public class GLStateManager {
|
||||
suspendPixelUnpackBuffer();
|
||||
RENDER_BACKEND.texImage2D(target, level, internalformat, width, height, border, format, type, pixels);
|
||||
restorePixelUnpackBuffer();
|
||||
maybeGenerateMipmap(target, level);
|
||||
}
|
||||
|
||||
public static void glTexImage2D(int target, int level, int internalformat, int width, int height, int border, int format, int type, long pixels_buffer_offset) {
|
||||
@@ -1914,6 +1918,7 @@ public class GLStateManager {
|
||||
}
|
||||
TextureInfoCache.INSTANCE.onTexImage2D(target, level, internalformat, width, height, border, format, type, pixels_buffer_offset);
|
||||
RENDER_BACKEND.texImage2D(target, level, internalformat, width, height, border, format, type, pixels_buffer_offset);
|
||||
maybeGenerateMipmap(target, level);
|
||||
}
|
||||
|
||||
public static void glTexCoord1f(float s) {
|
||||
@@ -3734,6 +3739,25 @@ public class GLStateManager {
|
||||
return DisplayListManager.getListMode();
|
||||
}
|
||||
|
||||
private static boolean handleRemovedTexParam(int target, int pname, int value) {
|
||||
if (pname == GL14.GL_GENERATE_MIPMAP) {
|
||||
if (target == GL11.GL_TEXTURE_2D) {
|
||||
final TextureInfo info = TextureInfoCache.INSTANCE.getInfo(getBoundTextureForServerState());
|
||||
if (info != null) info.setGenerateMipmap(value != 0);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static void maybeGenerateMipmap(int target, int level) {
|
||||
if (target != GL11.GL_TEXTURE_2D) return;
|
||||
final TextureInfo info = TextureInfoCache.INSTANCE.getInfo(getBoundTextureForServerState());
|
||||
if (info != null && info.isGenerateMipmap() && level == info.getBaseLevel() && level < info.getMaxLevel()) {
|
||||
RENDER_BACKEND.generateMipmap(target);
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean updateTexParameteriCache(int target, int texture, int pname, int param) {
|
||||
if (target != GL11.GL_TEXTURE_2D) {
|
||||
return true;
|
||||
@@ -3759,6 +3783,10 @@ public class GLStateManager {
|
||||
if (info.getWrapT() == param && !shouldBypassCache()) return false;
|
||||
info.setWrapT(param);
|
||||
}
|
||||
case GL12.GL_TEXTURE_BASE_LEVEL -> {
|
||||
if (info.getBaseLevel() == param && !shouldBypassCache()) return false;
|
||||
info.setBaseLevel(param);
|
||||
}
|
||||
case GL12.GL_TEXTURE_MAX_LEVEL -> {
|
||||
if (info.getMaxLevel() == param && !shouldBypassCache()) return false;
|
||||
info.setMaxLevel(param);
|
||||
@@ -3776,6 +3804,7 @@ public class GLStateManager {
|
||||
}
|
||||
|
||||
public static void glTexParameter(int target, int pname, IntBuffer params) {
|
||||
if (handleRemovedTexParam(target, pname, params.remaining() >= 1 ? params.get(params.position()) : 0)) return;
|
||||
if (params.remaining() >= 1) {
|
||||
final int val = params.get(params.position());
|
||||
final int remapped = remapTexClamp(pname, val);
|
||||
@@ -3786,6 +3815,7 @@ public class GLStateManager {
|
||||
}
|
||||
|
||||
public static void glTexParameter(int target, int pname, FloatBuffer params) {
|
||||
if (handleRemovedTexParam(target, pname, params.remaining() >= 1 ? (int) params.get(params.position()) : 0)) return;
|
||||
if (params.remaining() >= 1) {
|
||||
final float val = params.get(params.position());
|
||||
final float remapped = remapTexClamp(pname, val);
|
||||
@@ -3796,6 +3826,7 @@ public class GLStateManager {
|
||||
}
|
||||
|
||||
public static void glTexParameteri(int target, int pname, int param) {
|
||||
if (handleRemovedTexParam(target, pname, param)) return;
|
||||
param = remapTexClamp(pname, param);
|
||||
final RecordMode mode = DisplayListManager.getRecordMode();
|
||||
if (mode != RecordMode.NONE) {
|
||||
@@ -3835,6 +3866,7 @@ public class GLStateManager {
|
||||
}
|
||||
|
||||
public static void glTexParameterf(int target, int pname, float param) {
|
||||
if (handleRemovedTexParam(target, pname, param > 0 ? (int) (param + 0.5f) : (int) (param - 0.5f))) return;
|
||||
param = remapTexClamp(pname, param);
|
||||
final RecordMode mode = DisplayListManager.getRecordMode();
|
||||
if (mode != RecordMode.NONE) {
|
||||
@@ -3867,9 +3899,11 @@ public class GLStateManager {
|
||||
case GL11.GL_TEXTURE_MAG_FILTER -> info.getMagFilter();
|
||||
case GL11.GL_TEXTURE_WRAP_S -> info.getWrapS();
|
||||
case GL11.GL_TEXTURE_WRAP_T -> info.getWrapT();
|
||||
case GL12.GL_TEXTURE_BASE_LEVEL -> info.getBaseLevel();
|
||||
case GL12.GL_TEXTURE_MAX_LEVEL -> info.getMaxLevel();
|
||||
case GL12.GL_TEXTURE_MIN_LOD -> info.getMinLod();
|
||||
case GL12.GL_TEXTURE_MAX_LOD -> info.getMaxLod();
|
||||
case GL14.GL_GENERATE_MIPMAP -> info.isGenerateMipmap() ? GL11.GL_TRUE : GL11.GL_FALSE;
|
||||
default -> {
|
||||
if (isRecordingDisplayList()) {
|
||||
throw new IllegalStateException(String.format(
|
||||
@@ -4531,6 +4565,7 @@ public class GLStateManager {
|
||||
suspendPixelUnpackBuffer();
|
||||
RENDER_BACKEND.texSubImage2D(target, level, xoffset, yoffset, width, height, format, type, pixels);
|
||||
restorePixelUnpackBuffer();
|
||||
maybeGenerateMipmap(target, level);
|
||||
}
|
||||
|
||||
public static void glTexSubImage2D(int target, int level, int xoffset, int yoffset, int width, int height, int format, int type, IntBuffer pixels) {
|
||||
@@ -4544,6 +4579,7 @@ public class GLStateManager {
|
||||
suspendPixelUnpackBuffer();
|
||||
RENDER_BACKEND.texSubImage2D(target, level, xoffset, yoffset, width, height, format, type, pixels);
|
||||
restorePixelUnpackBuffer();
|
||||
maybeGenerateMipmap(target, level);
|
||||
}
|
||||
|
||||
public static void glTexSubImage2D(int target, int level, int xoffset, int yoffset, int width, int height, int format, int type, long pixels_buffer_offset) {
|
||||
@@ -4551,6 +4587,7 @@ public class GLStateManager {
|
||||
throw new UnsupportedOperationException("glTexSubImage2D with buffer offset in display lists not yet supported");
|
||||
}
|
||||
RENDER_BACKEND.texSubImage2D(target, level, xoffset, yoffset, width, height, format, type, pixels_buffer_offset);
|
||||
maybeGenerateMipmap(target, level);
|
||||
}
|
||||
|
||||
public static void glTexSubImage3D(int target, int level, int xoffset, int yoffset, int zoffset, int width, int height, int depth, int format, int type, ByteBuffer pixels) {
|
||||
@@ -4574,6 +4611,7 @@ public class GLStateManager {
|
||||
throw new UnsupportedOperationException("glCopyTexImage2D in display lists not yet implemented - if you see this, please report!");
|
||||
}
|
||||
RENDER_BACKEND.copyTexImage2D(target, level, internalFormat, x, y, width, height, border);
|
||||
maybeGenerateMipmap(target, level);
|
||||
}
|
||||
|
||||
public static void glCopyTexSubImage1D(int target, int level, int xoffset, int x, int y, int width) {
|
||||
@@ -4588,6 +4626,7 @@ public class GLStateManager {
|
||||
throw new UnsupportedOperationException("glCopyTexSubImage2D in display lists not yet implemented - if you see this, please report!");
|
||||
}
|
||||
RENDER_BACKEND.copyTexSubImage2D(target, level, xoffset, yoffset, x, y, width, height);
|
||||
maybeGenerateMipmap(target, level);
|
||||
}
|
||||
|
||||
public static void glCopyTexSubImage3D(int target, int level, int xoffset, int yoffset, int zoffset, int x, int y, int width, int height) {
|
||||
@@ -4633,6 +4672,12 @@ public class GLStateManager {
|
||||
}
|
||||
|
||||
public static void glHint(int target, int hint) {
|
||||
// These hint targets are removed in core profile, ignore them
|
||||
switch (target) {
|
||||
case GL11.GL_PERSPECTIVE_CORRECTION_HINT, GL11.GL_POINT_SMOOTH_HINT, GL11.GL_FOG_HINT, GL14.GL_GENERATE_MIPMAP_HINT -> {
|
||||
return;
|
||||
}
|
||||
}
|
||||
final RecordMode mode = DisplayListManager.getRecordMode();
|
||||
if (mode != RecordMode.NONE) {
|
||||
DisplayListManager.recordHint(target, hint);
|
||||
|
||||
@@ -8,6 +8,8 @@ import java.nio.DoubleBuffer;
|
||||
import java.nio.FloatBuffer;
|
||||
import java.nio.IntBuffer;
|
||||
import java.nio.ShortBuffer;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Abstract rendering backend.
|
||||
@@ -25,6 +27,14 @@ public abstract class RenderBackend {
|
||||
/** Higher priority backends are preferred. */
|
||||
public int getPriority() { return 0; }
|
||||
|
||||
public boolean supportsFileDrop() { return false; }
|
||||
|
||||
public void startFileDrop() {}
|
||||
|
||||
public void stopFileDrop() {}
|
||||
|
||||
public List<String> pollDroppedFiles() { return Collections.emptyList(); }
|
||||
|
||||
public abstract int getMinGLSLVersion();
|
||||
|
||||
public abstract void flush();
|
||||
|
||||
@@ -35,11 +35,30 @@ public final class EcosystemNarrowRules {
|
||||
"com.fiskmods.lightsabers.asm.transformers"
|
||||
)),
|
||||
|
||||
new NarrowRule("FiskHeroes", "com.fiskmods.heroes.asm", List.of(
|
||||
"com.fiskmods.heroes.asm.SHLoadingPlugin",
|
||||
"com.fiskmods.heroes.asm.transformers"
|
||||
)),
|
||||
|
||||
new NarrowRule("Ears", "com.unascribed.ears", List.of(
|
||||
"com.unascribed.ears.asm",
|
||||
"com.unascribed.ears.common.agent"
|
||||
)),
|
||||
|
||||
new NarrowRule("FoamFix", "pl.asie.foamfix", List.of(
|
||||
"pl.asie.foamfix.bugfixmod",
|
||||
"pl.asie.foamfix.coremod",
|
||||
"pl.asie.foamfix.forkage",
|
||||
"pl.asie.foamfix.ghostbuster",
|
||||
"pl.asie.foamfix.FoamFixMod",
|
||||
"pl.asie.foamfix.HackyMessageFactoryWrapper",
|
||||
"pl.asie.foamfix.LaunchWrapperRuntimeFix",
|
||||
"pl.asie.foamfix.ProxyClient",
|
||||
"pl.asie.foamfix.ProxyCommon",
|
||||
"pl.asie.foamfix.repack.com.unascribed.ears.asm",
|
||||
"pl.asie.foamfix.repack.com.unascribed.ears.common.agent"
|
||||
)),
|
||||
|
||||
new NarrowRule("Alfheim", "alfheim.common.core.asm.hook", List.of(
|
||||
"alfheim.common.core.asm.hook.AlfheimFieldHookHandler",
|
||||
"alfheim.common.core.asm.hook.AlfheimHPHooks",
|
||||
|
||||
@@ -17,6 +17,7 @@ public class TextureInfo {
|
||||
@Getter @Setter protected int magFilter = GL11.GL_LINEAR;
|
||||
@Getter @Setter protected int wrapS = GL11.GL_REPEAT;
|
||||
@Getter @Setter protected int wrapT = GL11.GL_REPEAT;
|
||||
@Getter @Setter protected int baseLevel = 0;
|
||||
@Getter @Setter protected int maxLevel = 1000;
|
||||
@Getter @Setter protected int minLod = -1000;
|
||||
@Getter @Setter protected int maxLod = 1000;
|
||||
@@ -24,6 +25,8 @@ public class TextureInfo {
|
||||
|
||||
@Getter @Setter protected float maxAnisotropy = 1.0f;
|
||||
|
||||
@Getter @Setter protected boolean generateMipmap = false;
|
||||
|
||||
protected TextureInfo(int id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
+54
-1
@@ -23,6 +23,9 @@ import org.lwjgl.opengl.GL44C;
|
||||
import org.lwjgl.opengl.GL45C;
|
||||
import org.lwjgl.opengl.GLCapabilities;
|
||||
import org.lwjgl.opengl.GLDebugMessageCallback;
|
||||
import org.lwjgl.sdl.SDL_DropEvent;
|
||||
import org.lwjgl.sdl.SDL_EventFilter;
|
||||
import org.lwjgl.sdl.SDLEvents;
|
||||
import org.lwjgl.system.MemoryStack;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
@@ -31,6 +34,10 @@ import java.nio.FloatBuffer;
|
||||
import java.nio.IntBuffer;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.ShortBuffer;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||
|
||||
/**
|
||||
* LWJGL3 GL implementation of {@link RenderBackend}.
|
||||
@@ -43,6 +50,10 @@ public final class Lwjgl3GLRenderBackend extends RenderBackend {
|
||||
private GLDebugMessageCallback debugCallback;
|
||||
private boolean debugOutputActive;
|
||||
|
||||
private SDL_EventFilter dropEventFilter;
|
||||
private final ConcurrentLinkedQueue<String> droppedFiles = new ConcurrentLinkedQueue<>();
|
||||
private volatile boolean watchingDrops;
|
||||
|
||||
@Override
|
||||
public void init() {
|
||||
caps = GL.getCapabilities();
|
||||
@@ -50,7 +61,49 @@ public final class Lwjgl3GLRenderBackend extends RenderBackend {
|
||||
|
||||
@Override
|
||||
public void shutdown() {
|
||||
// no-op
|
||||
stopFileDrop();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsFileDrop() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startFileDrop() {
|
||||
if (watchingDrops) return;
|
||||
dropEventFilter = SDL_EventFilter.create((userData, eventPtr) -> {
|
||||
if (SDL_DropEvent.ntype(eventPtr) == SDLEvents.SDL_EVENT_DROP_FILE) {
|
||||
final String path = SDL_DropEvent.ndataString(eventPtr);
|
||||
if (path != null && !path.isEmpty()) {
|
||||
droppedFiles.add(path);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
});
|
||||
SDLEvents.SDL_AddEventWatch(dropEventFilter, 0L);
|
||||
watchingDrops = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stopFileDrop() {
|
||||
if (!watchingDrops) return;
|
||||
SDLEvents.SDL_RemoveEventWatch(dropEventFilter, 0L);
|
||||
dropEventFilter.free();
|
||||
dropEventFilter = null;
|
||||
droppedFiles.clear();
|
||||
watchingDrops = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> pollDroppedFiles() {
|
||||
if (droppedFiles.isEmpty()) return Collections.emptyList();
|
||||
final List<String> out = new ArrayList<>();
|
||||
String p;
|
||||
while ((p = droppedFiles.poll()) != null) {
|
||||
out.add(p);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -310,6 +310,16 @@ public class AngelicaConfig {
|
||||
@Config.DefaultBoolean(true)
|
||||
@Config.RequiresMcRestart
|
||||
public boolean narrowEars;
|
||||
|
||||
@Config.Comment("Narrow Fisk's Superheroes transformer exclusions to allow GL redirection")
|
||||
@Config.DefaultBoolean(true)
|
||||
@Config.RequiresMcRestart
|
||||
public boolean narrowFiskHeroes;
|
||||
|
||||
@Config.Comment("Narrow FoamFix transformer exclusions to allow GL redirection in its repackaged Ears")
|
||||
@Config.DefaultBoolean(true)
|
||||
@Config.RequiresMcRestart
|
||||
public boolean narrowFoamFix;
|
||||
}
|
||||
|
||||
@Config.Comment("Renders chunks before neighbors are ready. Improves loading at render distance edges, useful for low render distance servers.")
|
||||
|
||||
@@ -186,6 +186,8 @@ public final class AngelicaClientTweaker implements IFMLLoadingPlugin, IEarlyMix
|
||||
narrowTransformerConfig("AdvancedLightsabers", AngelicaConfig.transformerCompat.narrowAdvancedLightsabers);
|
||||
narrowTransformerConfig("Alfheim", AngelicaConfig.transformerCompat.narrowAlfheim);
|
||||
narrowTransformerConfig("Ears", AngelicaConfig.transformerCompat.narrowEars);
|
||||
narrowTransformerConfig("FiskHeroes", AngelicaConfig.transformerCompat.narrowFiskHeroes);
|
||||
narrowTransformerConfig("FoamFix", AngelicaConfig.transformerCompat.narrowFoamFix);
|
||||
|
||||
tweaks.add("com.gtnewhorizons.angelica.loading.fml.tweakers.IncompatibleModsDisablerTweaker");
|
||||
if (AngelicaConfig.enableHudCaching) {
|
||||
|
||||
+14
@@ -14,6 +14,7 @@ import com.gtnewhorizons.angelica.rendering.celeritas.light.VanillaDiffuseProvid
|
||||
import com.gtnewhorizons.angelica.rendering.celeritas.world.WorldSlice;
|
||||
import lombok.Getter;
|
||||
import net.coderbot.iris.block_rendering.BlockRenderingSettings;
|
||||
import net.coderbot.iris.vertices.ExtendedDataHelper;
|
||||
import net.irisshaders.iris.api.v0.IrisApi;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.multiplayer.WorldClient;
|
||||
@@ -184,6 +185,8 @@ public class AngelicaChunkBuildContext extends ChunkBuildContext {
|
||||
animatedSprites.add(sprite);
|
||||
}
|
||||
|
||||
final boolean isFluid = blockRenderContext.renderType == ExtendedDataHelper.FLUID_RENDER_TYPE;
|
||||
|
||||
// If block used vanilla AO, then we can safely compute our own lighting data and ignore what vanilla
|
||||
// computed. We suppress vanilla emitting the brightness/color in MixinRenderBlocks.
|
||||
// Otherwise, we need to use the block's lightmap values as they are as the ISBRH may have
|
||||
@@ -213,6 +216,17 @@ public class AngelicaChunkBuildContext extends ChunkBuildContext {
|
||||
for (int vIdx = 0; vIdx < 4; vIdx++) {
|
||||
vertices[vIdx].trueNormal = trueNormal;
|
||||
}
|
||||
|
||||
if (useAoCalculation && isFluid) {
|
||||
quadView.setup(trueNormal, blockX, blockY, blockZ);
|
||||
final ModelQuadFacing lightFace = quadView.getLightFace();
|
||||
final LightPipeline pipeline = blockAllowsSmoothLighting ? smoothLightPipeline : flatLightPipeline;
|
||||
final ModelQuadFacing cullFace = quadView.getCullFace();
|
||||
pipeline.calculate(quadView, worldX, worldY, worldZ, quadLightData, cullFace, lightFace, shouldApplyDiffuse, true);
|
||||
for (int vIdx = 0; vIdx < 4; vIdx++) {
|
||||
vertices[vIdx].light = quadLightData.lm[vIdx];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Apply dynamic lights after AO calculation so they're not overwritten
|
||||
|
||||
+1
-1
@@ -269,7 +269,7 @@ public abstract class AngelicaChunkBuilderMeshingTask extends ChunkBuilderTask<C
|
||||
if (contextEncoder != null) {
|
||||
final byte lightValue = (byte) block.getLightValue();
|
||||
if (isFluid) {
|
||||
contextEncoder.prepareToRenderFluid(blockRenderContext, block, lightValue);
|
||||
contextEncoder.prepareToRenderFluid(blockRenderContext, block, metadata, lightValue);
|
||||
} else {
|
||||
int effectiveMeta = metadata;
|
||||
if (BlockRenderingSettings.INSTANCE.hasSnowyEntries()
|
||||
|
||||
+2
@@ -21,6 +21,8 @@ public class AngelicaRenderPassConfiguration {
|
||||
private record AngelicaPipelineState(int pass, boolean disableAlphaTest) implements TerrainRenderPass.PipelineState {
|
||||
@Override
|
||||
public void setup() {
|
||||
GLStateManager.glDepthMask(true);
|
||||
|
||||
if (pass == 0) {
|
||||
GLStateManager.glAlphaFunc(GL11.GL_GREATER, 0.1F);
|
||||
}
|
||||
|
||||
+1
-1
@@ -7,7 +7,7 @@ public interface ContextAwareChunkVertexEncoder extends ChunkVertexEncoder {
|
||||
|
||||
void prepareToRenderBlock(BlockRenderContext ctx, Block block, int metadata, short renderType, byte lightValue);
|
||||
|
||||
void prepareToRenderFluid(BlockRenderContext ctx, Block block, byte lightValue);
|
||||
void prepareToRenderFluid(BlockRenderContext ctx, Block block, int metadata, byte lightValue);
|
||||
|
||||
void finishRenderingBlock();
|
||||
}
|
||||
+29
-3
@@ -12,6 +12,8 @@ import net.coderbot.iris.vertices.ExtendedDataHelper;
|
||||
import net.coderbot.iris.vertices.NormalHelper;
|
||||
import net.coderbot.iris.vertices.NormI8;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.BlockDynamicLiquid;
|
||||
import net.minecraft.block.BlockStaticLiquid;
|
||||
import org.embeddedt.embeddium.impl.render.chunk.terrain.material.Material;
|
||||
import org.embeddedt.embeddium.impl.render.chunk.vertex.format.ChunkVertexEncoder;
|
||||
import org.joml.Vector3f;
|
||||
@@ -59,14 +61,38 @@ public class IrisExtendedChunkVertexEncoder implements ContextAwareChunkVertexEn
|
||||
}
|
||||
|
||||
@Override
|
||||
public void prepareToRenderFluid(BlockRenderContext ctx, Block block, byte lightValue) {
|
||||
public void prepareToRenderFluid(BlockRenderContext ctx, Block block, int metadata, byte lightValue) {
|
||||
this.context = ctx;
|
||||
Int2IntMap metaMap = blockMetaMatches != null ? blockMetaMatches.get(block) : null;
|
||||
ctx.blockId = (short) (metaMap != null ? metaMap.get(0) : -1);
|
||||
ctx.blockId = (short) resolveFluidBlockId(block, metadata);
|
||||
ctx.renderType = ExtendedDataHelper.FLUID_RENDER_TYPE;
|
||||
ctx.lightValue = lightValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Try and prevent material flickering
|
||||
*/
|
||||
private int resolveFluidBlockId(Block block, int metadata) {
|
||||
if (blockMetaMatches == null) return -1;
|
||||
|
||||
int id = lookupFluidMeta(block, metadata);
|
||||
if (id == -1) {
|
||||
final Block counterpart = liquidCounterpart(block);
|
||||
if (counterpart != null) id = lookupFluidMeta(counterpart, metadata);
|
||||
}
|
||||
return id;
|
||||
}
|
||||
|
||||
private int lookupFluidMeta(Block block, int metadata) {
|
||||
final Int2IntMap metaMap = blockMetaMatches.get(block);
|
||||
return metaMap != null ? metaMap.get(metadata) : -1;
|
||||
}
|
||||
|
||||
private static Block liquidCounterpart(Block block) {
|
||||
if (block instanceof BlockStaticLiquid) return Block.getBlockById(Block.getIdFromBlock(block) - 1);
|
||||
if (block instanceof BlockDynamicLiquid) return Block.getBlockById(Block.getIdFromBlock(block) + 1);
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void finishRenderingBlock() {
|
||||
if (context != null) {
|
||||
|
||||
@@ -289,9 +289,6 @@ public abstract class TileOverride implements Comparable<TileOverride> {
|
||||
if (token.isEmpty()) {
|
||||
// nothing
|
||||
} else if (token.contains("/")) {
|
||||
if (!token.endsWith(".png")) {
|
||||
token += ".png";
|
||||
}
|
||||
ResourceLocation resource = TexturePackAPI.parseResourceLocation(properties.getResource(), token);
|
||||
if (resource != null) {
|
||||
list.add(resource.toString());
|
||||
|
||||
@@ -72,7 +72,6 @@ import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.stream.Stream;
|
||||
import java.util.zip.ZipError;
|
||||
import java.util.zip.ZipException;
|
||||
|
||||
public class Iris {
|
||||
@@ -458,6 +457,33 @@ public class Iris {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Toggles shader debug mode. When enabled, patched shader sources are dumped to disk (see
|
||||
* {@link net.coderbot.iris.pipeline.PatchedShaderPrinter}) and logging is more verbose.
|
||||
*/
|
||||
public static void setDebug(boolean enable) {
|
||||
try {
|
||||
irisConfig.setDebugEnabled(enable);
|
||||
irisConfig.save();
|
||||
reload();
|
||||
} catch (IOException e) {
|
||||
logger.error("Failed to " + (enable ? "enable" : "disable") + " debug mode", e);
|
||||
}
|
||||
logger.info("Debug functionality is " + (enable ? "enabled, logging will be more verbose!" : "disabled."));
|
||||
}
|
||||
|
||||
/**
|
||||
* Toggles whether unrecognized shader packs may load, exposing the {@code ALLOWS_UNKNOWN_SHADERS} macro.
|
||||
*/
|
||||
public static void setAllowUnknownShaders(boolean allow) {
|
||||
try {
|
||||
irisConfig.setUnknown(allow);
|
||||
reload();
|
||||
} catch (IOException e) {
|
||||
logger.error("Failed to " + (allow ? "allow" : "disallow") + " unknown shaders", e);
|
||||
}
|
||||
}
|
||||
|
||||
public static void loadShaderpack() {
|
||||
if (irisConfig == null) {
|
||||
if (!initialized) {
|
||||
@@ -678,8 +704,7 @@ public class Iris {
|
||||
try (Stream<Path> stream = Files.walk(root)) {
|
||||
return stream.filter(Files::isDirectory).anyMatch(path -> path.endsWith("shaders"));
|
||||
}
|
||||
} catch (ZipError zipError) {
|
||||
// Java 8 seems to throw a ZipError instead of a subclass of IOException
|
||||
} catch (ZipException e) {
|
||||
Iris.logger.warn("The ZIP at " + pack + " is corrupt");
|
||||
} catch (IOException ignored) {
|
||||
// ignored, not a valid shader pack.
|
||||
|
||||
@@ -38,6 +38,8 @@ public class IrisConfig {
|
||||
*/
|
||||
private boolean enableDebugOptions;
|
||||
|
||||
private boolean allowUnknownShaders;
|
||||
|
||||
private final Path propertiesPath;
|
||||
|
||||
public IrisConfig(Path propertiesPath) {
|
||||
@@ -45,6 +47,7 @@ public class IrisConfig {
|
||||
enableShaders = true;
|
||||
disableUpdateMessage = false;
|
||||
enableDebugOptions = false;
|
||||
allowUnknownShaders = false;
|
||||
this.propertiesPath = propertiesPath;
|
||||
}
|
||||
|
||||
@@ -113,6 +116,25 @@ public class IrisConfig {
|
||||
return enableDebugOptions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether debug features are enabled.
|
||||
*/
|
||||
public void setDebugEnabled(boolean enabled) {
|
||||
this.enableDebugOptions = enabled;
|
||||
}
|
||||
|
||||
public boolean shouldAllowUnknownShaders() {
|
||||
return allowUnknownShaders;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether unrecognized shader packs may load.
|
||||
*/
|
||||
public void setUnknown(boolean allow) throws IOException {
|
||||
this.allowUnknownShaders = allow;
|
||||
save();
|
||||
}
|
||||
|
||||
/**
|
||||
* loads the config file and then populates the string, int, and boolean entries with the parsed entries
|
||||
*
|
||||
@@ -132,6 +154,7 @@ public class IrisConfig {
|
||||
shaderPackName = properties.getProperty("shaderPack");
|
||||
enableShaders = !"false".equals(properties.getProperty("enableShaders"));
|
||||
enableDebugOptions = "true".equals(properties.getProperty("enableDebugOptions"));
|
||||
allowUnknownShaders = "true".equals(properties.getProperty("allowUnknownShaders"));
|
||||
disableUpdateMessage = "true".equals(properties.getProperty("disableUpdateMessage"));
|
||||
// TODO: GUI
|
||||
try {
|
||||
@@ -159,6 +182,7 @@ public class IrisConfig {
|
||||
properties.setProperty("shaderPack", getShaderPackName().orElse(""));
|
||||
properties.setProperty("enableShaders", enableShaders ? "true" : "false");
|
||||
properties.setProperty("enableDebugOptions", enableDebugOptions ? "true" : "false");
|
||||
properties.setProperty("allowUnknownShaders", allowUnknownShaders ? "true" : "false");
|
||||
properties.setProperty("disableUpdateMessage", disableUpdateMessage ? "true" : "false");
|
||||
properties.setProperty("maxShadowRenderDistance", String.valueOf(IrisVideoSettings.shadowDistance));
|
||||
// NB: This uses ISO-8859-1 with unicode escapes as the encoding
|
||||
|
||||
@@ -4,6 +4,7 @@ import com.google.common.collect.ImmutableList;
|
||||
import com.gtnewhorizons.angelica.Tags;
|
||||
import com.gtnewhorizons.angelica.config.AngelicaConfig;
|
||||
import cpw.mods.fml.common.Loader;
|
||||
import net.coderbot.iris.Iris;
|
||||
import net.coderbot.iris.compat.dh.DHCompat;
|
||||
import net.coderbot.iris.parsing.BiomeCategories;
|
||||
import net.coderbot.iris.pipeline.HandRenderer;
|
||||
@@ -91,6 +92,10 @@ public class StandardMacros {
|
||||
define(standardDefines, "DISTANT_HORIZONS");
|
||||
}
|
||||
|
||||
if (Iris.getIrisConfig().shouldAllowUnknownShaders()) {
|
||||
define(standardDefines, "ALLOWS_UNKNOWN_SHADERS");
|
||||
}
|
||||
|
||||
define(standardDefines, "DH_BLOCK_UNKNOWN", String.valueOf(0));
|
||||
define(standardDefines, "DH_BLOCK_LEAVES", String.valueOf(1));
|
||||
define(standardDefines, "DH_BLOCK_STONE", String.valueOf(2));
|
||||
|
||||
@@ -4,10 +4,13 @@ import com.gtnewhorizons.angelica.glsm.GLStateManager;
|
||||
import cpw.mods.fml.client.config.GuiUtils;
|
||||
import lombok.Getter;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.audio.PositionedSoundRecord;
|
||||
import net.minecraft.client.gui.FontRenderer;
|
||||
import net.minecraft.client.gui.Gui;
|
||||
import net.minecraft.client.gui.ScaledResolution;
|
||||
import net.minecraft.client.resources.I18n;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
|
||||
/**
|
||||
* Class serving as abstraction and
|
||||
@@ -111,6 +114,32 @@ public final class GuiUtil {
|
||||
font.drawStringWithShadow(text, x + 4, y + 4, 0xFFFFFF);
|
||||
}
|
||||
|
||||
public static void drawScrollingText(FontRenderer font, String text, int centerX, int minX, int maxX, int minY, int maxY, int color) {
|
||||
final int textWidth = font.getStringWidth(text);
|
||||
final int boxWidth = maxX - minX;
|
||||
final int textY = ((minY + maxY) - font.FONT_HEIGHT) / 2 + 1;
|
||||
|
||||
if (textWidth > boxWidth) {
|
||||
final int overflow = textWidth - boxWidth;
|
||||
final double time = System.currentTimeMillis() / 1000.0;
|
||||
final double period = Math.max(overflow * 0.5, 3.0);
|
||||
final double t = (Math.sin((Math.PI / 2.0) * Math.cos((Math.PI * 2.0) * time / period)) / 2.0) + 0.5;
|
||||
final int scroll = (int) (t * overflow);
|
||||
|
||||
final Minecraft mc = client();
|
||||
final int scale = new ScaledResolution(mc, mc.displayWidth, mc.displayHeight).getScaleFactor();
|
||||
GLStateManager.glEnable(GL11.GL_SCISSOR_TEST);
|
||||
GLStateManager.glScissor(minX * scale, mc.displayHeight - (maxY * scale), boxWidth * scale, (maxY - minY) * scale);
|
||||
font.drawStringWithShadow(text, minX - scroll, textY, color);
|
||||
GLStateManager.glDisable(GL11.GL_SCISSOR_TEST);
|
||||
} else {
|
||||
int textX = centerX - (textWidth / 2);
|
||||
textX = Math.min(textX, maxX - textWidth);
|
||||
textX = Math.max(textX, minX);
|
||||
font.drawStringWithShadow(text, textX, textY, color);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Shorten a text to a specific length, adding an ellipsis (...)
|
||||
* to the end if shortened.
|
||||
@@ -140,13 +169,25 @@ public final class GuiUtil {
|
||||
* @return the translated text if found, otherwise the default provided
|
||||
*/
|
||||
public static String translateOrDefault(String defaultText, String translationDesc, Object ... format) {
|
||||
final String translated = I18n.format(translationDesc, format);
|
||||
final String translated = format.length == 0
|
||||
? translateLenient(translationDesc)
|
||||
: I18n.format(translationDesc, format);
|
||||
if(!translated.equals(translationDesc)) {
|
||||
return translated;
|
||||
}
|
||||
return defaultText;
|
||||
}
|
||||
|
||||
private static final String FORMAT_ERROR_PREFIX = "Format error: ";
|
||||
|
||||
/**
|
||||
* Nasty dirty hack, but it works.
|
||||
*/
|
||||
public static String translateLenient(String key) {
|
||||
final String translated = I18n.format(key);
|
||||
return translated.startsWith(FORMAT_ERROR_PREFIX) ? translated.substring(FORMAT_ERROR_PREFIX.length()) : translated;
|
||||
}
|
||||
|
||||
/**
|
||||
* Plays the {@code UI_BUTTON_CLICK} sound event as a
|
||||
* master sound effect.
|
||||
@@ -155,7 +196,7 @@ public final class GuiUtil {
|
||||
* or other action.
|
||||
*/
|
||||
public static void playButtonClickSound() {
|
||||
// client().getSoundManager().play(SimpleSoundInstance.forUI(SoundEvents.UI_BUTTON_CLICK, 1));
|
||||
client().getSoundHandler().playSound(PositionedSoundRecord.func_147674_a(new ResourceLocation("gui.button.press"), 1.0F));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -21,7 +21,9 @@ public class IrisElementRow {
|
||||
private final int spacing;
|
||||
private int x;
|
||||
private int y;
|
||||
private int width;
|
||||
|
||||
@Getter
|
||||
private int width;
|
||||
private int height;
|
||||
|
||||
public IrisElementRow(int spacing) {
|
||||
|
||||
@@ -19,7 +19,7 @@ public abstract class IrisGuiSlot extends GuiSlot {
|
||||
super(mc, width, height, top, bottom, slotHeight);
|
||||
// Set Center Vertically to false
|
||||
this.field_148163_i = false;
|
||||
|
||||
this.headerPadding = 2;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -37,11 +37,15 @@ public abstract class IrisGuiSlot extends GuiSlot {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void drawSelectionBox(int x, int y, int mouseX, int mouseY) {
|
||||
final int oldPadding = this.headerPadding;
|
||||
this.headerPadding = 2;
|
||||
super.drawSelectionBox(x, y, mouseX, mouseY);
|
||||
this.headerPadding = oldPadding;
|
||||
public int func_148124_c/*getSlotIndexFromScreenCoords*/(int x, int y) {
|
||||
final int left = this.left + this.width / 2 - this.getListWidth() / 2 + hitLeftInset() + hitXShift();
|
||||
final int right = this.left + this.width / 2 + this.getListWidth() / 2 - hitRightInset() + hitXShift();
|
||||
final int relativeY = y - this.top + (int) this.amountScrolled - hitYOffset();
|
||||
final int index = relativeY / this.slotHeight;
|
||||
if (y <= this.top || y >= this.bottom) {
|
||||
return -1;
|
||||
}
|
||||
return x < this.getScrollBarX() && x >= left && x <= right && index >= 0 && relativeY >= 0 && index < this.getSize() ? index : -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -53,6 +57,23 @@ public abstract class IrisGuiSlot extends GuiSlot {
|
||||
return false;
|
||||
}
|
||||
|
||||
protected int hitYOffset() {
|
||||
return 4;
|
||||
}
|
||||
|
||||
protected int hitRightInset() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
protected int hitLeftInset() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
protected int hitXShift() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
public boolean mouseClicked(int mouseX, int mouseY, int mouseButton) {
|
||||
if (!this.func_148125_i/*enabled*/()) {
|
||||
return false;
|
||||
@@ -60,15 +81,15 @@ public abstract class IrisGuiSlot extends GuiSlot {
|
||||
final int size = this.getSize();
|
||||
final int scrollBarX = this.getScrollBarX();
|
||||
final int rightEdge = scrollBarX + 6;
|
||||
final int elementLeft = this.width / 2 - this.getListWidth() / 2;
|
||||
final int elementRight = this.width / 2 + this.getListWidth() / 2;
|
||||
final int relativeY = mouseY - this.top - this.headerPadding + (int) this.amountScrolled - 4;
|
||||
final int elementLeft = this.width / 2 - this.getListWidth() / 2 + hitLeftInset() + hitXShift();
|
||||
final int elementRight = this.width / 2 + this.getListWidth() / 2 - hitRightInset() + hitXShift();
|
||||
final int relativeY = mouseY - this.top + (int) this.amountScrolled - hitYOffset();
|
||||
boolean handled = false;
|
||||
final boolean leftMouseDown = Mouse.isButtonDown(0);
|
||||
final boolean rightMouseDown = Mouse.isButtonDown(1);
|
||||
|
||||
if (mouseX <= this.left || mouseX >= this.right || mouseY <= this.top || mouseY >= this.bottom) {
|
||||
return handled;
|
||||
return false;
|
||||
}
|
||||
if (leftMouseDown && mouseX >= scrollBarX && mouseX <= rightEdge) {
|
||||
scrolling = true;
|
||||
|
||||
@@ -25,7 +25,7 @@ public class ShaderPackOptionList extends IrisGuiSlot {
|
||||
private final List<BaseEntry> entries = new ArrayList<>();
|
||||
|
||||
public ShaderPackOptionList(ShaderPackScreen screen, NavigationController navigation, ShaderPack pack, Minecraft client, int width, int height, int top, int bottom, int left, int right) {
|
||||
super(client, width, height, top, bottom, 20);
|
||||
super(client, width, height, top, bottom, 24);
|
||||
this.navigation = navigation;
|
||||
this.screen = screen;
|
||||
|
||||
@@ -72,7 +72,7 @@ public class ShaderPackOptionList extends IrisGuiSlot {
|
||||
}
|
||||
}
|
||||
|
||||
if (row.size() > 0) {
|
||||
if (!row.isEmpty()) {
|
||||
while (row.size() < columns) {
|
||||
row.add(AbstractElementWidget.EMPTY);
|
||||
}
|
||||
@@ -93,7 +93,12 @@ public class ShaderPackOptionList extends IrisGuiSlot {
|
||||
}
|
||||
@Override
|
||||
public boolean mouseReleased( int mouseX, int mouseY, int button) {
|
||||
final int relativeY = mouseY - this.top - this.headerPadding + (int) this.amountScrolled - 4;
|
||||
this.scrolling = false;
|
||||
if (mouseY <= this.top || mouseY >= this.bottom) {
|
||||
return false;
|
||||
}
|
||||
|
||||
final int relativeY = mouseY - this.top + (int) this.amountScrolled - hitYOffset();
|
||||
final int index = relativeY / this.slotHeight;
|
||||
|
||||
if (index < 0 || index >= this.entries.size())
|
||||
@@ -113,11 +118,31 @@ public class ShaderPackOptionList extends IrisGuiSlot {
|
||||
// noop
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int hitYOffset() {
|
||||
return 3;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int hitRightInset() {
|
||||
return 4;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int hitLeftInset() {
|
||||
return -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int hitXShift() {
|
||||
return 2;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void drawSlot(int index, int x, int y, int i1, Tessellator tessellator, int mouseX, int mouseY) {
|
||||
final BaseEntry entry = this.entries.get(index);
|
||||
final boolean isMouseOver = this.func_148124_c/*getSlotIndexFromScreenCoords*/(mouseX, mouseY) == index;
|
||||
entry.drawEntry(screen, index, x - 2, y + 4, this.getListWidth(), this.slotHeight, tessellator, mouseX, mouseY, isMouseOver);
|
||||
entry.drawEntry(screen, index, x, y - 2, this.getListWidth(), this.slotHeight, tessellator, mouseX, mouseY, isMouseOver);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -4,13 +4,23 @@ import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import net.coderbot.iris.Iris;
|
||||
import net.coderbot.iris.gui.element.shaderselection.BaseEntry;
|
||||
import net.coderbot.iris.gui.element.shaderselection.DownloadEntry;
|
||||
import net.coderbot.iris.gui.element.shaderselection.LabelEntry;
|
||||
import net.coderbot.iris.gui.element.shaderselection.ShaderPackEntry;
|
||||
import net.coderbot.iris.gui.element.shaderselection.TopButtonRowEntry;
|
||||
import net.coderbot.iris.gui.screen.ShaderPackScreen;
|
||||
import com.gtnewhorizons.angelica.glsm.backend.BackendManager;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.renderer.Tessellator;
|
||||
import net.minecraft.client.resources.I18n;
|
||||
import net.minecraft.util.EnumChatFormatting;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.FileSystems;
|
||||
import java.nio.file.StandardWatchEventKinds;
|
||||
import java.nio.file.WatchEvent;
|
||||
import java.nio.file.WatchKey;
|
||||
import java.nio.file.WatchService;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
@@ -31,15 +41,70 @@ public class ShaderPackSelectionList extends IrisGuiSlot {
|
||||
|
||||
private final List<BaseEntry> entries = new ArrayList<>();
|
||||
|
||||
private final WatchService watcher;
|
||||
private final WatchKey key;
|
||||
private boolean keyValid;
|
||||
|
||||
public ShaderPackSelectionList(ShaderPackScreen screen, Minecraft client, int width, int height, int top, int bottom, int left, int right) {
|
||||
super(client, width, height, top, bottom, 20);
|
||||
|
||||
this.screen = screen;
|
||||
this.topButtonRow = new TopButtonRowEntry(this, Iris.getIrisConfig().areShadersEnabled());
|
||||
|
||||
WatchService watcher1;
|
||||
WatchKey key1;
|
||||
try {
|
||||
watcher1 = FileSystems.getDefault().newWatchService();
|
||||
key1 = Iris.getShaderpacksDirectory().register(watcher1,
|
||||
StandardWatchEventKinds.ENTRY_CREATE,
|
||||
StandardWatchEventKinds.ENTRY_MODIFY,
|
||||
StandardWatchEventKinds.ENTRY_DELETE);
|
||||
keyValid = true;
|
||||
} catch (IOException e) {
|
||||
Iris.logger.error("Couldn't register shaderpacks directory file watcher!", e);
|
||||
watcher1 = null;
|
||||
key1 = null;
|
||||
keyValid = false;
|
||||
}
|
||||
this.watcher = watcher1;
|
||||
this.key = key1;
|
||||
|
||||
refresh();
|
||||
}
|
||||
|
||||
// Poll for new shaderpacks
|
||||
public void poll() {
|
||||
if (!keyValid) {
|
||||
return;
|
||||
}
|
||||
boolean changed = false;
|
||||
for (WatchEvent<?> event : key.pollEvents()) {
|
||||
if (event.kind() == StandardWatchEventKinds.OVERFLOW) {
|
||||
continue;
|
||||
}
|
||||
changed = true;
|
||||
}
|
||||
if (changed) {
|
||||
refresh();
|
||||
}
|
||||
keyValid = key.reset();
|
||||
}
|
||||
|
||||
public void close() throws IOException {
|
||||
if (key != null) {
|
||||
key.cancel();
|
||||
}
|
||||
if (watcher != null) {
|
||||
watcher.close();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawScreen(int mouseX, int mouseY, float partialTicks) {
|
||||
poll();
|
||||
super.drawScreen(mouseX, mouseY, partialTicks);
|
||||
}
|
||||
|
||||
public void refresh() {
|
||||
this.entries.clear();
|
||||
|
||||
@@ -68,8 +133,13 @@ public class ShaderPackSelectionList extends IrisGuiSlot {
|
||||
|
||||
this.entries.add(topButtonRow);
|
||||
|
||||
// Download something man
|
||||
if (names.isEmpty()) {
|
||||
this.entries.add(new DownloadEntry(this, "Download Shaders", "https://modrinth.com/shaders"));
|
||||
}
|
||||
|
||||
// Only allow the enable/disable shaders button if the user has added a shader pack. Otherwise, the button will be disabled.
|
||||
topButtonRow.allowEnableShadersButton = names.size() > 0;
|
||||
topButtonRow.allowEnableShadersButton = !names.isEmpty();
|
||||
|
||||
int index = 0;
|
||||
|
||||
@@ -78,6 +148,11 @@ public class ShaderPackSelectionList extends IrisGuiSlot {
|
||||
addPackEntry(index, name);
|
||||
}
|
||||
|
||||
// Try not to gaslight users in case they swap back and forth from lwjgl2 and lwjgl3
|
||||
final String footerKey = BackendManager.RENDER_BACKEND.supportsFileDrop()
|
||||
? "pack.iris.list.label"
|
||||
: "pack.iris.list.label.lwjgl2";
|
||||
addLabelEntries(EnumChatFormatting.GRAY.toString() + EnumChatFormatting.ITALIC + I18n.format(footerKey));
|
||||
}
|
||||
|
||||
public void addPackEntry(int index, String name) {
|
||||
@@ -128,6 +203,8 @@ public class ShaderPackSelectionList extends IrisGuiSlot {
|
||||
return true;
|
||||
} else if( entry instanceof TopButtonRowEntry topButtonRowEntry) {
|
||||
return topButtonRowEntry.mouseClicked(mouseX, mouseY, 0);
|
||||
} else if (entry instanceof DownloadEntry downloadEntry) {
|
||||
return downloadEntry.click(this.screen);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -152,7 +229,7 @@ public class ShaderPackSelectionList extends IrisGuiSlot {
|
||||
protected void drawSlot(int index, int x, int y, int i1, Tessellator tessellator, int mouseX, int mouseY) {
|
||||
final BaseEntry entry = this.entries.get(index);
|
||||
final boolean isMouseOver = this.func_148124_c/*getSlotIndexFromScreenCoords*/(mouseX, mouseY) == index;
|
||||
entry.drawEntry(screen, index, x - 2, y + 4, this.getListWidth(), tessellator, mouseX, mouseY, isMouseOver);
|
||||
entry.drawEntry(screen, index, x, y + 4, this.getListWidth(), tessellator, mouseX, mouseY, isMouseOver);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -14,6 +14,7 @@ public class ElementRowEntry extends BaseEntry {
|
||||
|
||||
private int cachedWidth;
|
||||
private int cachedPosX;
|
||||
private float cachedSingleWidth;
|
||||
|
||||
public ElementRowEntry(NavigationController navigation, List<AbstractElementWidget<?>> widgets) {
|
||||
super(navigation);
|
||||
@@ -32,25 +33,43 @@ public class ElementRowEntry extends BaseEntry {
|
||||
|
||||
// Width of a single widget
|
||||
final float singleWidgetWidth = (float) totalWidthWithoutMargins / widgets.size();
|
||||
this.cachedSingleWidth = singleWidgetWidth;
|
||||
|
||||
for (int i = 0; i < widgets.size(); i++) {
|
||||
final AbstractElementWidget<?> widget = widgets.get(i);
|
||||
final boolean widgetHovered = isMouseOver && (getHoveredWidget(mouseX) == i);
|
||||
widget.drawScreen(x + (int) ((singleWidgetWidth + 2) * i), y, (int) singleWidgetWidth, slotHeight + 2, mouseX, mouseY, 0, widgetHovered);
|
||||
widget.drawScreen(x + (int) ((singleWidgetWidth + 2) * i), y, (int) singleWidgetWidth, slotHeight - 2, mouseX, mouseY, 0, widgetHovered);
|
||||
|
||||
screen.setElementHoveredStatus(widget, widgetHovered);
|
||||
}
|
||||
}
|
||||
|
||||
public int getHoveredWidget(int mouseX) {
|
||||
final float positionAcrossWidget = ((float) MathHelper.clamp_int(mouseX - cachedPosX, 0, cachedWidth)) / cachedWidth;
|
||||
|
||||
final float CONTENT_ANCHOR_OFFSET = 2f;
|
||||
final float rel = (mouseX - cachedPosX) + CONTENT_ANCHOR_OFFSET;
|
||||
final float clamped = Math.clamp(rel, 0f, cachedWidth);
|
||||
final float positionAcrossWidget = clamped / cachedWidth;
|
||||
|
||||
return MathHelper.clamp_int((int) Math.floor(widgets.size() * positionAcrossWidget), 0, widgets.size() - 1);
|
||||
}
|
||||
|
||||
private int widgetAt(int mouseX) {
|
||||
final int i = getHoveredWidget(mouseX);
|
||||
final int widgetX = this.cachedPosX + (int) ((this.cachedSingleWidth + 2) * i);
|
||||
if (mouseX < widgetX || mouseX >= widgetX + (int) this.cachedSingleWidth) {
|
||||
return -1;
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean mouseClicked(int mouseX, int mouseY, int button) {
|
||||
return this.widgets.get(getHoveredWidget(mouseX)).mouseClicked(mouseX, mouseY, button);
|
||||
final int i = widgetAt(mouseX);
|
||||
if (i < 0) {
|
||||
return false;
|
||||
}
|
||||
return this.widgets.get(i).mouseClicked(mouseX, mouseY, button);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -7,6 +7,7 @@ import net.coderbot.iris.gui.element.IrisElementRow;
|
||||
import net.coderbot.iris.gui.screen.ShaderPackScreen;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.gui.FontRenderer;
|
||||
import net.minecraft.client.gui.Gui;
|
||||
import net.minecraft.client.gui.GuiScreen;
|
||||
import net.minecraft.client.renderer.Tessellator;
|
||||
import net.minecraft.client.resources.I18n;
|
||||
@@ -60,13 +61,12 @@ public class HeaderEntry extends BaseEntry {
|
||||
|
||||
@Override
|
||||
public void drawEntry(ShaderPackScreen screen, int index, int x, int y, int slotWidth, int slotHeight, Tessellator tessellator, int mouseX, int mouseY, boolean isMouseOver) {
|
||||
// Draw dividing line
|
||||
// fill(x - 3, (y + slotHeight) - 2, x + slotWidth, (y + slotHeight) - 1, 0x66BEBEBE);
|
||||
Gui.drawRect(x - 3, (y + slotHeight) - 3, x + slotWidth, (y + slotHeight) - 2, 0x66BEBEBE);
|
||||
final int tickDelta = 0;
|
||||
final FontRenderer font = Minecraft.getMinecraft().fontRenderer;
|
||||
|
||||
// Draw header text
|
||||
this.screen.drawCenteredString(font, text, x + (int) (slotWidth * 0.5), y + 5, 0xFFFFFF);
|
||||
GuiUtil.drawScrollingText(font, text, x + (int) (slotWidth * 0.5), x + 5,
|
||||
((x + slotWidth) - 10) - this.utilityButtons.getWidth(), y + 5, y + 15, 0xFFFFFF);
|
||||
|
||||
GuiUtil.bindIrisWidgetsTexture();
|
||||
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
package net.coderbot.iris.gui.element.shaderselection;
|
||||
|
||||
import net.coderbot.iris.gui.GuiUtil;
|
||||
import net.coderbot.iris.gui.element.ShaderPackSelectionList;
|
||||
import net.coderbot.iris.gui.screen.ShaderPackScreen;
|
||||
import net.minecraft.client.renderer.Tessellator;
|
||||
|
||||
/**
|
||||
* Show a download button when no shaderpacks exist in the shaderpacks folder.
|
||||
*/
|
||||
public class DownloadEntry extends BaseEntry {
|
||||
private final String label;
|
||||
private final String url;
|
||||
|
||||
public DownloadEntry(ShaderPackSelectionList list, String label, String url) {
|
||||
super(list);
|
||||
this.label = label;
|
||||
this.url = url;
|
||||
}
|
||||
|
||||
public boolean click(ShaderPackScreen screen) {
|
||||
GuiUtil.playButtonClickSound();
|
||||
screen.openLinkConfirm(url);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawEntry(ShaderPackScreen screen, int index, int x, int y, int listWidth, Tessellator tessellator, int mouseX, int mouseY, boolean isMouseOver) {
|
||||
GuiUtil.bindIrisWidgetsTexture();
|
||||
GuiUtil.drawButton(x - 2, y - 5, listWidth, 18, isMouseOver, false);
|
||||
screen.drawCenteredString(label, (x + listWidth / 2) - 2, y, 0xFFFFFF);
|
||||
}
|
||||
}
|
||||
@@ -14,6 +14,6 @@ public class LabelEntry extends BaseEntry {
|
||||
|
||||
@Override
|
||||
public void drawEntry(ShaderPackScreen screen, int index, int x, int y, int listWidth, Tessellator tessellator, int mouseX, int mouseY, boolean isMouseOver) {
|
||||
screen.drawCenteredString(label, x, y, 0xFFFFFF);
|
||||
screen.drawCenteredString(label, (x + listWidth / 2) - 2, y, 0xFFFFFF);
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
package net.coderbot.iris.gui.element.shaderselection;
|
||||
|
||||
import lombok.Getter;
|
||||
import net.coderbot.iris.gui.GuiUtil;
|
||||
import net.coderbot.iris.gui.element.ShaderPackSelectionList;
|
||||
import net.coderbot.iris.gui.screen.ShaderPackScreen;
|
||||
import net.minecraft.client.gui.FontRenderer;
|
||||
@@ -37,6 +38,8 @@ public class ShaderPackEntry extends BaseEntry {
|
||||
}
|
||||
|
||||
if(isMouseOver) {
|
||||
GuiUtil.bindIrisWidgetsTexture();
|
||||
GuiUtil.drawButton(x - 2, y - 6, listWidth, 20, true, false);
|
||||
name = EnumChatFormatting.BOLD + name;
|
||||
}
|
||||
|
||||
|
||||
@@ -13,12 +13,10 @@ public class TopButtonRowEntry extends BaseEntry {
|
||||
private static final String NONE_PRESENT_LABEL = I18n.format("options.iris.shaders.nonePresent"); //.withStyle(ChatFormatting.GRAY);
|
||||
private static final String SHADERS_DISABLED_LABEL = I18n.format("options.iris.shaders.disabled");
|
||||
private static final String SHADERS_ENABLED_LABEL = I18n.format("options.iris.shaders.enabled");
|
||||
private static final int REFRESH_BUTTON_WIDTH = 18;
|
||||
|
||||
private final ShaderPackSelectionList shaderPackSelectionList;
|
||||
private final IrisElementRow buttons = new IrisElementRow();
|
||||
private final EnableShadersButtonElement enableDisableButton;
|
||||
private final IrisElementRow.Element refreshPacksButton;
|
||||
|
||||
public boolean allowEnableShadersButton = true;
|
||||
public boolean shadersEnabled;
|
||||
@@ -38,15 +36,7 @@ public class TopButtonRowEntry extends BaseEntry {
|
||||
|
||||
return false;
|
||||
});
|
||||
this.refreshPacksButton = new IrisElementRow.IconButtonElement(
|
||||
GuiUtil.Icon.REFRESH,
|
||||
button -> {
|
||||
this.shaderPackSelectionList.refresh();
|
||||
|
||||
GuiUtil.playButtonClickSound();
|
||||
return true;
|
||||
});
|
||||
this.buttons.add(this.enableDisableButton, 0).add(this.refreshPacksButton, REFRESH_BUTTON_WIDTH);
|
||||
this.buttons.add(this.enableDisableButton, 0);
|
||||
}
|
||||
|
||||
public void setShadersEnabled(boolean shadersEnabled) {
|
||||
@@ -57,7 +47,7 @@ public class TopButtonRowEntry extends BaseEntry {
|
||||
|
||||
@Override
|
||||
public void drawEntry(ShaderPackScreen screen, int index, int x, int y, int listWidth, Tessellator tessellator, int mouseX, int mouseY, boolean isMouseOver) {
|
||||
this.buttons.setWidth(this.enableDisableButton, (listWidth - 1) - REFRESH_BUTTON_WIDTH);
|
||||
this.buttons.setWidth(this.enableDisableButton, listWidth);
|
||||
this.enableDisableButton.centerX = x + (int)(listWidth * 0.5);
|
||||
|
||||
this.buttons.drawScreen(x - 2, y - 3, 18, mouseX, mouseY, 0, isMouseOver);
|
||||
|
||||
@@ -90,9 +90,9 @@ public abstract class BaseOptionElementWidget<T extends OptionMenuElement> exten
|
||||
FontRenderer font = Minecraft.getMinecraft().fontRenderer;
|
||||
|
||||
// Draw the label
|
||||
font.drawStringWithShadow(this.trimmedLabel, x + 6, y + 7, 0xFFFFFF);
|
||||
font.drawStringWithShadow(this.trimmedLabel, x + 6, y + 7, this.isValueModified() ? 0xFFC94A : 0xFFFFFF);
|
||||
// Draw the value label
|
||||
font.drawStringWithShadow(this.valueLabel, (x + (width - 2)) - (int)(this.valueSectionWidth * 0.5) - (int)(font.getStringWidth(this.valueLabel) * 0.5), y + 7, 0xFFFFFF);
|
||||
font.drawStringWithShadow(this.valueLabel, (x + (width - 2)) - (int)(this.valueSectionWidth * 0.5) - (int)(font.getStringWidth(this.valueLabel) * 0.5), y + 7, getValueColor());
|
||||
}
|
||||
|
||||
protected final void renderOptionWithValue(int x, int y, int width, int height, boolean hovered) {
|
||||
@@ -119,17 +119,15 @@ public abstract class BaseOptionElementWidget<T extends OptionMenuElement> exten
|
||||
}
|
||||
|
||||
protected final String createTrimmedLabel() {
|
||||
String label = GuiUtil.shortenText(Minecraft.getMinecraft().fontRenderer, this.label, this.maxLabelWidth);
|
||||
|
||||
if (this.isValueModified()) {
|
||||
label = label + " (*)"; //.withStyle(style -> style.withColor(TextColor.fromRgb(0xffc94a)));
|
||||
}
|
||||
|
||||
return label;
|
||||
return GuiUtil.shortenText(Minecraft.getMinecraft().fontRenderer, this.label, this.maxLabelWidth);
|
||||
}
|
||||
|
||||
protected abstract String createValueLabel();
|
||||
|
||||
protected int getValueColor() {
|
||||
return 0xFFFFFF;
|
||||
}
|
||||
|
||||
public abstract boolean applyNextValue();
|
||||
|
||||
public abstract boolean applyPreviousValue();
|
||||
@@ -147,7 +145,13 @@ public abstract class BaseOptionElementWidget<T extends OptionMenuElement> exten
|
||||
|
||||
@Override
|
||||
public Optional<String> getCommentBody() {
|
||||
return Optional.ofNullable(getCommentKey()).map(I18n::format);
|
||||
final String key = getCommentKey();
|
||||
if (key == null) {
|
||||
return Optional.empty();
|
||||
}
|
||||
final String translated = GuiUtil.translateLenient(key);
|
||||
// Don't show comment boxes without a translation, otherwise you get something like option.{commentname}.comment
|
||||
return translated.equals(key) ? Optional.empty() : Optional.of(translated);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -70,6 +70,14 @@ public class BooleanElementWidget extends BaseOptionElementWidget<OptionMenuBool
|
||||
return this.value ? TEXT_TRUE : TEXT_FALSE;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getValueColor() {
|
||||
if (this.value == this.defaultValue) {
|
||||
return 0xFFFFFF;
|
||||
}
|
||||
return this.value ? 0x55FF55 : 0xFF5555;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCommentKey() {
|
||||
return "option." + this.option.getName() + ".comment";
|
||||
|
||||
@@ -6,13 +6,10 @@ import net.coderbot.iris.gui.screen.ShaderPackScreen;
|
||||
import net.coderbot.iris.shaderpack.option.menu.OptionMenuLinkElement;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.gui.FontRenderer;
|
||||
import net.minecraft.client.resources.I18n;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
public class LinkElementWidget extends CommentedElementWidget<OptionMenuLinkElement> {
|
||||
private static final String ARROW = new String(">");
|
||||
|
||||
private final String targetScreenId;
|
||||
private final String label;
|
||||
|
||||
@@ -39,7 +36,7 @@ public class LinkElementWidget extends CommentedElementWidget<OptionMenuLinkElem
|
||||
|
||||
final FontRenderer font = Minecraft.getMinecraft().fontRenderer;
|
||||
|
||||
final int maxLabelWidth = width - 9;
|
||||
final int maxLabelWidth = width - 6;
|
||||
|
||||
if (font.getStringWidth(this.label) > maxLabelWidth) {
|
||||
this.isLabelTrimmed = true;
|
||||
@@ -51,8 +48,7 @@ public class LinkElementWidget extends CommentedElementWidget<OptionMenuLinkElem
|
||||
|
||||
int labelWidth = font.getStringWidth(this.trimmedLabel);
|
||||
|
||||
font.drawStringWithShadow(this.trimmedLabel, x + (int)(width * 0.5) - (int)(labelWidth * 0.5) - (int)(0.5 * Math.max(labelWidth - (width - 18), 0)), y + 7, 0xFFFFFF);
|
||||
font.drawString(ARROW, (x + width) - 9, y + 7, 0xFFFFFF);
|
||||
font.drawStringWithShadow(this.trimmedLabel, x + (int)(width * 0.5) - (int)(labelWidth * 0.5), y + 7, 0xFFFFFF);
|
||||
|
||||
if (hovered && this.isLabelTrimmed) {
|
||||
// To prevent other elements from being drawn on top of the tooltip
|
||||
@@ -79,7 +75,7 @@ public class LinkElementWidget extends CommentedElementWidget<OptionMenuLinkElem
|
||||
@Override
|
||||
public Optional<String> getCommentBody() {
|
||||
final String translation = "screen." + this.targetScreenId + ".comment";
|
||||
final String translated = I18n.format(translation);
|
||||
return Optional.ofNullable(!translated.equals(translation) ? I18n.format(translation) : null);
|
||||
final String translated = GuiUtil.translateLenient(translation);
|
||||
return Optional.ofNullable(!translated.equals(translation) ? translated : null);
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
package net.coderbot.iris.gui.element.widget;
|
||||
|
||||
import net.coderbot.iris.Iris;
|
||||
import net.minecraft.util.EnumChatFormatting;
|
||||
import net.coderbot.iris.gui.GuiUtil;
|
||||
import net.coderbot.iris.gui.NavigationController;
|
||||
import net.coderbot.iris.gui.element.ShaderPackOptionList;
|
||||
@@ -64,7 +65,7 @@ public final class OptionMenuConstructor {
|
||||
|
||||
static {
|
||||
registerScreen(OptionMenuMainElementScreen.class, screen ->
|
||||
new ElementWidgetScreenData(Iris.getCurrentPackName() + (Iris.isFallback() ? " (fallback)" : ""), false));
|
||||
new ElementWidgetScreenData(EnumChatFormatting.BOLD + Iris.getCurrentPackName() + (Iris.isFallback() ? " (fallback)" : ""), false));
|
||||
|
||||
registerScreen(OptionMenuSubElementScreen.class, screen ->
|
||||
new ElementWidgetScreenData(GuiUtil.translateOrDefault(new String(screen.screenId), "screen." + screen.screenId), true));
|
||||
|
||||
@@ -59,6 +59,11 @@ public class ProfileElementWidget extends BaseOptionElementWidget<OptionMenuProf
|
||||
return this.profileLabel;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getValueColor() {
|
||||
return PROFILE_CUSTOM.equals(this.profileLabel) ? 0xFFFF55 : 0xFFFFFF;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<String> getCommentTitle() {
|
||||
return Optional.of(PROFILE_LABEL);
|
||||
|
||||
@@ -108,7 +108,7 @@ public class SliderElementWidget extends StringElementWidget {
|
||||
|
||||
@Override
|
||||
public boolean mouseReleased(double mx, double my, int button) {
|
||||
if (button == 0) {
|
||||
if (button == 0 && this.mouseDown) {
|
||||
this.onReleased();
|
||||
|
||||
return true;
|
||||
|
||||
@@ -60,6 +60,11 @@ public class StringElementWidget extends BaseOptionElementWidget<OptionMenuStrin
|
||||
return GuiUtil.translateOrDefault(getValue(), "value." + this.option.getName() + "." + getValue());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getValueColor() {
|
||||
return 0x6688FF;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCommentKey() {
|
||||
return "option." + this.option.getName() + ".comment";
|
||||
|
||||
@@ -2,6 +2,7 @@ package net.coderbot.iris.gui.screen;
|
||||
|
||||
import com.gtnewhorizons.angelica.AngelicaMod;
|
||||
import com.gtnewhorizons.angelica.glsm.GLStateManager;
|
||||
import com.gtnewhorizons.angelica.glsm.backend.BackendManager;
|
||||
import net.coderbot.iris.Iris;
|
||||
import net.coderbot.iris.gui.GuiUtil;
|
||||
import net.coderbot.iris.gui.NavigationController;
|
||||
@@ -16,8 +17,12 @@ import net.coderbot.iris.shaderpack.ShaderPack;
|
||||
import net.irisshaders.iris.api.v0.IrisApi;
|
||||
import net.minecraft.client.gui.FontRenderer;
|
||||
import net.minecraft.client.gui.GuiButton;
|
||||
import net.minecraft.client.gui.GuiConfirmOpenLink;
|
||||
import net.minecraft.client.gui.GuiScreen;
|
||||
import net.minecraft.client.gui.GuiYesNo;
|
||||
import net.minecraft.client.resources.I18n;
|
||||
import net.minecraft.util.EnumChatFormatting;
|
||||
import net.minecraft.util.Util;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.lwjgl.Sys;
|
||||
import org.lwjgl.input.Keyboard;
|
||||
@@ -25,12 +30,19 @@ import org.lwjgl.input.Mouse;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.nio.file.FileAlreadyExistsException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.Properties;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.stream.Collectors;
|
||||
@@ -41,8 +53,8 @@ public class ShaderPackScreen extends GuiScreen implements HudHideable {
|
||||
*/
|
||||
public static final Set<Runnable> TOP_LAYER_RENDER_QUEUE = new HashSet<>();
|
||||
|
||||
private static final String SELECT_TITLE = I18n.format("pack.iris.select.title");
|
||||
private static final String CONFIGURE_TITLE = I18n.format("pack.iris.configure.title");
|
||||
private static final String SELECT_TITLE = EnumChatFormatting.GRAY.toString() + EnumChatFormatting.ITALIC + I18n.format("pack.iris.select.title");
|
||||
private static final String CONFIGURE_TITLE = EnumChatFormatting.GRAY.toString() + EnumChatFormatting.ITALIC + I18n.format("pack.iris.configure.title");
|
||||
private static final int COMMENT_PANEL_WIDTH = 314;
|
||||
|
||||
private final GuiScreen parent;
|
||||
@@ -72,7 +84,6 @@ public class ShaderPackScreen extends GuiScreen implements HudHideable {
|
||||
|
||||
private boolean guiHidden = false;
|
||||
private boolean dirty = false;
|
||||
private float guiButtonHoverTimer = 0.0f;
|
||||
|
||||
public ShaderPackScreen(GuiScreen parent) {
|
||||
this.title = I18n.format("options.iris.shaderPackSelection.title");
|
||||
@@ -102,6 +113,8 @@ public class ShaderPackScreen extends GuiScreen implements HudHideable {
|
||||
this.initGui();
|
||||
}
|
||||
|
||||
handleDroppedFiles();
|
||||
|
||||
if (this.mc.theWorld == null) {
|
||||
super.drawDefaultBackground();
|
||||
} else if (!this.guiHidden) {
|
||||
@@ -122,11 +135,7 @@ public class ShaderPackScreen extends GuiScreen implements HudHideable {
|
||||
hoveredElementCommentTimer = 0;
|
||||
}
|
||||
|
||||
final float previousHoverTimer = this.guiButtonHoverTimer;
|
||||
super.drawScreen(mouseX, mouseY, delta);
|
||||
if (previousHoverTimer == this.guiButtonHoverTimer) {
|
||||
this.guiButtonHoverTimer = 0.0f;
|
||||
}
|
||||
|
||||
if (!this.guiHidden) {
|
||||
drawCenteredString(this.fontRendererObj, this.title, (int) (this.width * 0.5), 8, 0xFFFFFF);
|
||||
@@ -143,12 +152,9 @@ public class ShaderPackScreen extends GuiScreen implements HudHideable {
|
||||
|
||||
// Draw the comment panel
|
||||
if (this.isDisplayingComment()) {
|
||||
// Determine panel height and position
|
||||
final int panelHeight = Math.max(50, 18 + (this.hoveredElementCommentBody.size() * 10));
|
||||
int x = mouseX + 5;
|
||||
if (x + 314 >= (this.width - 4)) x = this.width - (318);
|
||||
int y = mouseY + 8;
|
||||
if (y + panelHeight >= (this.height - 4)) y = this.height - (panelHeight + 4);
|
||||
final int x = (int) (0.5 * this.width) - 157;
|
||||
final int y = this.height - (panelHeight + 4);
|
||||
// Draw panel
|
||||
GuiUtil.drawPanel(x, y, COMMENT_PANEL_WIDTH, panelHeight);
|
||||
// Draw text
|
||||
@@ -181,10 +187,21 @@ public class ShaderPackScreen extends GuiScreen implements HudHideable {
|
||||
@Override
|
||||
public void initGui() {
|
||||
super.initGui();
|
||||
|
||||
BackendManager.RENDER_BACKEND.startFileDrop();
|
||||
|
||||
final int bottomCenter = this.width / 2 - 50;
|
||||
final int topCenter = this.width / 2 - 76;
|
||||
final boolean inWorld = this.mc.theWorld != null;
|
||||
|
||||
if (this.shaderPackList != null) {
|
||||
try {
|
||||
this.shaderPackList.close();
|
||||
} catch (IOException e) {
|
||||
Iris.logger.error("Failed to close previous shaderpack selection watcher!", e);
|
||||
}
|
||||
}
|
||||
|
||||
this.shaderPackList = new ShaderPackSelectionList(this, this.mc, this.width, this.height, 32, this.height - 58, 0, this.width);
|
||||
|
||||
if (Iris.getCurrentPack().isPresent() && this.navigation != null) {
|
||||
@@ -339,12 +356,30 @@ public class ShaderPackScreen extends GuiScreen implements HudHideable {
|
||||
public void refreshScreenSwitchButton() {
|
||||
if (this.screenSwitchButton != null) {
|
||||
this.screenSwitchButton.displayString = optionMenuOpen ? I18n.format("options.iris.shaderPackList") : I18n.format("options.iris.shaderPackSettings");
|
||||
this.screenSwitchButton.enabled = optionMenuOpen || shaderPackList.getTopButtonRow().shadersEnabled;
|
||||
// Disable the settings switch when shaders are off or the selected pack exposes no options
|
||||
this.screenSwitchButton.enabled = optionMenuOpen || (shaderPackList.getTopButtonRow().shadersEnabled
|
||||
&& Iris.getCurrentPack().map(p -> !p.getMenuContainer().mainScreen.elements.isEmpty()).orElse(true));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void keyTyped(char typedChar, int keyCode) {
|
||||
if (GuiScreen.isCtrlKeyDown() && keyCode == Keyboard.KEY_D) {
|
||||
this.mc.displayGuiScreen(new GuiYesNo((result, id) -> {
|
||||
Iris.setDebug(result);
|
||||
this.mc.displayGuiScreen(this);
|
||||
}, "Shader debug mode toggle",
|
||||
"Debug mode helps investigate problems and shows shader errors. Would you like to enable it?", 0));
|
||||
return;
|
||||
}
|
||||
if (GuiScreen.isCtrlKeyDown() && keyCode == Keyboard.KEY_G) {
|
||||
this.mc.displayGuiScreen(new GuiYesNo((result, id) -> {
|
||||
Iris.setAllowUnknownShaders(result);
|
||||
this.mc.displayGuiScreen(this);
|
||||
}, "Unknown shader toggle",
|
||||
"This allows unknown shaders to load in.", 0));
|
||||
return;
|
||||
}
|
||||
if (keyCode == Keyboard.KEY_ESCAPE) {
|
||||
if (this.guiHidden) {
|
||||
this.guiHidden = false;
|
||||
@@ -359,6 +394,21 @@ public class ShaderPackScreen extends GuiScreen implements HudHideable {
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (keyCode == Keyboard.KEY_F1 && this.mc.theWorld != null) {
|
||||
this.guiHidden = !this.guiHidden;
|
||||
this.initGui();
|
||||
return;
|
||||
}
|
||||
if (keyCode == Keyboard.KEY_TAB) {
|
||||
final boolean canOpenOptions = shaderPackList.getTopButtonRow().shadersEnabled
|
||||
&& Iris.getCurrentPack().map(p -> !p.getMenuContainer().mainScreen.elements.isEmpty()).orElse(false);
|
||||
if (this.optionMenuOpen || canOpenOptions) {
|
||||
this.optionMenuOpen = !this.optionMenuOpen;
|
||||
this.applyChanges();
|
||||
this.initGui();
|
||||
}
|
||||
return;
|
||||
}
|
||||
super.keyTyped(typedChar, keyCode);
|
||||
}
|
||||
|
||||
@@ -367,6 +417,84 @@ public class ShaderPackScreen extends GuiScreen implements HudHideable {
|
||||
this.notificationDialogTimer = 100;
|
||||
}
|
||||
|
||||
private void handleDroppedFiles() {
|
||||
final List<String> dropped = BackendManager.RENDER_BACKEND.pollDroppedFiles();
|
||||
if (dropped.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
final List<Path> paths = dropped.stream().map(Paths::get).collect(Collectors.toList());
|
||||
if (this.optionMenuOpen) {
|
||||
onOptionMenuFilesDrop(paths);
|
||||
} else {
|
||||
onPackListFilesDrop(paths);
|
||||
}
|
||||
}
|
||||
|
||||
public void onPackListFilesDrop(List<Path> paths) {
|
||||
final List<Path> packs = paths.stream().filter(Iris::isValidShaderpack).toList();
|
||||
|
||||
for (Path pack : packs) {
|
||||
final String fileName = pack.getFileName().toString();
|
||||
try {
|
||||
Iris.getShaderpacksDirectoryManager().copyPackIntoDirectory(fileName, pack);
|
||||
} catch (FileAlreadyExistsException e) {
|
||||
displayNotification(I18n.format("options.iris.shaderPackSelection.copyErrorAlreadyExists", fileName));
|
||||
this.shaderPackList.refresh();
|
||||
return;
|
||||
} catch (IOException e) {
|
||||
Iris.logger.warn("Error copying dragged shader pack", e);
|
||||
displayNotification(I18n.format("options.iris.shaderPackSelection.copyError", fileName));
|
||||
this.shaderPackList.refresh();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// After copying, refresh the list so the new packs show up
|
||||
this.shaderPackList.refresh();
|
||||
|
||||
if (packs.isEmpty()) {
|
||||
if (paths.size() == 1) {
|
||||
displayNotification(I18n.format("options.iris.shaderPackSelection.failedAddSingle", paths.getFirst().getFileName().toString()));
|
||||
} else {
|
||||
displayNotification(I18n.format("options.iris.shaderPackSelection.failedAdd"));
|
||||
}
|
||||
} else if (packs.size() == 1) {
|
||||
final String packName = packs.getFirst().getFileName().toString();
|
||||
displayNotification(I18n.format("options.iris.shaderPackSelection.addedPack", packName));
|
||||
// Select the freshly-added pack, since the user probably wants to use it
|
||||
this.shaderPackList.select(packName);
|
||||
} else {
|
||||
displayNotification(I18n.format("options.iris.shaderPackSelection.addedPacks", packs.size()));
|
||||
}
|
||||
}
|
||||
|
||||
public void onOptionMenuFilesDrop(List<Path> paths) {
|
||||
// Only one settings file should be imported at a time
|
||||
if (paths.size() != 1) {
|
||||
displayNotification(I18n.format("options.iris.shaderPackOptions.tooManyFiles"));
|
||||
return;
|
||||
}
|
||||
importPackOptions(paths.getFirst());
|
||||
}
|
||||
|
||||
public void importPackOptions(Path settingFile) {
|
||||
try (InputStream in = Files.newInputStream(settingFile)) {
|
||||
final Properties properties = new Properties();
|
||||
properties.load(in);
|
||||
|
||||
Iris.queueShaderPackOptionsFromProperties(properties);
|
||||
|
||||
displayNotification(I18n.format("options.iris.shaderPackOptions.importedSettings", settingFile.getFileName().toString()));
|
||||
|
||||
if (this.navigation != null) {
|
||||
this.navigation.refresh();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Iris.logger.error("Error importing shader settings file \"" + settingFile + "\"", e);
|
||||
displayNotification(I18n.format("options.iris.shaderPackOptions.failedImport", settingFile.getFileName().toString()));
|
||||
}
|
||||
}
|
||||
|
||||
public void onClose() {
|
||||
if (!dropChanges) {
|
||||
applyChanges();
|
||||
@@ -377,6 +505,19 @@ public class ShaderPackScreen extends GuiScreen implements HudHideable {
|
||||
this.mc.displayGuiScreen(parent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onGuiClosed() {
|
||||
BackendManager.RENDER_BACKEND.stopFileDrop();
|
||||
|
||||
if (this.shaderPackList != null) {
|
||||
try {
|
||||
this.shaderPackList.close();
|
||||
} catch (IOException e) {
|
||||
Iris.logger.error("Failed to safely close shaderpack selection!", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void dropChangesAndClose() {
|
||||
dropChanges = true;
|
||||
onClose();
|
||||
@@ -419,8 +560,29 @@ public class ShaderPackScreen extends GuiScreen implements HudHideable {
|
||||
CompletableFuture.runAsync(() -> openUri(Iris.getShaderpacksDirectoryManager().getDirectoryUri()));
|
||||
}
|
||||
|
||||
public void openLinkConfirm(String url) {
|
||||
this.mc.displayGuiScreen(new GuiConfirmOpenLink((result, id) -> {
|
||||
if (result) {
|
||||
try {
|
||||
openUri(new URI(url));
|
||||
} catch (URISyntaxException e) {
|
||||
Iris.logger.error("Invalid shader download URL: " + url, e);
|
||||
}
|
||||
}
|
||||
this.mc.displayGuiScreen(this);
|
||||
}, url, 0, true) {
|
||||
@Override
|
||||
public void initGui() {
|
||||
super.initGui();
|
||||
for (int i = 0; i < this.buttonList.size(); i++) {
|
||||
this.buttonList.get(i).xPosition = this.width / 2 - 155 + i * 105;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void openUri(URI uri) {
|
||||
switch (net.minecraft.util.Util.getOSType()) {
|
||||
switch (Util.getOSType()) {
|
||||
case OSX -> {
|
||||
try {
|
||||
Runtime.getRuntime().exec(new String[] { "/usr/bin/open", uri.toString() });
|
||||
@@ -452,7 +614,7 @@ public class ShaderPackScreen extends GuiScreen implements HudHideable {
|
||||
|
||||
try {
|
||||
final Class<?> aClass = Class.forName("java.awt.Desktop");
|
||||
final Object getDesktop = aClass.getMethod("getDesktop").invoke((Object) null);
|
||||
final Object getDesktop = aClass.getMethod("getDesktop").invoke(null);
|
||||
aClass.getMethod("browse", URI.class).invoke(getDesktop, uri);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
@@ -475,17 +637,17 @@ public class ShaderPackScreen extends GuiScreen implements HudHideable {
|
||||
this.hoveredElementCommentTitle = ((CommentedElementWidget<?>) widget).getCommentTitle();
|
||||
|
||||
Optional<String> commentBody = ((CommentedElementWidget<?>) widget).getCommentBody();
|
||||
if (!commentBody.isPresent()) {
|
||||
if (commentBody.isEmpty()) {
|
||||
this.hoveredElementCommentBody.clear();
|
||||
} else {
|
||||
String rawCommentBody = commentBody.get();
|
||||
|
||||
// Strip any trailing "."s
|
||||
// Strip any trailing periods
|
||||
if (rawCommentBody.endsWith(".")) {
|
||||
rawCommentBody = rawCommentBody.substring(0, rawCommentBody.length() - 1);
|
||||
}
|
||||
// Split comment body into lines by separator ". "
|
||||
List<String> splitByPeriods = Arrays.stream(rawCommentBody.split("\\. [ ]*")).map(String::new).collect(Collectors.toList());
|
||||
List<String> splitByPeriods = Arrays.stream(rawCommentBody.split("\\. +")).toList();
|
||||
// Line wrap
|
||||
this.hoveredElementCommentBody = new ArrayList<>();
|
||||
for (String text : splitByPeriods) {
|
||||
|
||||
@@ -1597,6 +1597,11 @@ public class DeferredWorldRenderingPipeline implements WorldRenderingPipeline, R
|
||||
|
||||
this.customUniforms.update();
|
||||
|
||||
// Make sure SSBO is bound
|
||||
if (ssboHolder != null) {
|
||||
ssboHolder.setupBuffers();
|
||||
}
|
||||
|
||||
// Get ready for world rendering
|
||||
prepareRenderTargets();
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package net.coderbot.iris.rendertarget;
|
||||
|
||||
import com.gtnewhorizons.angelica.compat.mojang.NativeImage;
|
||||
import com.gtnewhorizons.angelica.glsm.GLStateManager;
|
||||
import com.gtnewhorizons.angelica.glsm.RenderSystem;
|
||||
import net.minecraft.client.renderer.texture.DynamicTexture;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
|
||||
@@ -10,6 +10,11 @@ import java.util.Random;
|
||||
public class NativeImageBackedNoiseTexture extends DynamicTexture {
|
||||
public NativeImageBackedNoiseTexture(int size) {
|
||||
super(create(size));
|
||||
|
||||
RenderSystem.texParameteri(getGlTextureId(), GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_LINEAR);
|
||||
RenderSystem.texParameteri(getGlTextureId(), GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, GL11.GL_LINEAR);
|
||||
RenderSystem.texParameteri(getGlTextureId(), GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_S, GL11.GL_REPEAT);
|
||||
RenderSystem.texParameteri(getGlTextureId(), GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_T, GL11.GL_REPEAT);
|
||||
}
|
||||
|
||||
private static NativeImage create(int size) {
|
||||
@@ -27,11 +32,4 @@ public class NativeImageBackedNoiseTexture extends DynamicTexture {
|
||||
return image;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateDynamicTexture() {
|
||||
GLStateManager.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_LINEAR);
|
||||
GLStateManager.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, GL11.GL_LINEAR);
|
||||
super.updateDynamicTexture();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package net.coderbot.iris.shaderpack;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class DimensionFlatteningMap {
|
||||
private static final Map<String, String> MODERN_TO_LEGACY = new HashMap<>();
|
||||
|
||||
static {
|
||||
MODERN_TO_LEGACY.put("minecraft:overworld", "Overworld");
|
||||
MODERN_TO_LEGACY.put("minecraft:the_nether", "Nether");
|
||||
MODERN_TO_LEGACY.put("minecraft:the_end", "The End");
|
||||
}
|
||||
|
||||
/**
|
||||
* Maps a modern dimension ID to its 1.7.10 string name.
|
||||
*/
|
||||
public static String toLegacyName(String dimensionName) {
|
||||
return MODERN_TO_LEGACY.getOrDefault(dimensionName, dimensionName);
|
||||
}
|
||||
}
|
||||
@@ -10,6 +10,7 @@ import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
import java.util.Set;
|
||||
@@ -33,7 +34,7 @@ public class LanguageMap {
|
||||
stream.filter(path -> !Files.isDirectory(path)).forEach(path -> {
|
||||
// Also note that OptiFine uses a property scheme for loading language entries to keep parity with other
|
||||
// OptiFine features
|
||||
final String currentFileName = path.getFileName().toString();
|
||||
final String currentFileName = path.getFileName().toString().toLowerCase(Locale.ROOT);
|
||||
|
||||
if (!currentFileName.endsWith(".lang")) {
|
||||
// This file lacks a .lang file extension and should be ignored.
|
||||
|
||||
@@ -23,14 +23,12 @@ import net.coderbot.iris.shaderpack.option.ShaderPackOptions;
|
||||
import net.coderbot.iris.shaderpack.option.menu.OptionMenuContainer;
|
||||
import net.coderbot.iris.shaderpack.option.values.MutableOptionValues;
|
||||
import net.coderbot.iris.shaderpack.option.values.OptionValues;
|
||||
import net.coderbot.iris.shaderpack.parsing.BooleanParser;
|
||||
import net.coderbot.iris.shaderpack.preprocessor.JcppProcessor;
|
||||
import net.coderbot.iris.shaderpack.preprocessor.PropertiesPreprocessor;
|
||||
import net.coderbot.iris.shaderpack.texture.CustomTextureData;
|
||||
import net.coderbot.iris.shaderpack.texture.TextureFilteringData;
|
||||
import net.coderbot.iris.shaderpack.texture.TextureStage;
|
||||
import net.coderbot.iris.uniforms.custom.CustomUniforms;
|
||||
import net.irisshaders.iris.api.v0.IrisApi;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
@@ -242,12 +240,8 @@ public class ShaderPack {
|
||||
List<String> invalidFeatureFlags = invalidFlagList.stream().map(FeatureFlags::getHumanReadableName).collect(Collectors.toList());
|
||||
|
||||
if (!invalidFeatureFlags.isEmpty()) {
|
||||
// TODO: GUI
|
||||
// if (Minecraft.getMinecraft().screen instanceof ShaderPackScreen) {
|
||||
// Minecraft.getMinecraft().setScreen(new FeatureMissingErrorScreen(Minecraft.getMinecraft().screen, I18n.format("iris.unsupported.pack"), I18n.format("iris.unsupported.pack.description", FeatureFlags.getInvalidStatus(invalidFlagList), invalidFeatureFlags.stream()
|
||||
// .collect(Collectors.joining(", ", ": ", ".")))));
|
||||
// }
|
||||
IrisApi.getInstance().getConfig().setShadersEnabledAndApply(false);
|
||||
// TODO: GUI?
|
||||
Iris.logger.warn("Shader pack requires unsupported feature flags, loading anyway: {}", String.join(", ", invalidFeatureFlags));
|
||||
}
|
||||
|
||||
ProfileSet profiles = ProfileSet.fromTree(shaderProperties.getProfiles(), this.shaderPackOptions.getOptionSet());
|
||||
@@ -258,9 +252,7 @@ public class ShaderPack {
|
||||
this.profile.current.ifPresent(profile -> disabledPrograms.addAll(profile.disabledPrograms));
|
||||
// Add programs that are disabled by shader options
|
||||
shaderProperties.getConditionallyEnabledPrograms().forEach((program, shaderOption) -> {
|
||||
if ("true".equals(shaderOption)) return;
|
||||
|
||||
if ("false".equals(shaderOption) || !this.shaderPackOptions.getOptionValues().getBooleanValueOrDefault(shaderOption)) {
|
||||
if (!BooleanParser.parse(shaderOption, this.shaderPackOptions.getOptionValues())) {
|
||||
disabledPrograms.add(program);
|
||||
}
|
||||
});
|
||||
@@ -438,7 +430,8 @@ public class ShaderPack {
|
||||
folderNames.add(folderName);
|
||||
|
||||
for (String dimensionName : dimensionNames) {
|
||||
dimensionMap.put(dimensionName, folderName);
|
||||
// Convert modern dimension IDs to 1.7.10 names
|
||||
dimensionMap.put(DimensionFlatteningMap.toLegacyName(dimensionName), folderName);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -668,6 +661,7 @@ public class ShaderPack {
|
||||
*/
|
||||
public ProgramSet getProgramSet(String dimensionName) {
|
||||
int dimensionId = Iris.getCurrentDimensionId();
|
||||
dimensionName = DimensionFlatteningMap.toLegacyName(dimensionName);
|
||||
|
||||
// First, try to find an exact match in the dimension map
|
||||
String folderName = dimensionMap.get(dimensionName);
|
||||
|
||||
@@ -383,8 +383,11 @@ public class FlatteningMap {
|
||||
doublePlant("peony", 5);
|
||||
|
||||
// === Water / Lava (IDs 8-11) ===
|
||||
// In 1.13+, water/lava are single blocks. In 1.7.10, flowing variants are separate.
|
||||
// Map modern names to both still and flowing for full coverage.
|
||||
// In 1.13+, water/lava are single blocks. In 1.7.10, flowing variants are separate.
|
||||
// Map modern names to both still and flowing for full coverage. See IrisExtendedChunkVertexEncoder.java
|
||||
// for more info on this.
|
||||
liquidLevels("water", "water", "flowing_water");
|
||||
liquidLevels("lava", "lava", "flowing_lava");
|
||||
multi("water",
|
||||
entry("water"),
|
||||
entry("flowing_water"));
|
||||
@@ -972,6 +975,13 @@ public class FlatteningMap {
|
||||
STATE_MAPPINGS.put(modern + "|" + property + "=" + value, List.of(entries));
|
||||
}
|
||||
|
||||
/** Maps each modern liquid level state to that exact metadata on both the static and flowing IDs */
|
||||
private static void liquidLevels(String modern, String legacyStatic, String legacyDynamic) {
|
||||
for (int level = 0; level <= 15; level++) {
|
||||
state(modern, "level", String.valueOf(level), entryMetas(legacyStatic, level), entryMetas(legacyDynamic, level));
|
||||
}
|
||||
}
|
||||
|
||||
/** Creates a BlockEntry with no specific metas. */
|
||||
private static BlockEntry entry(String legacyName) {
|
||||
return new BlockEntry(new NamespacedId("minecraft", legacyName), Collections.emptySet());
|
||||
|
||||
@@ -11,6 +11,9 @@ public interface OptionValues {
|
||||
Optional<String> getStringValue(String name);
|
||||
|
||||
default boolean getBooleanValueOrDefault(String name) {
|
||||
if ("0".equals(name)) return false;
|
||||
if ("1".equals(name)) return true;
|
||||
|
||||
return getBooleanValue(name).orElseGet(() -> {
|
||||
if (!getOptionSet().getBooleanOptions().containsKey(name)) {
|
||||
Iris.logger.warn("Tried to get boolean value for unknown option: " + name + ", defaulting to true!");
|
||||
|
||||
@@ -0,0 +1,124 @@
|
||||
package net.coderbot.iris.shaderpack.parsing;
|
||||
|
||||
import net.coderbot.iris.Iris;
|
||||
import net.coderbot.iris.shaderpack.option.values.OptionValues;
|
||||
|
||||
import java.util.EmptyStackException;
|
||||
import java.util.Stack;
|
||||
|
||||
public class BooleanParser {
|
||||
public static boolean parse(String expression, OptionValues valueLookup) {
|
||||
try {
|
||||
StringBuilder option = new StringBuilder();
|
||||
Stack<Operation> operationStack = new Stack<>();
|
||||
Stack<Boolean> valueStack = new Stack<>();
|
||||
for (int i = 0; i < expression.length(); i++) {
|
||||
char c = expression.charAt(i);
|
||||
switch (c) {
|
||||
case '!' -> operationStack.push(Operation.NOT);
|
||||
case '&' -> {
|
||||
if (!option.isEmpty()) {
|
||||
valueStack.push(processValue(option.toString(), valueLookup, operationStack));
|
||||
option = new StringBuilder();
|
||||
}
|
||||
if (operationStack.isEmpty() || !operationStack.peek().equals(Operation.AND)) {
|
||||
operationStack.push(Operation.OPEN);
|
||||
}
|
||||
i++;
|
||||
operationStack.push(Operation.AND);
|
||||
}
|
||||
case '|' -> {
|
||||
if (!option.isEmpty()) {
|
||||
valueStack.push(processValue(option.toString(), valueLookup, operationStack));
|
||||
option = new StringBuilder();
|
||||
}
|
||||
if (!operationStack.isEmpty() && operationStack.peek().equals(Operation.AND)) {
|
||||
evaluate(operationStack, valueStack, true);
|
||||
}
|
||||
i++;
|
||||
operationStack.push(Operation.OR);
|
||||
}
|
||||
case '(' -> operationStack.push(Operation.OPEN);
|
||||
case ')' -> {
|
||||
if (!option.isEmpty()) {
|
||||
valueStack.push(processValue(option.toString(), valueLookup, operationStack));
|
||||
option = new StringBuilder();
|
||||
}
|
||||
if (!operationStack.isEmpty() && operationStack.peek().equals(Operation.AND)) {
|
||||
evaluate(operationStack, valueStack, true);
|
||||
}
|
||||
evaluate(operationStack, valueStack, true);
|
||||
}
|
||||
case ' ' -> {}
|
||||
default -> option.append(c);
|
||||
}
|
||||
}
|
||||
if (!option.isEmpty()) {
|
||||
valueStack.push(processValue(option.toString(), valueLookup, operationStack));
|
||||
}
|
||||
evaluate(operationStack, valueStack, false);
|
||||
boolean result = valueStack.pop();
|
||||
if (!valueStack.isEmpty() || !operationStack.isEmpty()) {
|
||||
Iris.logger.warn("Failed to parse boolean expression, stack isn't empty, defaulting to true: '{}'", expression);
|
||||
return true;
|
||||
}
|
||||
return result;
|
||||
} catch (EmptyStackException e) {
|
||||
Iris.logger.warn("Failed to parse boolean expression, stack is empty unexpectedly, defaulting to true: '{}'", expression);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean processValue(String value, OptionValues valueLookup, Stack<Operation> operationStack) {
|
||||
boolean booleanValue = switch (value) {
|
||||
case "true", "1" -> true;
|
||||
case "false", "0" -> false;
|
||||
default -> valueLookup != null && valueLookup.getBooleanValueOrDefault(value);
|
||||
};
|
||||
if (!operationStack.isEmpty() && operationStack.peek() == Operation.NOT) {
|
||||
operationStack.pop();
|
||||
return !booleanValue;
|
||||
}
|
||||
return booleanValue;
|
||||
}
|
||||
|
||||
private static void evaluate(Stack<Operation> operationStack, Stack<Boolean> valueStack, boolean currentBracket) {
|
||||
boolean value = valueStack.pop();
|
||||
while (!operationStack.isEmpty() && (!currentBracket || operationStack.peek() != Operation.OPEN)) {
|
||||
value = operationStack.pop().compute(value, valueStack);
|
||||
}
|
||||
if (!operationStack.isEmpty() && operationStack.peek() == Operation.OPEN) {
|
||||
operationStack.pop();
|
||||
if (!operationStack.isEmpty() && operationStack.peek() == Operation.NOT) {
|
||||
value = operationStack.pop().compute(value, valueStack);
|
||||
}
|
||||
}
|
||||
valueStack.push(value);
|
||||
}
|
||||
|
||||
private enum Operation {
|
||||
AND {
|
||||
@Override
|
||||
boolean compute(boolean value, Stack<Boolean> valueStack) {
|
||||
return valueStack.pop() && value;
|
||||
}
|
||||
},
|
||||
OR {
|
||||
@Override
|
||||
boolean compute(boolean value, Stack<Boolean> valueStack) {
|
||||
return valueStack.pop() || value;
|
||||
}
|
||||
},
|
||||
NOT {
|
||||
@Override
|
||||
boolean compute(boolean value, Stack<Boolean> valueStack) {
|
||||
return !value;
|
||||
}
|
||||
},
|
||||
OPEN;
|
||||
|
||||
boolean compute(boolean value, Stack<Boolean> valueStack) {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -116,6 +116,7 @@ public final class CommonUniforms {
|
||||
final SmoothedVec2f eyeBrightnessSmooth = new SmoothedVec2f(directives.getEyeBrightnessHalfLife(), directives.getEyeBrightnessHalfLife(), CommonUniforms::getEyeBrightness, updateNotifier);
|
||||
|
||||
uniforms
|
||||
.uniform1f(ONCE, "pi", () -> (float) Math.PI)
|
||||
.uniform1f(ONCE, "darknessFactor", () -> 0.0F) // This is PER_FRAME in modern, it is an effect added by The Warden. We're just setting to 0 because 1.7.10 doesn't have it.
|
||||
.uniform1f(ONCE, "darknessLightFactor", () -> 0.0F) // Warden darkness current light factor - 1.7.10 doesn't have it so hardcode to 0
|
||||
.uniform1b(PER_FRAME, "hideGUI", () -> client.gameSettings.hideGUI)
|
||||
|
||||
@@ -72,6 +72,11 @@ public class VanillaBiomeList {
|
||||
biomes.add(new BiomeEntry(BiomeGenBase.sky, "END_HIGHLANDS"));
|
||||
biomes.add(new BiomeEntry(BiomeGenBase.sky, "END_BARRENS"));
|
||||
|
||||
// Modern biome variants (1.20+)
|
||||
biomes.add(new BiomeEntry(BiomeGenBase.jungle, "BIOME_SPARSE_JUNGLE"));
|
||||
biomes.add(new BiomeEntry(BiomeGenBase.mushroomIsland, "BIOME_MUSHROOM_FIELDS"));
|
||||
biomes.add(new BiomeEntry(BiomeGenBase.swampland, "BIOME_MANGROVE_SWAMP"));
|
||||
|
||||
return Collections.unmodifiableList(biomes);
|
||||
}
|
||||
|
||||
|
||||
@@ -214,6 +214,8 @@ options.angelica.threadedChunkBuilding.tooltip=If enabled, chunk meshing will be
|
||||
|
||||
pack.iris.select.title=Select
|
||||
pack.iris.configure.title=Configure
|
||||
pack.iris.list.label=+ Drag and Drop Shader Packs to add
|
||||
pack.iris.list.label.lwjgl2=Install lwjgl3ify to drag and drop Shader Packs
|
||||
label.iris.true=On
|
||||
label.iris.false=Off
|
||||
|
||||
|
||||
@@ -0,0 +1,257 @@
|
||||
options.button.shader=シェーダー...
|
||||
|
||||
options.chunks=%s チャンク
|
||||
options.entityShadows=エンティティの影
|
||||
options.droppedItems=%s アイテム
|
||||
options.droppedItems.max=無制限
|
||||
|
||||
sodium.option_impact.low=低
|
||||
sodium.option_impact.medium=中
|
||||
sodium.option_impact.high=高
|
||||
sodium.option_impact.extreme=極高
|
||||
sodium.option_impact.varies=場合による
|
||||
sodium.options.pages.quality=品質
|
||||
sodium.options.pages.performance=パフォーマンス
|
||||
sodium.options.pages.advanced=詳細
|
||||
sodium.options.pages.appearance=外観
|
||||
sodium.options.pages.text=文字エフェクト
|
||||
sodium.options.view_distance.tooltip=地形をどれだけ遠くまで描画するかを設定します。描画距離が短いほど描画される地形が少なくなり、FPSが向上します。
|
||||
sodium.options.simulation_distance.tooltip=エンティティが読み込まれ、処理される距離を設定します。演算距離を短くすることで内部サーバーの負荷が減り、FPSが向上します。
|
||||
sodium.options.brightness.tooltip=ゲーム画面の明るさ(ガンマ)を設定します。
|
||||
sodium.options.clouds.name=雲
|
||||
sodium.options.clouds.tooltip=雲をどのように表示するか、無効にするかを設定します。
|
||||
sodium.options.gui_scale.tooltip=GUIの大きさを設定します。「自動」では最大倍率が適用されます。
|
||||
sodium.options.fullscreen.tooltip=有効にすると、ゲーム画面は(対応している場合)フルスクリーンで表示されます。
|
||||
sodium.options.v_sync.tooltip=有効にすると、ゲームのFPSがモニターのリフレッシュレートに同期され、入力遅延が増加する代わりに、より滑らかになります。処理速度が遅いと、パフォーマンスが低下する可能性があります。
|
||||
sodium.options.fps_limit.tooltip=最大FPSを制限し、マルチタスク時の負荷を軽減できます。垂直同期が有効になっている場合、この設定はモニターのリフレッシュレートよりも低い値でない限り無視されます。
|
||||
sodium.options.view_bobbing.tooltip=有効にすると、移動時に視点が揺れます。画面酔いの症状が出る場合は、無効にすると症状が軽減される可能性があります。
|
||||
|
||||
|
||||
sodium.options.graphics_quality.tooltip=一部の古い形式の設定を制御します。これはMODとの互換性のために必要です。以降の設定を「デフォルト」にすると、この設定が適用されます。
|
||||
sodium.options.clouds_quality.tooltip=雲の品質を設定します。
|
||||
sodium.options.weather_quality.tooltip=雨や雪のエフェクトの品質を設定します。
|
||||
sodium.options.leaves_quality.name=木の葉の品質
|
||||
sodium.options.leaves_quality.tooltip=木の葉の品質を設定します。
|
||||
sodium.options.grass_quality.name=草ブロックの品質
|
||||
sodium.options.grass_quality.tooltip=草ブロックの側面の品質を設定します。
|
||||
sodium.options.celeritas_smooth_lighting.name=Celeritasスムースライティング
|
||||
sodium.options.celeritas_smooth_lighting.tooltip=有効にすると、Celeritasの照明パイプラインがスムースライティングに使用されます。スムースライティングが有効である必要があります。
|
||||
sodium.options.particle_quality.name=パーティクルの品質
|
||||
sodium.options.particle_quality.tooltip=画面上に同時に存在できるパーティクルの最大数を設定します。
|
||||
sodium.options.smooth_lighting.tooltip=ブロックの照明と陰影を滑らかにします。チャンクロードが少し遅くなりますが、FPSには影響しません。
|
||||
sodium.options.biome_blend.value=%s ブロック
|
||||
sodium.options.biome_blend.tooltip=ブロックの色情報を収集するバイオームの範囲を設定します。値を大きくすると、チャンクロードが大幅に遅くなる上に、あまり品質が向上しなくなります。
|
||||
|
||||
sodium.options.entity_shadows.tooltip=有効にすると、エンティティの下に影が表示されます。
|
||||
sodium.options.vignette.name=ビネット
|
||||
sodium.options.vignette.tooltip=有効にすると、ゲーム画面にビネット効果が適用されます。フィルレートが制限されていない限り、FPSに影響が出る可能性は非常に低いでしょう。
|
||||
sodium.options.mipmap_levels.tooltip=ブロックのテクスチャに使用するミップマップの数を設定します。値が大きいほど遠くのブロックの見た目が良くなりますが、アニメーションが多いとパフォーマンスに悪影響を与える可能性があります。
|
||||
sodium.options.use_chunk_multidraw.name=チャンクの同時描画
|
||||
sodium.options.use_chunk_multidraw.tooltip=複数のチャンクを少ない回数で描画できます。CPU負荷を大幅に削減し、GPUの利用効率も向上する可能性があります。一部のグラフィックドライバで問題を引き起こす可能性があるため、不具合が発生する場合は無効にしてください。
|
||||
sodium.options.use_vertex_objects.name=頂点配列オブジェクト
|
||||
sodium.options.use_vertex_objects.tooltip=頂点の描画方法に関する情報をグラフィックドライバに移動することでパフォーマンスが向上し、同じオブジェクトの反復描画をより最適化できるようになります。互換性の無いMODを使用している場合を除き、通常はこの機能を無効にする必要はありません。
|
||||
sodium.options.use_block_face_culling.name=ブロック表面カリング
|
||||
sodium.options.use_block_face_culling.tooltip=有効にすると、画面に映るブロック面のみが描画対象となります。描画処理の初期段階で多数のブロック面が除外され、メモリ帯域幅とGPUの処理時間を節約できます。一部のリソースパックでは問題が発生する可能性があるため、ブロック面に穴が開く場合は無効にしてください。
|
||||
sodium.options.use_compact_vertex_format.name=小さな頂点フォーマット
|
||||
sodium.options.use_compact_vertex_format.tooltip=有効にすると、チャンク描画に小さな頂点フォーマットが使用されます。特に内臓グラフィックスの場合、VRAMの使用量と帯域幅を大幅に削減できますが、位置とテクスチャ座標属性の精度が低下するため、一部のリソースパックでZ-Fightingが発生する可能性があります。
|
||||
sodium.options.use_fog_occlusion.name=霧による遮蔽
|
||||
sodium.options.use_fog_occlusion.tooltip=有効にすると、霧に完全に隠れているチャンクは描画されなくなり、パフォーマンスが向上します。霧が強い水中などでより効果が高くなりますが、空と霧の間で見た目の異常が出る可能性があります。
|
||||
sodium.options.use_entity_culling.name=エンティティカリング
|
||||
sodium.options.use_entity_culling.tooltip=有効にすると、見える範囲に存在しないと判断されたエンティティが描画されなくなります。地下や壁の背後にあるエンティティの描画をしないことで、パフォーマンスが向上します。
|
||||
sodium.options.use_particle_culling.name=パーティクルカリング
|
||||
sodium.options.use_particle_culling.tooltip=有効にすると、見えると判断されたパーティクルのみが描画されるようになります。近くに多数のパーティクルがある場合にFPSが大幅に向上する可能性があります。
|
||||
sodium.options.animate_only_visible_textures.name=見えるアニメーションのみ描画
|
||||
sodium.options.animate_only_visible_textures.tooltip=有効にすると、表示可能と判断されたアニメーションのみが描画されます。特にリソースパックの負荷が高い場合、一部のハードウェアでFPSが大幅に向上する可能性があります。一部のアニメーションが動かないなどの問題が発生した場合は、この設定を無効にしてください。
|
||||
sodium.options.translucency_sorting.name=半透明ブロックの整理
|
||||
sodium.options.translucency_sorting.tooltip=有効にすると、半透明ブロックは奥から手前へと正しく並べ替えられ、特に複数の半透明ブロックが重なっている場合の品質が向上しますが、代わりに負荷が上昇します。
|
||||
sodium.options.cpu_render_ahead_limit.name=CPUの先読み処理制限
|
||||
sodium.options.cpu_render_ahead_limit.tooltip=CPUがGPUの描画完了まで待機できる最大フレーム数を設定します。極端に低い値、または高い値を設定すると、FPSが不安定になる可能性があります。
|
||||
sodium.options.cpu_render_ahead_limit.value=%s フレーム
|
||||
sodium.options.allow_direct_memory_access.name=ダイレクトメモリアクセス
|
||||
sodium.options.allow_direct_memory_access.tooltip=有効にすると、一部の重要なコードパスでのパフォーマンス向上のために、メモリへの直接アクセスが許可されます。チャンクやエンティティの描画でのCPUの余分な負荷が大幅に削減される可能性が高まりますが、一部のバグやクラッシュの診断が難しくなる場合があります。誰かに指示された場合か、設定内容を十分に理解している場合にのみ無効にしてください。
|
||||
sodium.options.ignore_driver_blacklist.name=ドライバブラックリストの無視
|
||||
sodium.options.ignore_driver_blacklist.tooltip=有効にすると、ハードウェア/ドライバー構成との既知の非互換性が無視され、問題を引き起こす可能性のある設定を有効にできるようになります。何をしているのかを正確に理解していない限り、このオプションを変更しないでください。変更後に設定画面を保存して閉じ、再度開く必要があります。
|
||||
sodium.options.enable_memory_tracing.name=メモリトレース
|
||||
sodium.options.enable_memory_tracing.tooltip=デバッグ機能です。有効にすると、メモリリークが検出された際の診断情報を改善するために、メモリ割り当てと処理の呼び出し履歴が収集されます。
|
||||
sodium.options.performance_impact_string=パフォーマンスへの影響: %s
|
||||
sodium.options.use_persistent_mapping.name=永続的なマッピング
|
||||
sodium.options.use_persistent_mapping.tooltip=有効にすると、チャンクとエンティティの描画を高速化するために、少量のメモリが永続的にマッピングされます。\n\nOpenGL4.4かARB_buffer_storageが必要です。
|
||||
sodium.options.chunk_memory_allocator.name=チャンクメモリ割り当て
|
||||
sodium.options.chunk_memory_allocator.tooltip=チャンク描画に使用するメモリ割り当て方法を設定します。\n- 非同期: 最速で、ほとんどの最新のグラフィックドライバで正常に動作します。\n- スワップ: 古いグラフィックドライバ向けの代替法です。メモリ使用量が大幅に増加する可能性があります。
|
||||
sodium.options.chunk_memory_allocator.async=非同期
|
||||
sodium.options.chunk_memory_allocator.swap=スワップ
|
||||
sodium.options.chunk_update_threads.name=チャンク更新スレッド
|
||||
sodium.options.chunk_update_threads.tooltip=チャンクロードに使用するCPUスレッド数を設定します。スレッド数を増やすと、チャンクロード速度が向上しますが、フレームタイムに悪影響を与える可能性があります。
|
||||
sodium.options.always_defer_chunk_updates.name=常にチャンク更新を遅らせる
|
||||
sodium.options.always_defer_chunk_updates.tooltip=有効にすると、重要なチャンクの更新完了を待たずに描画が実行されます。状況によってはFPSが大幅に向上する可能性がありますが、地形描画に著しい視覚的な遅延が発生する場合があります。
|
||||
sodium.options.use_no_error_context.name=エラーの無いコンテキスト
|
||||
sodium.options.use_no_error_context.tooltip=有効にすると、エラーチェックが無効になった状態でOpenGLコンテキストが作成されます。パフォーマンスが若干向上する可能性がありますが、OpenGLエラーを適切に処理できずにゲームがクラッシュする可能性も高まります。原因不明の突然のクラッシュが発生する場合は、この設定を無効にしてください。
|
||||
sodium.options.async_occlusion_mode.name=非同期オクルージョン
|
||||
sodium.options.async_occlusion_mode.tooltip=有効にすると、レンダリングパスで非同期オクルージョンカリングを使用します。「Only Shadow(デフォルト)」はシャドウパスのみで非同期オクルージョンを実行し、メインの描画リストでは同期を維持します。「Everything」は全てのパスを非同期で実行しますが、カメラの高速移動時に1フレームの可視遅延が発生する可能性があります。「None」は非同期オクルージョンを完全に無効化します。
|
||||
sodium.options.use_occlusion_culling.name=オクルージョンカリング
|
||||
sodium.options.use_occlusion_culling.tooltip=有効にすると、他のチャンクの後ろに隠れているチャンクは描画されません。無効にするとパフォーマンスが大幅に低下しますが、デバッグには役立ちます。
|
||||
sodium.options.threads.value=%s スレッド
|
||||
sodium.options.default=デフォルト
|
||||
sodium.options.buttons.undo=戻す
|
||||
sodium.options.buttons.apply=適用
|
||||
sodium.options.buttons.donate=JellySquidに一杯のコーヒーを!
|
||||
|
||||
options.dynamic_fov=臨場感ある視野角
|
||||
options.dynamic_fov.tooltip=有効にすると、ゲーム画面の視野角はプレイヤーの速度に応じて変化します。
|
||||
options.framerate=%s FPS
|
||||
|
||||
iris.shaders.toggled=シェーダーを %s に切り替えました!
|
||||
iris.shaders.disabled=シェーダーを無効化しました!
|
||||
|
||||
options.iris.apply=適用
|
||||
options.iris.refresh=更新
|
||||
options.iris.openShaderPackFolder=パックフォルダーを開く...
|
||||
options.iris.shaderPackSettings=シェーダーの設定...
|
||||
options.iris.shaderPackList=シェーダー一覧...
|
||||
options.iris.refreshShaderPacks=シェーダーの更新
|
||||
options.iris.shaderPackSelection=シェーダーパック...
|
||||
options.iris.shaderPackSelection.title=シェーダーパック
|
||||
options.iris.shaderPackSelection.addedPack=シェーダー「%s」を追加しました
|
||||
options.iris.shaderPackSelection.addedPacks=%s個のシェーダーを追加しました。
|
||||
options.iris.shaderPackSelection.failedAdd=無効なファイルです
|
||||
options.iris.shaderPackSelection.failedAddSingle=「%s」は無効なシェーダーです。
|
||||
options.iris.shaderPackSelection.copyError=シェーダー「%s」を追加できませんでした
|
||||
options.iris.shaderPackSelection.copyErrorAlreadyExists=「%s」は既にパックフォルダーに存在します!
|
||||
options.iris.shaderPackOptions.tooManyFiles=シェーダー設定ファイルは複数個インポートできません!
|
||||
options.iris.shaderPackOptions.failedImport=シェーダー設定ファイル「%s」のインポートに失敗しました!
|
||||
options.iris.shaderPackOptions.importedSettings=シェーダー設定を「%s」からインポートしました。
|
||||
options.iris.shaders.disabled=シェーダー: OFF
|
||||
options.iris.shaders.enabled=シェーダー: ON
|
||||
options.iris.shaders.nonePresent=シェーダー: 未選択
|
||||
options.iris.back=戻る
|
||||
options.iris.reset=リセット
|
||||
options.iris.reset.tooltip=全ての設定をリセットしますか?
|
||||
options.iris.reset.tooltip.holdShift=Shiftキーを押しながらクリックでリセット
|
||||
options.iris.importSettings.tooltip=ファイルから設定をインポート
|
||||
options.iris.exportSettings.tooltip=設定をファイルへエクスポート
|
||||
options.iris.mustDisableFullscreen=フルスクリーンを解除してください!
|
||||
options.iris.setToDefault=この設定をリセットしますか?
|
||||
options.iris.profile=プロファイル
|
||||
options.iris.profile.custom=カスタム
|
||||
options.iris.shadowDistance=影の最大描画距離
|
||||
options.iris.shadowDistance.sodium_tooltip=影の最大描画距離
|
||||
options.iris.shadowDistance.enabled=影が描画される最大の距離を設定できます。 指定された値より遠くの地形やエンティティには影が描画されません。 最大描画距離を下げることで、パフォーマンスが向上することがあります。
|
||||
options.iris.shadowDistance.disabled=お使いのシェーダーパックでは既に最大描画距離が設定されているため、ここでは変更できません。
|
||||
options.iris.gui.hide=GUIを非表示
|
||||
options.iris.gui.show=GUIを表示
|
||||
|
||||
options.dynamic_lights=ダイナミックライト
|
||||
options.dynamic_lights.tooltip=ダイナミックライトを有効にします。モード:OFF - 無効、FASTEST - 500ミリ秒の遅延、FAST - 250ミリ秒の遅延、FANCY - 50ミリ秒の遅延、REALTIME - 無遅延。
|
||||
options.dynamic_lights_shader_force=ダイナミックライト - シェーダーに強制適用
|
||||
options.dynamic_lights_shader_force.tooltip=有効 - シェーダーがONのときでもダイナミックライトを使用します、無効 - シェーダーがONのときはダイナミックライトを使用しません。
|
||||
options.dynamic_lights_frustum_culling=フラスタムカリング
|
||||
options.dynamic_lights_frustum_culling.tooltip=画面上の光源があるチャンクのみを更新します。GPU負荷が軽減されます。
|
||||
options.dynamic_lights_adaptive_ticking=適応型ティック処理
|
||||
options.dynamic_lights_adaptive_ticking.tooltip=遠方および画面外の光源の更新頻度を下げます。グローバルモード設定と併用できます。
|
||||
options.dynamic_lights_slow_dist=遅い光源更新の距離
|
||||
options.dynamic_lights_slow_dist.tooltip=光源の更新頻度が1/5となる距離(単位:ブロック)。推奨値:32ブロック(約2チャンク)。
|
||||
options.dynamic_lights_slower_dist=より遅い光源更新の距離
|
||||
options.dynamic_lights_slower_dist.tooltip=光源の更新頻度が1/10となる距離(単位:ブロック)。推奨値:64ブロック(約4チャンク)。
|
||||
options.dynamic_lights_background_dist=バックグラウンド更新距離
|
||||
options.dynamic_lights_background_dist.tooltip=光源の更新頻度が1/20(1秒に1回)となる距離(単位:ブロック)。見えない光源にも適用されます。
|
||||
options.dynamic_lights_cull_timeout=カリングタイムアウト(ティック)
|
||||
options.dynamic_lights_cull_timeout.tooltip=見えないチャンクが更新を強制されるまでに待機できる最大ティック数。値が小さいほど応答性は向上しますが、GPUの負荷が増加します。
|
||||
options.dynamiclights.page=ダイナミックライト
|
||||
options.dynamiclights.entities=エンティティの設定...
|
||||
options.dynamiclights.entities.title=ダイナミックライト- エンティティ
|
||||
options.dynamiclights.entities.info=ダイナミックライトを適用するエンティティの種類を設定します。一部の項目はMODとの互換性のために設定されています。
|
||||
options.dynamiclights.entities.search=検索 (@mod, $on, $off)
|
||||
options.dynamiclights.entity.tooltip=%sのエンティティのダイナミックライトを設定します。そのエンティティタイプが不要な光を発する場合は、パフォーマンス向上のために無効にしてください。
|
||||
|
||||
options.angelica.search.no_results=該当する設定が見つかりません
|
||||
options.angelica.fontconfig=フォント設定...
|
||||
options.angelica.fontconfig.title=フォント設定
|
||||
options.angelica.fontconfig.currentfonts=使用フォント: §e%s§r 代替フォント: §b%s
|
||||
options.angelica.fontconfig.searchprompt=§7§oフォントを検索...
|
||||
options.angelica.fontconfig.testareaprompt=§7§oテストエリア
|
||||
options.angelica.fontconfig.testareainfo=ここに文章を入力して、どのように表示されるかを確認できます。書式設定には「&」を使用してください。
|
||||
options.angelica.fontconfig.testareaexample=&d&lへロブライン&rは&n此処には&7&m&o居なかった&r
|
||||
options.angelica.fontconfig.disable_custom_font=カスタムフォントを無効化
|
||||
options.angelica.fontconfig.enable_custom_font=カスタムフォントを有効化
|
||||
options.angelica.fontconfig.reset_values=設定をリセット
|
||||
options.angelica.fontconfig.no_fonts_warning=お使いのシステムではカスタムフォントを利用できません。詳細についてはログをご覧ください。
|
||||
options.angelica.fontconfig.font_quality=カスタムフォントの品質: %s
|
||||
options.angelica.fontconfig.shadow_offset=陰影のオフセット: %s
|
||||
options.angelica.fontconfig.shadow_copies=陰影の数: %s
|
||||
options.angelica.fontconfig.bold_copies=太字のコピーの数:%s
|
||||
options.angelica.fontconfig.glyph_scale=文字の大きさ:%s
|
||||
options.angelica.fontconfig.glyph_aspect=文字の縦横比:%s
|
||||
options.angelica.fontconfig.whitespace_scale=空白の長さ:%s
|
||||
options.angelica.fontconfig.glyph_spacing=文字間の長さ:%s
|
||||
options.angelica.fontconfig.font_aa_strength=アンチエイリアシングの強度:%s
|
||||
options.angelica.fontconfig.aamode.aa_none=アンチエイリアシング:オフ
|
||||
options.angelica.fontconfig.aamode.aa_4x=アンチエイリアシング:4x MSAA
|
||||
options.angelica.fontconfig.aamode.aa_16x=アンチエイリアシング:16x MSAA
|
||||
options.angelica.fontconfig.custom_font_scale=カスタムフォントの大きさ:%s
|
||||
options.angelica.fontconfig.shadow_offset_unicode=ユニコード陰影オフセット:%s
|
||||
options.angelica.fontconfig.font_quality.tooltip=カスタムフォントの描画品質を向上させ、パフォーマンスとメモリ使用量を多少犠牲にする代わりに、ギザギザを軽減します。
|
||||
options.angelica.fontconfig.shadow_offset.tooltip=フォントの陰影のオフセット。§l太字§rにも適用されます。
|
||||
options.angelica.fontconfig.shadow_copies.tooltip=文字の陰影の数。すべてをオフセットすることで、擬似的な3D効果を生み出します。
|
||||
options.angelica.fontconfig.bold_copies.tooltip=太字のコピーの数。細めのカスタムフォントで、太字の見栄えが良くなる場合があります。
|
||||
options.angelica.fontconfig.glyph_scale.tooltip=各文字の大きさ。極端な値を設定すると、プレイに支障が出る可能性があります。
|
||||
options.angelica.fontconfig.glyph_aspect.tooltip=各文字の縦横比。
|
||||
options.angelica.fontconfig.whitespace_scale.tooltip=スペースなどの空白の拡大率。
|
||||
options.angelica.fontconfig.glyph_spacing.tooltip=各文字の間隔。
|
||||
options.angelica.fontconfig.font_aa_strength.tooltip=フォントのアンチエイリアシングに使用されるサンプル間隔。値が大きいとフォントがぼやけ、値が小さいとギザギザが発生する可能性があります。お使いの環境に最適な値を見つけてください。
|
||||
options.angelica.fontconfig.aamode.tooltip=フォントのアンチエイリアシングモード。パフォーマンスを多少犠牲にする代わりに、拡大縮小された文字や、斜体の外観と読みやすさを大幅に向上させることができます。
|
||||
options.angelica.fontconfig.custom_font_scale.tooltip=カスタムフォントの大きさ変更の値です。カスタムフォントの文字が、通常フォントの文字と比較して小さすぎるか、大きすぎる場合はこの値を調整してください。
|
||||
options.angelica.fontconfig.shadow_offset_unicode.tooltip=Unicodeフォントにのみ適用される陰影オフセットの値です。Unicodeフォントの一部をMinecraft風のフォントに置き換えるリソースパックを使用している場合は、この値を1.0倍に設定してください。
|
||||
options.angelica.hudCaching=HUDキャッシング
|
||||
options.angelica.hudCaching.tooltip=HUDをフレームバッファにキャッシュし、フレーム間で再利用することで描画時の余計な負荷を削減します。起動時にHUDキャッシングを有効にする必要があります(実験的機能)。
|
||||
options.angelica.droppedItemLimit=ドロップアイテムの描画数制限
|
||||
options.angelica.droppedItemLimit.tooltip=描画されるドロップアイテムの最大数。値を小さくするとパフォーマンスが向上する可能性があります。
|
||||
options.angelica.mobSpawnerRenderDistance=モブスポナーの描画距離
|
||||
options.angelica.mobSpawnerRenderDistance.tooltip=モブスポナー内の回転するモブの描画距離
|
||||
options.angelica.itemdisplaylistcount=アイテム描画キャッシュの制限
|
||||
options.angelica.itemdisplaylistcount.tooltip=最適化されたアイテム描画でキャッシュするVBOの最大値。値を大きくするとパフォーマンスが大幅に向上しますが、VRAMの使用量が増える可能性があります。
|
||||
options.angelica.threadedChunkBuilding=並列チャンク構築
|
||||
options.angelica.threadedChunkBuilding.tooltip=有効にすると、チャンクメッシュ生成が複数のスレッドで並列実行され、チャンクロード速度が大幅に向上します。カスタムブロックレンダラーを使用するMODでレンダリングの問題が発生する場合は、無効にしてください。有効化には描画の再読み込みが必要です。
|
||||
|
||||
pack.iris.select.title=シェーダー選択
|
||||
pack.iris.configure.title=シェーダー設定
|
||||
pack.iris.list.label=+ ドラッグアンドドロップでシェーダーを追加
|
||||
pack.iris.list.label.lwjgl2=ドラッグアンドドロップでシェーダーを追加するにはlwjgl3ifyをインストールしてください
|
||||
label.iris.true=ON
|
||||
label.iris.false=OFF
|
||||
|
||||
sodium.options.use_render_pass_optimization.name=レンダーパスの最適化
|
||||
sodium.options.use_render_pass_optimization.tooltip=スプライトの透明度を分析し、スプライトがより負荷の高いレンダリングパスを必要としない場合、レンダリングパスを自動的にダウングレードします(例:半透明から切り抜き、切り抜きから不透明)。これにより、描画呼び出しと余計な描画が削減されます。
|
||||
|
||||
options.angelica.aggressiveChunkLoading=積極的チャンクロード
|
||||
options.angelica.aggressiveChunkLoading.tooltip=隣接するチャンクの準備がまだ整っていなくても、チャンクが読み込まれるとすぐに描画します。描画距離の端での体感的なチャンクロード速度が向上します。隣接するチャンクが読み込まれると、チャンクは自動的に再構築されます。描画距離の短いサーバーで役立ちます。
|
||||
options.angelica.disablef3=F3画面追加情報の無効化
|
||||
options.angelica.disablef3.tooltip=Angelicaに関するF3画面の情報の表示を無効にします。
|
||||
options.angelica.texteffects.rgb_colors=RGBカラー
|
||||
options.angelica.texteffects.rgb_colors.tooltip=「%s」のHTMLカラーコードを有効にします。
|
||||
options.angelica.texteffects.gradients=グラデーション
|
||||
options.angelica.texteffects.gradients.tooltip=滑らかな色の移り変わり
|
||||
options.angelica.texteffects.rainbow=虹色
|
||||
options.angelica.texteffects.rainbow.tooltip=虹色のアニメーション
|
||||
options.angelica.texteffects.wave_text=波打つ文字
|
||||
options.angelica.texteffects.wave_text.tooltip=波打つ文字のアニメーション
|
||||
options.angelica.texteffects.wave_amplitude=波の振幅
|
||||
options.angelica.texteffects.wave_amplitude.tooltip=波打つ文字が跳ね返る距離(デフォルト:2.0)
|
||||
options.angelica.texteffects.dinnerbone_text=文字の上下反転
|
||||
options.angelica.texteffects.dinnerbone_text.tooltip=文字の上下反転の設定。
|
||||
options.angelica.texteffects.drop_shadow=陰影
|
||||
options.angelica.texteffects.drop_shadow.tooltip=区切りごとの陰影は「%s」、色付きの陰影は
|
||||
options.angelica.texteffects.ampersand_conversion=アンパサンドの変換
|
||||
options.angelica.texteffects.ampersand_conversion.tooltip=描画時に「%s」プレフィックスコードをフォーマットコードに変換します。
|
||||
|
||||
sodium.options.multidraw_mode.name=同時描画モード
|
||||
sodium.options.multidraw_mode.tooltip=地形描画の命令の割り当て方法を設定します。§l直接的§r は glMultiDrawElementsBaseVertex を使用します (デフォルト、OpenGL 3.2 以降)。§l間接的§r はGPU間接レンダリング (GL 4.3 以降) を使用し、一部のハードウェアではCPUの余分な負荷を削減できます。§l独立的§r は個別の描画呼び出しをします。
|
||||
sodium.options.multidraw_mode.direct=直接的
|
||||
sodium.options.multidraw_mode.indirect=間接的
|
||||
sodium.options.multidraw_mode.individual=独立的
|
||||
sodium.options.upload_method.name=ストリーミングアップロード方式
|
||||
sodium.options.upload_method.tooltip=データがGPUにストリーミングされる方式を変更します。一部の設定は、特定のドライバーでパフォーマンスの向上につながる場合があります。
|
||||
|
||||
|
||||
|
||||
sodium.options.enable_deferred_batching.name=遅延パーティクル同時処理
|
||||
sodium.options.enable_deferred_batching.tooltip=パーティクルの描画呼び出しを、レイヤーごとに統合された描画にまとめて実行します。パーティクルが正しくレンダリングされない場合は、この設定を無効にしてください。
|
||||
@@ -0,0 +1,80 @@
|
||||
options.button.detail=詳細...
|
||||
options.button.other=その他...
|
||||
options.button.particle=パーティクル...
|
||||
options.button.sky=環境...
|
||||
options.chunks=%s チャンク
|
||||
options.framerate=%s FPS
|
||||
options.graphics.shelledfancy=描画優先(ハイブリッド)
|
||||
options.graphics.shelledfast=処理優先(ハイブリッド)
|
||||
options.graphics.smart=スマート
|
||||
options.graphics.ultra=ウルトラ
|
||||
options.off=オフ
|
||||
options.on=オン
|
||||
options.cloud_height=雲の高さ
|
||||
options.cloud_height.tooltip=雲の高さを設定します。
|
||||
options.cloud_scale=雲の大きさ
|
||||
options.cloud_scale.tooltip=雲の大きさを設定します。
|
||||
options.gui_background=背景テーマ
|
||||
options.gui_background.tooltip=設定画面背景のテーマを設定します。
|
||||
options.downfall_distance=天気のエフェクト
|
||||
options.downfall_distance.tooltip=天気のエフェクトを設定します。
|
||||
options.dynamic_fov=臨場感ある視野角
|
||||
options.dynamic_fov.tooltip=ゲームモードによっては、プレイヤーの移動速度や特定のMODの操作(ツールのズームや武器のスコープなど)に応じて、ゲーム画面の視野角が変化します。
|
||||
options.horizon=地平線
|
||||
options.horizon.tooltip=描画チャンクの端を映すかを設定します。
|
||||
options.terrain_fog=霧
|
||||
options.terrain_fog.tooltip=霧の有効、無効を設定します。
|
||||
options.fog_near_distance=霧の距離
|
||||
options.fog_near_distance.tooltip=霧が発生し始める距離を設定します。(0%%(透明)から描画距離に応じて線形的に増加します)。
|
||||
options.bobview_mode=画面の揺れ
|
||||
options.bobview_mode.tooltip=画面の揺れ動作を、手または画面のみを揺らすように変更します。
|
||||
options.bobview.hand=手のみ
|
||||
options.bobview.camera=画面のみ
|
||||
options.fov.all=オン
|
||||
options.fov.mods=Modによる動作のみ
|
||||
options.fov.none=オフ
|
||||
options.mode_cloud_translucency=半透明の雲
|
||||
options.mode_cloud_translucency.tooltip=半透明の雲の有効、無効を設定します
|
||||
options.mode_clouds=雲
|
||||
options.mode_clouds.tooltip=雲の設定
|
||||
options.mode_dropped_items=ドロップアイテム
|
||||
options.mode_dropped_items.tooltip=ドロップアイテムの描画品質を設定します。
|
||||
options.mode_glint_inv=GUIエンチャントエフェクト
|
||||
options.mode_glint_inv.tooltip=GUI上でのエンチャントエフェクトの有効、無効を設定します。
|
||||
options.mode_glint_world=ワールドエンチャントエフェクト
|
||||
options.mode_glint_world.tooltip=ワールド上でのエンチャントエフェクトの有効、無効を設定します。
|
||||
options.mode_gui_background=背景
|
||||
options.mode_gui_background.tooltip=設定画面背景の有効、無効を設定します。
|
||||
options.mode_leaves=葉の品質
|
||||
options.mode_leaves.tooltip=葉の品質
|
||||
options.mode_light_flicker=光のちらつき
|
||||
options.mode_light_flicker.tooltip=光のちらつきの有効、無効を設定します。
|
||||
options.mode_shadows=エンティティの影
|
||||
options.mode_shadows.tooltip=エンティティの影の有効、無効を設定します。
|
||||
options.mode_sky=空
|
||||
options.mode_sky.tooltip=空の描画の有効、無効を設定します。
|
||||
options.mode_sun_moon=太陽と月
|
||||
options.mode_sun_moon.tooltip=太陽と月の描画の有効、無効を設定します。
|
||||
options.mode_stars=星
|
||||
options.mode_stars.tooltip=星の描画の有効、無効を設定します。
|
||||
options.mode_water=水
|
||||
options.mode_water.tooltip=水の設定をします。
|
||||
options.mode_vignette=ビネット
|
||||
options.mode_vignette.tooltip=ビネットの有効、無効を設定します。
|
||||
options.particles_enc_table=エンチャント台のパーティクル
|
||||
options.particles_enc_table.tooltip=エンチャント台のパーティクルの設定をします。
|
||||
options.particles_void=奈落のパーティクル
|
||||
options.particles_void.tooltip=奈落のパーティクルの有効、無効を設定します。
|
||||
options.render_distance_clouds=雲までの距離
|
||||
options.render_distance_clouds.tooltip=最も近い雲までの距離を設定します。
|
||||
options.title.detail=詳細設定
|
||||
options.title.other=その他の設定
|
||||
options.title.particle=パーティクルの設定
|
||||
options.title.sky=環境の設定
|
||||
options.title.video=ビデオ設定
|
||||
options.total_stars=星の密度
|
||||
options.total_stars.tooltip=星の密度を設定します。
|
||||
options.void_fog=奈落の霧
|
||||
options.void_fog.tooltip=奈落の霧の有効、無効を設定します。
|
||||
options.hurt_shake=被ダメージ時の画面揺れ
|
||||
options.background.random=ランダム
|
||||
@@ -6,15 +6,12 @@ import net.coderbot.iris.layer.GbufferPrograms;
|
||||
import net.coderbot.iris.pipeline.HandRenderer;
|
||||
import net.coderbot.iris.uniforms.ItemIdManager;
|
||||
import net.irisshaders.iris.api.v0.IrisApi;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.renderer.ItemRenderer;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import org.objectweb.asm.Opcodes;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.Redirect;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
/**
|
||||
@@ -44,31 +41,6 @@ public class MixinItemRenderer {
|
||||
ItemIdManager.setItemId(this.itemToRender);
|
||||
}
|
||||
|
||||
/**
|
||||
* Force the equip lower/raise animation whenever the held stack isn't an exact match for
|
||||
* the one being rendered.
|
||||
*/
|
||||
@Redirect(
|
||||
method = "updateEquippedItem",
|
||||
at = @At(value = "INVOKE", target = "Lnet/minecraft/item/ItemStack;getItemDamage()I", ordinal = 0)
|
||||
)
|
||||
private int iris$animateStackSwap(ItemStack incoming) {
|
||||
if (this.itemToRender != null
|
||||
&& !ItemStack.areItemStacksEqual(incoming, this.itemToRender)) {
|
||||
return Integer.MIN_VALUE;
|
||||
}
|
||||
return incoming.getItemDamage();
|
||||
}
|
||||
|
||||
@Redirect(
|
||||
method = "updateEquippedItem",
|
||||
at = @At(value = "FIELD", target = "Lnet/minecraft/client/renderer/ItemRenderer;itemToRender:Lnet/minecraft/item/ItemStack;", opcode = Opcodes.PUTFIELD, ordinal = 0)
|
||||
)
|
||||
private void iris$commitSlotOnInstantSwap(ItemRenderer self, ItemStack value) {
|
||||
this.itemToRender = value;
|
||||
int equippedItemSlot = Minecraft.getMinecraft().thePlayer.inventory.currentItem;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset the item ID after rendering first-person items.
|
||||
*/
|
||||
|
||||
@@ -78,7 +78,9 @@ public class MixinLocale {
|
||||
languageCodes.clear();
|
||||
|
||||
// Reverse order due to how minecraft has English and then the primary language in the language definitions list
|
||||
new LinkedList<>(definitions).descendingIterator().forEachRemaining(languageCodes::add);
|
||||
new LinkedList<>(definitions).descendingIterator()
|
||||
// FQN here because due to clashing
|
||||
.forEachRemaining(code -> languageCodes.add(code.toLowerCase(java.util.Locale.ROOT)));
|
||||
}
|
||||
|
||||
@Inject(method = "checkUnicode", at = @At("HEAD"), cancellable = true)
|
||||
|
||||
+18
-1
@@ -20,7 +20,7 @@ import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
/**
|
||||
* Mixin allows devs to target the ender crystal beams as a separate entity.
|
||||
* Mixin allows devs to target the ender crystal beams and dragon death rays as separate entities.
|
||||
* Also sets the special condition "lightning" on the dragon's death beams.
|
||||
*/
|
||||
@Mixin(RenderDragon.class)
|
||||
@@ -28,9 +28,15 @@ public abstract class MixinRenderDragon {
|
||||
@Unique
|
||||
private static final NamespacedId END_CRYSTAL_BEAM = new NamespacedId("minecraft", "end_crystal_beam");
|
||||
|
||||
@Unique
|
||||
private static final NamespacedId DRAGON_DEATH_RAY = new NamespacedId("minecraft", "dragon_death_rays");
|
||||
|
||||
@Unique
|
||||
private int angelica$previousEntityId = -1;
|
||||
|
||||
@Unique
|
||||
private int angelica$previousDeathRayEntityId = -1;
|
||||
|
||||
@Unique
|
||||
private boolean angelica$deathBeamsActive = false;
|
||||
|
||||
@@ -83,6 +89,13 @@ public abstract class MixinRenderDragon {
|
||||
GbufferPrograms.setupSpecialRenderCondition(SpecialCondition.LIGHTNING);
|
||||
angelica$deathBeamsActive = true;
|
||||
|
||||
Object2IntFunction<NamespacedId> entityIdMap = BlockRenderingSettings.INSTANCE.getEntityIds();
|
||||
if (entityIdMap != null) {
|
||||
angelica$previousDeathRayEntityId = CapturedRenderingState.INSTANCE.getCurrentRenderedEntity();
|
||||
int deathRayId = entityIdMap.applyAsInt(DRAGON_DEATH_RAY);
|
||||
CapturedRenderingState.INSTANCE.setCurrentEntity(deathRayId);
|
||||
}
|
||||
|
||||
angelica$depthPassReplay++;
|
||||
GLStateManager.glColorMask(false, false, false, false);
|
||||
angelica$invokeRenderEquippedItems(dragon, partialTicks);
|
||||
@@ -118,6 +131,10 @@ public abstract class MixinRenderDragon {
|
||||
private void angelica$endDeathBeamsLighting(EntityDragon dragon, float partialTicks, CallbackInfo ci) {
|
||||
if (angelica$depthPassReplay > 0) return;
|
||||
if (angelica$deathBeamsActive) {
|
||||
if (angelica$previousDeathRayEntityId != -1) {
|
||||
CapturedRenderingState.INSTANCE.setCurrentEntity(angelica$previousDeathRayEntityId);
|
||||
angelica$previousDeathRayEntityId = -1;
|
||||
}
|
||||
GbufferPrograms.teardownSpecialRenderCondition();
|
||||
angelica$deathBeamsActive = false;
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user