Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
28 changes: 28 additions & 0 deletions src/client/java/org/infinite/mixin/infinite/gui/ScreenMixin.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package org.infinite.mixin.infinite.gui;

import net.minecraft.client.gui.DrawContext;
import net.minecraft.client.gui.screen.Screen;
import net.minecraft.util.math.ColorHelper;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;

@Mixin(Screen.class)
public abstract class ScreenMixin {

/**
* Replace vanilla panorama background with a simple dark gradient for all menu screens
* (singleplayer, multiplayer, etc.). TitleScreen has its own mixin, so this covers the rest.
*/
@Inject(method = "renderPanoramaBackground", at = @At("HEAD"), cancellable = true)
private void infiniteClient$renderBlackBackground(
DrawContext context, float delta, CallbackInfo ci) {
int width = context.getScaledWindowWidth();
int height = context.getScaledWindowHeight();
int top = ColorHelper.getArgb(255, 8, 10, 14);
int bottom = ColorHelper.getArgb(255, 0, 0, 0);
context.fillGradient(0, 0, width, height, top, bottom);
ci.cancel();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
package org.infinite.mixin.infinite.gui;

import com.mojang.blaze3d.pipeline.RenderPipeline;
import com.mojang.blaze3d.systems.CommandEncoder;
import com.mojang.blaze3d.textures.GpuTexture;
import net.minecraft.client.gui.DrawContext;
import net.minecraft.client.gui.screen.SplashOverlay;
import org.infinite.global.rendering.theme.overlay.InfiniteLoadingScreenRenderer;
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;

@Mixin(SplashOverlay.class)
public abstract class SplashOverlayMixin {
@Shadow private float progress;
@Shadow private long reloadCompleteTime;
@Shadow private long reloadStartTime;
@Shadow private boolean reloading;

@Inject(method = "render", at = @At("TAIL"))
private void infiniteClient$overlay(
DrawContext context, int mouseX, int mouseY, float delta, CallbackInfo ci) {
// Draw our overlay after vanilla so we fully cover Mojang while still letting progress update.
InfiniteLoadingScreenRenderer.render(
context, this.progress, this.reloadStartTime, this.reloadCompleteTime, this.reloading);
}

// Suppress vanilla splash drawing while keeping its logic (progress, completion) intact.
@Redirect(
method = "render",
at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/DrawContext;fill(IIIII)V"))
private void infiniteClient$skipVanillaFill(
DrawContext instance, int x1, int y1, int x2, int y2, int color) {
// no-op to hide Mojang background
}

@Redirect(
method = "render",
at =
@At(
value = "INVOKE",
target =
"Lnet/minecraft/client/gui/DrawContext;drawTexture(Lcom/mojang/blaze3d/pipeline/RenderPipeline;Lnet/minecraft/util/Identifier;IIFFIIIIIII)V"))
private void infiniteClient$skipVanillaTexture(
DrawContext instance,
RenderPipeline pipeline,
net.minecraft.util.Identifier id,
int x,
int y,
float u,
float v,
int width,
int height,
int regionWidth,
int regionHeight,
int textureWidth,
int textureHeight,
int color) {
// no-op to hide Mojang logos
}

@Redirect(
method = "render",
at =
@At(
value = "INVOKE",
target =
"Lnet/minecraft/client/gui/screen/SplashOverlay;renderProgressBar(Lnet/minecraft/client/gui/DrawContext;IIIIF)V"))
private void infiniteClient$skipVanillaProgressBar(
SplashOverlay self,
DrawContext context,
int minX,
int minY,
int maxX,
int maxY,
float opacity) {
// no-op to hide Mojang progress bar
}

@Redirect(
method = "render",
at =
@At(
value = "INVOKE",
target =
"Lcom/mojang/blaze3d/systems/CommandEncoder;clearColorTexture(Lcom/mojang/blaze3d/textures/GpuTexture;I)V"))
private void infiniteClient$skipVanillaClear(
CommandEncoder encoder, GpuTexture texture, int argb) {
// no-op to avoid the brand red clear
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
package org.infinite.mixin.infinite.gui;

import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;
import net.minecraft.client.gl.RenderPipelines;
import net.minecraft.client.gui.DrawContext;
import net.minecraft.client.gui.screen.TitleScreen;
import net.minecraft.util.Identifier;
import net.minecraft.util.math.ColorHelper;
import org.infinite.InfiniteClient;
import org.infinite.global.rendering.loading.LoadingAnimationSetting;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At;

@Mixin(TitleScreen.class)
public abstract class TitleScreenMixin {
@Unique private static final Identifier INFINITE_ICON = Identifier.of("infinite", "icon.png");

@WrapOperation(
method = "render",
at =
@At(
value = "INVOKE",
target =
"Lnet/minecraft/client/gui/screen/TitleScreen;renderPanoramaBackground(Lnet/minecraft/client/gui/DrawContext;F)V"))
private void infiniteClient$replacePanorama(
TitleScreen instance, DrawContext drawContext, float v, Operation<Void> original) {
if (!InfiniteClient.INSTANCE.isGlobalFeatureEnabled(LoadingAnimationSetting.class)) {
original.call(instance, drawContext, v);
return;
}
// --- カスタム描画処理(オリジナルのコード) ---
int width = drawContext.getScaledWindowWidth();
int height = drawContext.getScaledWindowHeight();

// ぼかし効果の追加(前回の回答の修正案から追加)
int blurOverlayColor = 0x40000000;
drawContext.fill(0, 0, width, height, blurOverlayColor);

int top = ColorHelper.getArgb(208, 8, 10, 14);
int bottom = ColorHelper.getArgb(208, 0, 0, 0);
drawContext.fillGradient(0, 0, width, height, top, bottom);

int size = Math.min(width, height) / 3;
size = Math.max(96, Math.min(size, 180));
int x = (width - size) / 2;
int y = Math.max(height / 5, (height - size) / 2);
int logoColor = ColorHelper.getArgb(80, 255, 255, 255);

drawContext.drawTexture(
RenderPipelines.GUI_TEXTURED,
INFINITE_ICON,
x,
y,
0f,
0f,
size,
size,
256,
256,
256,
256,
logoColor);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package org.infinite.global.rendering
import org.infinite.global.GlobalFeature
import org.infinite.global.GlobalFeatureCategory
import org.infinite.global.rendering.font.FontSetting
import org.infinite.global.rendering.loading.LoadingAnimationSetting
import org.infinite.global.rendering.theme.ThemeSetting

class GlobalRenderingFeatureCategory :
Expand All @@ -11,5 +12,6 @@ class GlobalRenderingFeatureCategory :
mutableListOf(
GlobalFeature(ThemeSetting()),
GlobalFeature(FontSetting()),
GlobalFeature(LoadingAnimationSetting()),
),
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package org.infinite.global.rendering.loading

import org.infinite.global.ConfigurableGlobalFeature
import org.infinite.settings.FeatureSetting

class LoadingAnimationSetting : ConfigurableGlobalFeature() {
override val settings: List<FeatureSetting<*>> = listOf()
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
package org.infinite.global.rendering.theme.overlay

import net.minecraft.client.MinecraftClient
import net.minecraft.client.gl.RenderPipelines
import net.minecraft.client.gui.DrawContext
import net.minecraft.text.Text
import net.minecraft.util.Identifier
import net.minecraft.util.Util
import net.minecraft.util.math.ColorHelper
import kotlin.math.min
import kotlin.math.roundToInt

/**
* Renders an animated loading screen using a sequence of image textures.
*/
object InfiniteLoadingScreenRenderer {
private var fallbackCompleteTime: Long = -1

private const val ANIMATION_FRAMES_COUNT = 360 // animation-0000.png から animation-0359.png まで
private const val ANIMATION_FRAME_DURATION_MS = 30L // フレーム表示時間 (ms)
private const val TEXTURE_SIZE = 512 // テクスチャのサイズ (512x512)

private val animationTextures: List<Identifier> by lazy {
(0 until ANIMATION_FRAMES_COUNT).map { i ->
Identifier.of("infinite", "textures/gui/loading_animations/animation-${String.format("%04d", i)}.png")
}
}

@JvmStatic
fun render(
context: DrawContext,
progress: Float,
reloadStartTime: Long,
reloadCompleteTime: Long,
reloading: Boolean,
) {
val now = Util.getMeasuringTimeMs()
val completeMark =
if (reloadCompleteTime > -1) {
fallbackCompleteTime = -1
reloadCompleteTime
} else {
if (!reloading && progress >= 0.999f) {
if (fallbackCompleteTime == -1L) fallbackCompleteTime = now
} else {
fallbackCompleteTime = -1
}
fallbackCompleteTime
}

val fadeIn = if (reloadStartTime > -1) ((now - reloadStartTime).toFloat() / 400f).coerceIn(0f, 1f) else 1f
val fadeOut = if (completeMark > -1) (1f - ((now - completeMark).toFloat() / 800f)).coerceIn(0f, 1f) else 1f
val alpha = (fadeIn * fadeOut).coerceIn(0f, 1f)
if (alpha <= 0f) return

val width = context.scaledWindowWidth
val height = context.scaledWindowHeight

val textRenderer = MinecraftClient.getInstance().textRenderer
val topColor = ColorHelper.getArgb((255 * alpha).roundToInt(), 8, 10, 14)
val bottomColor = ColorHelper.getArgb((255 * alpha).roundToInt(), 0, 0, 0)
context.fillGradient(0, 0, width, height, topColor, bottomColor)

// アニメーション画像の描画
val currentFrameIndex = ((now / ANIMATION_FRAME_DURATION_MS) % ANIMATION_FRAMES_COUNT).toInt()
val texture = animationTextures[currentFrameIndex]

val displaySize = (min(width, height) * 0.5f).roundToInt() // 画面の小さい方に合わせて表示サイズを調整
val textureX = (width - displaySize) / 2
val textureY = (height - displaySize) / 2 - (height * 0.1f).roundToInt() // 少し上に表示

context.drawTexture(
RenderPipelines.GUI_TEXTURED,
texture,
textureX,
textureY,
0f,
0f,
displaySize,
displaySize,
displaySize,
displaySize,
TEXTURE_SIZE,
TEXTURE_SIZE,
)

val titleAlpha = (255 * alpha).roundToInt()
val title = Text.literal("Infinite Client")
context.drawCenteredTextWithShadow(
textRenderer,
title,
width / 2,
textureY + displaySize + 12, // アニメーション画像の下に表示
ColorHelper.getArgb(titleAlpha, 255, 255, 255),
)

val subtitleText =
if (reloading) {
Text.literal("Loading resources...")
} else {
Text.literal("Finishing setup...")
}
context.drawCenteredTextWithShadow(
textRenderer,
subtitleText,
width / 2,
textureY + displaySize + 26, // タイトルの下に表示
ColorHelper.getArgb((210 * alpha).roundToInt(), 180, 180, 180),
)

val progressBarWidth = (width * 0.55f).roundToInt()
val progressBarHeight = 7
val progressBarX = (width - progressBarWidth) / 2
val progressBarY = (height * 0.68f).roundToInt()
val baseBarColor = ColorHelper.getArgb((80 * alpha).roundToInt(), 255, 255, 255)
context.fill(progressBarX, progressBarY, progressBarX + progressBarWidth, progressBarY + progressBarHeight, baseBarColor)

val clampedProgress = progress.coerceIn(0f, 1f)
val filledWidth = (progressBarWidth * clampedProgress).roundToInt()
val fillColor = ColorHelper.getArgb((230 * alpha).roundToInt(), 255, 255, 255)
if (filledWidth > 0) {
context.fill(progressBarX, progressBarY, progressBarX + filledWidth, progressBarY + progressBarHeight, fillColor)
}

val percentText = "${(clampedProgress * 100f).roundToInt()}%"
context.drawCenteredTextWithShadow(
textRenderer,
Text.literal("$percentText • Infinite"),
width / 2,
progressBarY + progressBarHeight + 8,
ColorHelper.getArgb((200 * alpha).roundToInt(), 210, 210, 210),
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,26 +17,19 @@ class LoadingWidgetRenderer(
delta: Float,
) {
val graphics2D = Graphics2D(context, MinecraftClient.getInstance().renderTickCounter) // Instantiate Graphics2D

val x = widget.x
val y = widget.y
val width = widget.width
val height = widget.height
val hovered = widget.isHovered
val colors: ThemeColors = InfiniteClient.currentColors()

// テーマとホバー状態に基づいて色を決定
var backgroundColor = colors.backgroundColor
var borderColor = colors.primaryColor

if (hovered) {
backgroundColor = colors.primaryColor
}

// カスタム背景の描画
graphics2D.fill(x, y, width, height, backgroundColor)

// カスタムボーダーの描画
val borderWidth = 1 // 枠線の太さ
graphics2D.drawBorder(x, y, width, height, borderColor, borderWidth)
}
Expand Down
6 changes: 4 additions & 2 deletions src/client/resources/infinite.client.mixins.json
Original file line number Diff line number Diff line change
Expand Up @@ -61,12 +61,14 @@
"infinite.gui.ScrollableWidgetMixin",
"infinite.gui.SliderWidgetMixin",
"infinite.gui.TextFieldWidgetMixin",
"infinite.gui.SplashOverlayMixin",
"infinite.gui.ScreenMixin",
"infinite.gui.TitleScreenMixin",
"infinite.interfaces.WorldRendererMixin",
"infinite.settings.OptionsScreenMixin",
"infinite.world.ClientPlayNetworkHandlerMixin"
],
"injectors": {
"defaultRequire": 1
},
"mixins": []
}
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Loading