mirror of
https://github.com/GTNewHorizons/Angelica.git
synced 2026-11-15 01:34:48 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f78cfdd5fb | ||
|
|
183bcfbf41 | ||
|
|
502f30c0f9 | ||
|
|
ceff04adba | ||
|
|
b4dfdb8cc5 | ||
|
|
3064818477 |
No files matched your search
+1
-1
@@ -66,7 +66,7 @@ configurations.all {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compileOnly("com.github.GTNewHorizons:Hodgepodge:2.7.14:dev")
|
||||
compileOnly("com.github.GTNewHorizons:Hodgepodge:2.7.158:dev")
|
||||
|
||||
compileOnly("com.gtnewhorizons.retrofuturabootstrap:RetroFuturaBootstrap:1.1.0") { transitive = false }
|
||||
// runtimeOnlyNonPublishable("com.github.GTNewHorizons:lwjgl3ify:3.0.99")
|
||||
|
||||
@@ -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",
|
||||
|
||||
+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) {
|
||||
|
||||
-1
@@ -17,7 +17,6 @@ public class CeleritasBlockTransformer implements IClassTransformer {
|
||||
public CeleritasBlockTransformer() {
|
||||
this.inner = new CeleritasBlockTransform(AngelicaClientTweaker.isObfEnv());
|
||||
this.exclusions = inner.getTransformerExclusions();
|
||||
this.inner.setCeleritasSetting();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+30
-34
@@ -31,16 +31,21 @@ public final class CeleritasBlockTransform implements Opcodes {
|
||||
private static final Logger LOGGER = LogManager.getLogger("CeleritasBlockTransformer");
|
||||
private static final String BlockClass = "net/minecraft/block/Block";
|
||||
private static final String ThreadedBlockData = "com/gtnewhorizons/angelica/client/rendering/ThreadedBlockData";
|
||||
/** All classes under <tt>net.minecraft.block.Block*</tt> are Block subclasses save for these. */
|
||||
private static final String[] VanillaBlockExclusions = {
|
||||
"net/minecraft/block/IGrowable",
|
||||
"net/minecraft/block/ITileEntityProvider",
|
||||
"net/minecraft/block/BlockEventData",
|
||||
"net/minecraft/block/BlockSourceImpl",
|
||||
"net/minecraft/block/material/"
|
||||
};
|
||||
|
||||
private final Map<String, String> fieldNameToRedirect = new HashMap<>();
|
||||
private final Set<String> blockSubclasses = Collections.newSetFromMap(new ConcurrentHashMap<>());
|
||||
private final Set<String> moddedBlockSubclasses = Collections.newSetFromMap(new ConcurrentHashMap<>());
|
||||
// Block subclass owners we shouldn't redirect because they shadow some fields we want to redirect
|
||||
private final Set<String> blockSubclassExclusions = Collections.newSetFromMap(new ConcurrentHashMap<>());
|
||||
private final ClassConstantPoolParser cstPoolParser;
|
||||
|
||||
private final MethodHandle celeritasEnabledGetter;
|
||||
private boolean isCeleritasEnabled;
|
||||
|
||||
public CeleritasBlockTransform(boolean isObf) {
|
||||
final List<Pair<String, String>> mappings = ImmutableList.of(
|
||||
Pair.of("minX", "field_149759_B"),
|
||||
@@ -56,37 +61,30 @@ public final class CeleritasBlockTransform implements Opcodes {
|
||||
}
|
||||
|
||||
this.cstPoolParser = new ClassConstantPoolParser(this.fieldNameToRedirect.keySet().toArray(new String[0]));
|
||||
}
|
||||
|
||||
blockSubclasses.add(BlockClass);
|
||||
|
||||
try {
|
||||
// Needed because the config is loaded in LaunchClassLoader, but we need to access it in the parent system loader.
|
||||
final Class<?> angelicaConfig = Class.forName("com.gtnewhorizons.angelica.config.AngelicaConfig", true, Launch.classLoader);
|
||||
celeritasEnabledGetter = MethodHandles.lookup().findStaticGetter(angelicaConfig, "enableCeleritas", boolean.class);
|
||||
} catch (ReflectiveOperationException e) {
|
||||
throw new RuntimeException(e);
|
||||
private boolean isVanillaBlockSubclass(String className) {
|
||||
if (!className.startsWith(BlockClass)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public void setCeleritasSetting() {
|
||||
isCeleritasEnabled = true;
|
||||
}
|
||||
|
||||
private boolean isCeleritasEnabled() {
|
||||
if (isCeleritasEnabled) return true;
|
||||
try {
|
||||
return (boolean) celeritasEnabledGetter.invokeExact();
|
||||
} catch (Throwable e) {
|
||||
throw new RuntimeException(e);
|
||||
for (String exclusion : VanillaBlockExclusions) {
|
||||
if (className.startsWith(exclusion)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// This method needs to be called for every class, including the ones we don't want to transform
|
||||
private boolean isBlockSubclass(String className) {
|
||||
return isVanillaBlockSubclass(className) || moddedBlockSubclasses.contains(className);
|
||||
}
|
||||
|
||||
// This method needs to be called for every class, including the ones we don't want to transform.
|
||||
// Vanilla blocks are recognized by name; only modded subclasses need tracking, and FML's
|
||||
// EventSubscriptionTransformer guarantees a modded class's superclass loads first.
|
||||
public void trackBlockSubclasses(String className, String superClassName) {
|
||||
// It works because the deepest subclasses are always transformed first due to
|
||||
// ForgeEventTransformer recursive superclass loading
|
||||
if (blockSubclasses.contains(superClassName)) {
|
||||
blockSubclasses.add(className);
|
||||
if (!isVanillaBlockSubclass(className) && isBlockSubclass(superClassName)) {
|
||||
moddedBlockSubclasses.add(className);
|
||||
|
||||
if (blockSubclassExclusions.contains(superClassName)) {
|
||||
LOGGER.info("Class {} extends a class with shadowed block bounds fields and will be skipped from redirecting", className);
|
||||
@@ -110,9 +108,6 @@ public final class CeleritasBlockTransform implements Opcodes {
|
||||
|
||||
/** @return Was the class changed? */
|
||||
public boolean transformClassNode(String transformedName, ClassNode cn) {
|
||||
if (!isCeleritasEnabled()) {
|
||||
return false;
|
||||
}
|
||||
boolean changed = false;
|
||||
if (BlockClass.equals(cn.name)) {
|
||||
changed = cn.fields.removeIf(field -> fieldNameToRedirect.containsKey(field.name));
|
||||
@@ -124,7 +119,8 @@ public final class CeleritasBlockTransform implements Opcodes {
|
||||
}
|
||||
|
||||
private void trackBlockShadowingFields(ClassNode cn) {
|
||||
if (blockSubclasses.contains(cn.name)) {
|
||||
// Only modded subclasses can shadow; vanilla declares these fields solely in Block.
|
||||
if (moddedBlockSubclasses.contains(cn.name)) {
|
||||
for (FieldNode field : cn.fields) {
|
||||
if (fieldNameToRedirect.containsKey(field.name)) {
|
||||
LOGGER.info("Class '{}' shadows one or more block bounds fields, these accesses won't be redirected!", cn.name);
|
||||
@@ -141,7 +137,7 @@ public final class CeleritasBlockTransform implements Opcodes {
|
||||
for (AbstractInsnNode node = mn.instructions.getFirst(); node != null; node = node.getNext()) {
|
||||
if ((node.getOpcode() == GETFIELD || node.getOpcode() == PUTFIELD) && node instanceof FieldInsnNode fNode) {
|
||||
String newFieldName = fieldNameToRedirect.get(fNode.name);
|
||||
if (newFieldName != null && blockSubclasses.contains(fNode.owner) && !blockSubclassExclusions.contains(fNode.owner)) {
|
||||
if (newFieldName != null && isBlockSubclass(fNode.owner) && !blockSubclassExclusions.contains(fNode.owner)) {
|
||||
if (LOG_SPAM) {
|
||||
LOGGER.info("Redirecting Block.{} in {} to thread-safe wrapper", fNode.name, transformedName);
|
||||
}
|
||||
|
||||
@@ -329,6 +329,15 @@ public enum Mixins implements IMixins {
|
||||
)
|
||||
),
|
||||
|
||||
IRIS_SHADERS_CHISEL_BEACON(new MixinBuilder("Iris Chisel Beacon Beam")
|
||||
.setPhase(Phase.LATE)
|
||||
.setApplyIf(() -> AngelicaConfig.enableIris)
|
||||
.addRequiredMod(TargetedMod.CHISEL)
|
||||
.addClientMixins(
|
||||
"chisel.MixinRenderCarvableBeacon"
|
||||
)
|
||||
),
|
||||
|
||||
ANGELICA_TEXTURE(new MixinBuilder()
|
||||
.setPhase(Phase.EARLY)
|
||||
.setApplyIf(() -> AngelicaConfig.enableIris || AngelicaConfig.enableCeleritas)
|
||||
|
||||
@@ -10,6 +10,7 @@ public enum TargetedMod implements ITargetMod {
|
||||
ARCHAICFIX("org.embeddedt.archaicfix.ArchaicCore", "archaicfix"),
|
||||
BACKHAND("xonin.backhand.coremod.BackhandLoadingPlugin", "backhand"),
|
||||
CAMPFIRE_BACKPORT(null, "campfirebackport"),
|
||||
CHISEL(null, "chisel"),
|
||||
COFHCORE( "cofh.asm.LoadingPlugin", "CoFHCore"),
|
||||
DYNAMIC_SURROUNDINGS_MIST("org.blockartistry.mod.DynSurround.mixinplugin.DynamicSurroundingsEarlyMixins", "dsurround"),
|
||||
DYNAMIC_SURROUNDINGS_ORIGINAL("org.blockartistry.mod.DynSurround.asm.TransformLoader", "dsurround"),
|
||||
|
||||
@@ -1,28 +1,45 @@
|
||||
package com.gtnewhorizons.angelica.render;
|
||||
|
||||
import com.gtnewhorizon.gtnhlib.client.renderer.vao.IVertexArrayObject;
|
||||
import com.gtnewhorizon.gtnhlib.client.renderer.vao.VertexBufferType;
|
||||
import com.gtnewhorizon.gtnhlib.client.renderer.vertex.DefaultVertexFormat;
|
||||
import com.gtnewhorizons.angelica.config.AngelicaConfig;
|
||||
import com.gtnewhorizons.angelica.glsm.GLStateManager;
|
||||
import com.gtnewhorizons.angelica.glsm.states.Color4;
|
||||
import com.gtnewhorizons.angelica.client.rendering.GlUniformFloat2v;
|
||||
import net.irisshaders.iris.api.v0.IrisApi;
|
||||
import net.minecraft.util.AxisAlignedBB;
|
||||
import org.embeddedt.embeddium.impl.gl.shader.GlProgram;
|
||||
import org.embeddedt.embeddium.impl.gl.shader.GlShader;
|
||||
import org.embeddedt.embeddium.impl.gl.shader.ShaderConstants;
|
||||
import org.embeddedt.embeddium.impl.gl.shader.ShaderType;
|
||||
import org.embeddedt.embeddium.impl.gl.shader.uniform.GlUniformFloat;
|
||||
import org.embeddedt.embeddium.impl.gl.shader.uniform.GlUniformFloat3v;
|
||||
import org.embeddedt.embeddium.impl.gl.shader.uniform.GlUniformFloat4v;
|
||||
import org.embeddedt.embeddium.impl.gl.shader.uniform.GlUniformMatrix4f;
|
||||
import org.embeddedt.embeddium.impl.render.shader.ShaderLoader;
|
||||
import org.joml.Matrix4f;
|
||||
import org.lwjgl.BufferUtils;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
public final class SelectionBoxRenderer {
|
||||
|
||||
private static GlProgram<SelectionBoxUniforms> program;
|
||||
private static int emptyVao;
|
||||
private static IVertexArrayObject vao;
|
||||
private static final Matrix4f mvpMatrix = new Matrix4f();
|
||||
private static final float[] colorBuf = new float[4];
|
||||
|
||||
private static final int VERT_COUNT = 24;
|
||||
private static final float[] UNIT_EDGES = {
|
||||
0,0,0, 1,0,0, 1,0,0, 1,0,1,
|
||||
1,0,1, 0,0,1, 0,0,1, 0,0,0,
|
||||
0,1,0, 1,1,0, 1,1,0, 1,1,1,
|
||||
1,1,1, 0,1,1, 0,1,1, 0,1,0,
|
||||
0,0,0, 0,1,0, 1,0,0, 1,1,0,
|
||||
1,0,1, 1,1,1, 0,0,1, 0,1,1
|
||||
};
|
||||
|
||||
private SelectionBoxRenderer() {}
|
||||
|
||||
public static void init() {
|
||||
@@ -40,8 +57,6 @@ public final class SelectionBoxRenderer {
|
||||
|
||||
program = builder.link(ctx -> new SelectionBoxUniforms(
|
||||
ctx.bindUniform("u_MVP", GlUniformMatrix4f::new),
|
||||
ctx.bindUniform("u_Min", GlUniformFloat3v::new),
|
||||
ctx.bindUniform("u_Max", GlUniformFloat3v::new),
|
||||
ctx.bindUniform("u_Color", GlUniformFloat4v::new),
|
||||
needsGS ? ctx.bindUniform("u_ViewportSize", GlUniformFloat2v::new) : null,
|
||||
needsGS ? ctx.bindUniform("u_LineWidth", GlUniformFloat::new) : null));
|
||||
@@ -50,20 +65,34 @@ public final class SelectionBoxRenderer {
|
||||
fs.destroy();
|
||||
if (gs != null) gs.destroy();
|
||||
|
||||
emptyVao = GLStateManager.glGenVertexArrays();
|
||||
final ByteBuffer buf = BufferUtils.createByteBuffer(UNIT_EDGES.length * Float.BYTES);
|
||||
buf.asFloatBuffer().put(UNIT_EDGES);
|
||||
vao = VertexBufferType.IMMUTABLE.allocate(DefaultVertexFormat.POSITION, GL11.GL_LINES, buf, VERT_COUNT);
|
||||
}
|
||||
|
||||
public static void draw(AxisAlignedBB aabb, int color) {
|
||||
if (program == null) return;
|
||||
if (program == null || vao == null) return;
|
||||
|
||||
final float minX = (float) aabb.minX, minY = (float) aabb.minY, minZ = (float) aabb.minZ;
|
||||
final float extX = (float) (aabb.maxX - aabb.minX);
|
||||
final float extY = (float) (aabb.maxY - aabb.minY);
|
||||
final float extZ = (float) (aabb.maxZ - aabb.minZ);
|
||||
|
||||
if (AngelicaConfig.enableIris && IrisApi.getInstance().isShaderPackInUse()) {
|
||||
drawThroughShader(minX, minY, minZ, extX, extY, extZ, color);
|
||||
} else {
|
||||
drawFast(minX, minY, minZ, extX, extY, extZ, color);
|
||||
}
|
||||
}
|
||||
|
||||
private static void drawFast(float minX, float minY, float minZ, float extX, float extY, float extZ, int color) {
|
||||
final SelectionBoxUniforms uniforms = program.getInterface();
|
||||
|
||||
program.bind();
|
||||
|
||||
GLStateManager.getProjectionMatrix().mul(GLStateManager.getModelViewMatrix(), mvpMatrix);
|
||||
mvpMatrix.translate(minX, minY, minZ).scale(extX, extY, extZ);
|
||||
uniforms.mvp.set(mvpMatrix);
|
||||
uniforms.min.set((float) aabb.minX, (float) aabb.minY, (float) aabb.minZ);
|
||||
uniforms.max.set((float) aabb.maxX, (float) aabb.maxY, (float) aabb.maxZ);
|
||||
|
||||
if (color != -1) {
|
||||
colorBuf[0] = ((color >> 16) & 0xFF) / 255.0f;
|
||||
@@ -84,25 +113,42 @@ public final class SelectionBoxRenderer {
|
||||
uniforms.lineWidth.setFloat(GLStateManager.getLineState().getWidth());
|
||||
}
|
||||
|
||||
GLStateManager.glBindVertexArray(emptyVao);
|
||||
GLStateManager.glDrawArrays(GL11.GL_LINES, 0, 24);
|
||||
GLStateManager.glBindVertexArray(0);
|
||||
vao.render();
|
||||
|
||||
program.unbind();
|
||||
}
|
||||
|
||||
private static void drawThroughShader(float minX, float minY, float minZ, float extX, float extY, float extZ, int color) {
|
||||
GLStateManager.glPushMatrix();
|
||||
GLStateManager.glTranslatef(minX, minY, minZ);
|
||||
GLStateManager.glScalef(extX, extY, extZ);
|
||||
|
||||
final Color4 prev = GLStateManager.getColor();
|
||||
final boolean overrideColor = color != -1;
|
||||
if (overrideColor) {
|
||||
GLStateManager.glColor4f(((color >> 16) & 0xFF) / 255.0f, ((color >> 8) & 0xFF) / 255.0f, (color & 0xFF) / 255.0f, 1.0f);
|
||||
}
|
||||
|
||||
vao.render();
|
||||
|
||||
if (overrideColor) {
|
||||
GLStateManager.glColor4f(prev.getRed(), prev.getGreen(), prev.getBlue(), prev.getAlpha());
|
||||
}
|
||||
GLStateManager.glPopMatrix();
|
||||
}
|
||||
|
||||
public static void destroy() {
|
||||
if (program != null) {
|
||||
program.destroy();
|
||||
program = null;
|
||||
}
|
||||
if (emptyVao != 0) {
|
||||
GLStateManager.glDeleteVertexArrays(emptyVao);
|
||||
emptyVao = 0;
|
||||
if (vao != null) {
|
||||
vao.delete();
|
||||
vao = null;
|
||||
}
|
||||
}
|
||||
|
||||
private record SelectionBoxUniforms(GlUniformMatrix4f mvp, GlUniformFloat3v min, GlUniformFloat3v max, GlUniformFloat4v color, GlUniformFloat2v viewportSize, GlUniformFloat lineWidth) {
|
||||
private record SelectionBoxUniforms(GlUniformMatrix4f mvp, GlUniformFloat4v color, GlUniformFloat2v viewportSize, GlUniformFloat lineWidth) {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -20,11 +20,7 @@ final class BlockOrientation extends RenderBlockState {
|
||||
// 1 2 3
|
||||
// c: coordinate (x,y,z) 0-2
|
||||
private static final int[][][] NEIGHBOR_OFFSET = new int[][][] {
|
||||
(
|
||||
fixedBottomFaceUV
|
||||
? makeNeighborOffset(EAST_FACE, SOUTH_FACE, WEST_FACE, NORTH_FACE) // BOTTOM_FACE fixedBottomFaceUV
|
||||
: makeNeighborOffset(WEST_FACE, SOUTH_FACE, EAST_FACE, NORTH_FACE) // BOTTOM_FACE not fixed
|
||||
),
|
||||
makeNeighborOffset(EAST_FACE, SOUTH_FACE, WEST_FACE, NORTH_FACE), // BOTTOM_FACE
|
||||
makeNeighborOffset(WEST_FACE, SOUTH_FACE, EAST_FACE, NORTH_FACE), // TOP_FACE
|
||||
makeNeighborOffset(EAST_FACE, BOTTOM_FACE, WEST_FACE, TOP_FACE), // NORTH_FACE
|
||||
makeNeighborOffset(WEST_FACE, BOTTOM_FACE, EAST_FACE, TOP_FACE), // SOUTH_FACE
|
||||
@@ -48,6 +44,7 @@ final class BlockOrientation extends RenderBlockState {
|
||||
private int textureFace;
|
||||
private int textureFaceOrig;
|
||||
private int rotateUV;
|
||||
private boolean flipBottom;
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
@@ -60,6 +57,7 @@ final class BlockOrientation extends RenderBlockState {
|
||||
offsetsComputed = false;
|
||||
haveOffsets = false;
|
||||
dx = dy = dz = 0;
|
||||
flipBottom = !fixedBottomFaceUV;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -104,7 +102,7 @@ final class BlockOrientation extends RenderBlockState {
|
||||
|
||||
@Override
|
||||
public int[] getOffset(int blockFace, int relativeDirection) {
|
||||
return NEIGHBOR_OFFSET[blockFace][rotateUV(relativeDirection)];
|
||||
return NEIGHBOR_OFFSET[flipBottom && blockFace == 0 ? 1 : blockFace][rotateUV(relativeDirection)];
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -147,6 +145,11 @@ final class BlockOrientation extends RenderBlockState {
|
||||
return haveOffsets;
|
||||
}
|
||||
|
||||
|
||||
public void setFlipBottom(){
|
||||
flipBottom = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldConnectByBlock(Block neighbor, int neighborX, int neighborY, int neighborZ) {
|
||||
return block == neighbor
|
||||
@@ -172,6 +175,7 @@ final class BlockOrientation extends RenderBlockState {
|
||||
copy.textureFace = textureFace;
|
||||
copy.textureFaceOrig = textureFaceOrig;
|
||||
copy.rotateUV = rotateUV;
|
||||
copy.flipBottom = flipBottom;
|
||||
|
||||
copy.blockAccess = blockAccess;
|
||||
copy.block = block;
|
||||
@@ -204,6 +208,7 @@ final class BlockOrientation extends RenderBlockState {
|
||||
rotateUV = 0;
|
||||
textureFace = blockFaceToTextureFace(blockFace);
|
||||
metadataBits = (1 << metadata) | (1 << altMetadata);
|
||||
flipBottom = !fixedBottomFaceUV;
|
||||
}
|
||||
|
||||
void setBlockMetadata(Block block, int metadata, int face) {
|
||||
|
||||
@@ -53,6 +53,9 @@ public final class CompactCtmQuadProcessor {
|
||||
}
|
||||
|
||||
public boolean processFace(RenderBlocks rb, RenderBlockState renderBlockState, IIcon origIcon) {
|
||||
if(renderBlockState instanceof BlockOrientation blockOrientation){
|
||||
blockOrientation.setFlipBottom();
|
||||
}
|
||||
int neighborBits = override.getNeighborBits(renderBlockState, origIcon);
|
||||
|
||||
int ctmIndex = TileOverride.neighborMap[neighborBits & 0xFF];
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -1,19 +1,9 @@
|
||||
#version 330 core
|
||||
|
||||
uniform mat4 u_MVP;
|
||||
uniform vec3 u_Min;
|
||||
uniform vec3 u_Max;
|
||||
layout(location = 0) in vec3 a_Position;
|
||||
|
||||
const vec3 edges[24] = vec3[24](
|
||||
vec3(0,0,0), vec3(1,0,0), vec3(1,0,0), vec3(1,0,1),
|
||||
vec3(1,0,1), vec3(0,0,1), vec3(0,0,1), vec3(0,0,0),
|
||||
vec3(0,1,0), vec3(1,1,0), vec3(1,1,0), vec3(1,1,1),
|
||||
vec3(1,1,1), vec3(0,1,1), vec3(0,1,1), vec3(0,1,0),
|
||||
vec3(0,0,0), vec3(0,1,0), vec3(1,0,0), vec3(1,1,0),
|
||||
vec3(1,0,1), vec3(1,1,1), vec3(0,0,1), vec3(0,1,1)
|
||||
);
|
||||
uniform mat4 u_MVP;
|
||||
|
||||
void main() {
|
||||
vec3 pos = mix(u_Min, u_Max, edges[gl_VertexID]);
|
||||
gl_Position = u_MVP * vec4(pos, 1.0);
|
||||
gl_Position = u_MVP * vec4(a_Position, 1.0);
|
||||
}
|
||||
@@ -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)
|
||||
|
||||
+28
@@ -2,11 +2,14 @@ package com.gtnewhorizons.angelica.mixins.early.shaders;
|
||||
|
||||
import net.coderbot.iris.gbuffer_overrides.matching.SpecialCondition;
|
||||
import net.coderbot.iris.layer.GbufferPrograms;
|
||||
import net.minecraft.client.renderer.Tessellator;
|
||||
import net.minecraft.client.renderer.tileentity.TileEntityBeaconRenderer;
|
||||
import net.minecraft.tileentity.TileEntityBeacon;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Unique;
|
||||
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;
|
||||
|
||||
@Mixin(TileEntityBeaconRenderer.class)
|
||||
@@ -22,5 +25,30 @@ public class MixinTileEntityBeaconRenderer {
|
||||
GbufferPrograms.teardownSpecialRenderCondition();
|
||||
}
|
||||
|
||||
/**
|
||||
* Whoever wrote this part of vanilla code sucks. Just change the alpha my guy.
|
||||
*/
|
||||
@Redirect(
|
||||
method = "Lnet/minecraft/client/renderer/tileentity/TileEntityBeaconRenderer;renderTileEntityAt(Lnet/minecraft/tileentity/TileEntityBeacon;DDDF)V",
|
||||
at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/Tessellator;setColorRGBA(IIII)V", ordinal = 0))
|
||||
private void angelica$innerBeamColor(Tessellator tessellator, int r, int g, int b, int a) {
|
||||
angelica$beamColor(tessellator, r, g, b, 255);
|
||||
}
|
||||
|
||||
@Redirect(
|
||||
method = "Lnet/minecraft/client/renderer/tileentity/TileEntityBeaconRenderer;renderTileEntityAt(Lnet/minecraft/tileentity/TileEntityBeacon;DDDF)V",
|
||||
at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/Tessellator;setColorRGBA(IIII)V", ordinal = 1))
|
||||
private void angelica$outerBeamColor(Tessellator tessellator, int r, int g, int b, int a) {
|
||||
angelica$beamColor(tessellator, r, g, b, a);
|
||||
}
|
||||
|
||||
/**
|
||||
* Make beam fullbright.
|
||||
*/
|
||||
@Unique
|
||||
private void angelica$beamColor(Tessellator tessellator, int r, int g, int b, int a) {
|
||||
tessellator.setColorRGBA(r, g, b, a);
|
||||
tessellator.setBrightness(0x00F000F0);
|
||||
}
|
||||
|
||||
}
|
||||
+52
@@ -0,0 +1,52 @@
|
||||
package com.gtnewhorizons.angelica.mixins.late.chisel;
|
||||
|
||||
import net.coderbot.iris.gbuffer_overrides.matching.SpecialCondition;
|
||||
import net.coderbot.iris.layer.GbufferPrograms;
|
||||
import net.minecraft.client.renderer.Tessellator;
|
||||
import net.minecraft.world.World;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Pseudo;
|
||||
import org.spongepowered.asm.mixin.Unique;
|
||||
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;
|
||||
|
||||
/**
|
||||
* Chisel ships its own beacon beam renderer, we yoink a lot of the code from
|
||||
* {@link com.gtnewhorizons.angelica.mixins.early.shaders.MixinTileEntityBeaconRenderer} to apply the same fixes here.
|
||||
*/
|
||||
@Pseudo
|
||||
@Mixin(targets = { "team.chisel.client.render.tile.RenderCarvableBeacon" }, remap = false)
|
||||
public class MixinRenderCarvableBeacon {
|
||||
|
||||
@Inject(method = "renderBeam(FLnet/minecraft/world/World;DDDIF)V", at = @At("HEAD"))
|
||||
private void angelica$beginBeaconBeam(float f1, World world, double x, double y, double z, int meta, float partialTicks, CallbackInfo ci) {
|
||||
GbufferPrograms.setupSpecialRenderCondition(SpecialCondition.BEACON_BEAM);
|
||||
}
|
||||
|
||||
@Inject(method = "renderBeam(FLnet/minecraft/world/World;DDDIF)V", at = @At("RETURN"))
|
||||
private void angelica$endBeaconBeam(float f1, World world, double x, double y, double z, int meta, float partialTicks, CallbackInfo ci) {
|
||||
GbufferPrograms.teardownSpecialRenderCondition();
|
||||
}
|
||||
|
||||
@Redirect(
|
||||
method = "renderBeam(FLnet/minecraft/world/World;DDDIF)V",
|
||||
at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/Tessellator;setColorRGBA(IIII)V", ordinal = 0, remap = true))
|
||||
private void angelica$innerBeamColor(Tessellator tessellator, int r, int g, int b, int a) {
|
||||
angelica$beamColor(tessellator, r, g, b, 255);
|
||||
}
|
||||
|
||||
@Redirect(
|
||||
method = "renderBeam(FLnet/minecraft/world/World;DDDIF)V",
|
||||
at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/Tessellator;setColorRGBA(IIII)V", ordinal = 1, remap = true))
|
||||
private void angelica$outerBeamColor(Tessellator tessellator, int r, int g, int b, int a) {
|
||||
angelica$beamColor(tessellator, r, g, b, a);
|
||||
}
|
||||
|
||||
@Unique
|
||||
private void angelica$beamColor(Tessellator tessellator, int r, int g, int b, int a) {
|
||||
tessellator.setColorRGBA(r, g, b, a);
|
||||
tessellator.setBrightness(0x00F000F0);
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user