From 998c54b1abd51b473c6670dd3b6304d4793c4677 Mon Sep 17 00:00:00 2001 From: SuperSkidder Date: Sat, 5 Apr 2025 11:05:35 +0800 Subject: [PATCH 001/193] fix: gradle build error --- v1.8.9/build.gradle.kts | 2 +- v1.8.9/settings.gradle.kts | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/v1.8.9/build.gradle.kts b/v1.8.9/build.gradle.kts index 4e7c6748..bb4d5404 100644 --- a/v1.8.9/build.gradle.kts +++ b/v1.8.9/build.gradle.kts @@ -3,7 +3,7 @@ import org.apache.commons.lang3.SystemUtils plugins { idea java - id("gg.essential.loom") version "0.10.0.+" + id("gg.essential.loom") version "0.10.0.5" id("dev.architectury.architectury-pack200") version "0.1.3" id("com.github.johnrengelman.shadow") version "8.1.1" id("com.gorylenko.gradle-git-properties") version "2.3.2" diff --git a/v1.8.9/settings.gradle.kts b/v1.8.9/settings.gradle.kts index 5f2c4348..2d05641f 100644 --- a/v1.8.9/settings.gradle.kts +++ b/v1.8.9/settings.gradle.kts @@ -2,6 +2,7 @@ pluginManagement { repositories { mavenCentral() gradlePluginPortal() + maven("https://repo.polyfrost.cc/releases/") maven("https://oss.sonatype.org/content/repositories/snapshots") maven("https://maven.architectury.dev/") maven("https://maven.fabricmc.net") From 0ce119825a08a84e82ca5aa4998d82ae0264c4eb Mon Sep 17 00:00:00 2001 From: SuperSkidder Date: Sat, 5 Apr 2025 11:10:46 +0800 Subject: [PATCH 002/193] change: copyright info, remove ai panel temporarily --- shared/java/top/fpsmaster/FPSMaster.java | 2 +- shared/java/top/fpsmaster/ui/click/MainPanel.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/shared/java/top/fpsmaster/FPSMaster.java b/shared/java/top/fpsmaster/FPSMaster.java index faeadf49..fea993c2 100644 --- a/shared/java/top/fpsmaster/FPSMaster.java +++ b/shared/java/top/fpsmaster/FPSMaster.java @@ -38,7 +38,7 @@ public class FPSMaster { public static final String SERVICE_API = "https://service.fpsmaster.top"; public static final String EDITION = Constants.EDITION; - public static final String COPYRIGHT = "Copyright ©2020-2024 FPSMaster Team All Rights Reserved."; + public static final String COPYRIGHT = "Copyright ©2020-2025 FPSMaster Team All Rights Reserved."; public static FPSMaster INSTANCE = new FPSMaster(); diff --git a/shared/java/top/fpsmaster/ui/click/MainPanel.java b/shared/java/top/fpsmaster/ui/click/MainPanel.java index ffbe66bd..7b36b860 100644 --- a/shared/java/top/fpsmaster/ui/click/MainPanel.java +++ b/shared/java/top/fpsmaster/ui/click/MainPanel.java @@ -76,7 +76,7 @@ public MainPanel() { @Override public void render(int mouseX, int mouseY, float partialTicks) { - aiChatPanel.render(mouseX, mouseY, scaleFactor); + //aiChatPanel.render(mouseX, mouseY, scaleFactor); if (!Mouse.isButtonDown(0)) { dragLock = "null"; From a1f556fd9a77233e4ce7b9e596e4cbf752ed9e9a Mon Sep 17 00:00:00 2001 From: Leng <110669856+xiaoshaziYA@users.noreply.github.com> Date: Sat, 5 Apr 2025 13:59:35 +0800 Subject: [PATCH 003/193] Update AbstractResourcePackMixin_DownscaleImages.java --- ...ractResourcePackMixin_DownscaleImages.java | 62 +++++++++++++++++-- 1 file changed, 56 insertions(+), 6 deletions(-) diff --git a/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/AbstractResourcePackMixin_DownscaleImages.java b/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/AbstractResourcePackMixin_DownscaleImages.java index 301e09c8..994991d5 100644 --- a/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/AbstractResourcePackMixin_DownscaleImages.java +++ b/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/AbstractResourcePackMixin_DownscaleImages.java @@ -21,24 +21,74 @@ public abstract class AbstractResourcePackMixin_DownscaleImages { @Inject(method = "getPackImage", at = @At("HEAD"), cancellable = true) private void patcher$downscalePackImage(CallbackInfoReturnable cir) throws IOException { - // 这个影响不明显,暂时先不加额外的选项了,默认开启 -// if (!Performance.downscalePackImages.value) return; - BufferedImage image = TextureUtil.readBufferedImage(this.getInputStreamByName("pack.png")); if (image == null) { cir.setReturnValue(null); return; } + // 检查是否是特殊材质(如附魔效果) + if (isSpecialTexture(image)) { + cir.setReturnValue(image); + return; + } + + // 如果图片尺寸已经小于等于64x64,直接返回原图 if (image.getWidth() <= 64 && image.getHeight() <= 64) { cir.setReturnValue(image); return; } + // 正常缩放其他图片 BufferedImage downscaledIcon = new BufferedImage(64, 64, BufferedImage.TYPE_INT_ARGB); - Graphics graphics = downscaledIcon.getGraphics(); - graphics.drawImage(image, 0, 0, 64, 64, null); - graphics.dispose(); + Graphics2D graphics = downscaledIcon.createGraphics(); + try { + // 设置更好的渲染质量 + graphics.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR); + graphics.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY); + graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + graphics.drawImage(image, 0, 0, 64, 64, null); + } finally { + graphics.dispose(); + } cir.setReturnValue(downscaledIcon); } + + /** + * 检查是否为特殊材质(如附魔效果) + * @param image 要检查的图片 + * @return 如果是特殊材质返回true + */ + private boolean isSpecialTexture(BufferedImage image) { + // 检查图片是否具有半透明像素(附魔效果通常有) + if (hasSemiTransparentPixels(image)) { + return true; + } + + // 可以添加其他特殊材质的检测条件 + return false; + } + + /** + * 检查图片是否包含半透明像素 + * @param image 要检查的图片 + * @return 如果包含半透明像素返回true + */ + private boolean hasSemiTransparentPixels(BufferedImage image) { + int width = image.getWidth(); + int height = image.getHeight(); + + // 只检查部分像素以提高性能 + for (int x = 0; x < width; x += Math.max(1, width / 10)) { + for (int y = 0; y < height; y += Math.max(1, height / 10)) { + int pixel = image.getRGB(x, y); + int alpha = (pixel >> 24) & 0xff; + // 如果有半透明像素(既不全透明也不全不透明) + if (alpha > 0 && alpha < 255) { + return true; + } + } + } + return false; + } } From 1086a1918471e7e52ce7e188d254d9d1f6b3fc66 Mon Sep 17 00:00:00 2001 From: Leng <110669856+xiaoshaziYA@users.noreply.github.com> Date: Sat, 5 Apr 2025 14:03:30 +0800 Subject: [PATCH 004/193] Update MixinGuiIngame.java --- .../fpsmaster/forge/mixin/MixinGuiIngame.java | 72 +++++++++++++++++++ 1 file changed, 72 insertions(+) diff --git a/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinGuiIngame.java b/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinGuiIngame.java index 5aec71f6..964c3d83 100644 --- a/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinGuiIngame.java +++ b/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinGuiIngame.java @@ -1,8 +1,12 @@ package top.fpsmaster.forge.mixin; +import net.minecraft.client.Minecraft; +import net.minecraft.client.audio.PositionedSoundRecord; import net.minecraft.client.gui.GuiIngame; import net.minecraft.client.gui.ScaledResolution; +import net.minecraft.client.network.NetHandlerPlayClient; import net.minecraft.scoreboard.ScoreObjective; +import net.minecraft.util.ResourceLocation; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; @@ -12,12 +16,21 @@ import top.fpsmaster.event.events.EventRender2D; import top.fpsmaster.features.impl.interfaces.Scoreboard; import top.fpsmaster.features.impl.render.Crosshair; +import top.fpsmaster.utils.render.Render2DUtils; +import top.fpsmaster.utils.render.font.FontManager; + +import java.awt.*; @Mixin(GuiIngame.class) public class MixinGuiIngame { + private static final ResourceLocation BUTTON_CLICK_SOUND = new ResourceLocation("gui.button.press"); + @Inject(method = "renderTooltip", at = @At("RETURN")) private void renderTooltipPost(ScaledResolution sr, float partialTicks, CallbackInfo callbackInfo) { EventDispatcher.dispatchEvent(new EventRender2D(partialTicks)); + + // 渲染服务器延迟信息 + renderPingInfo(sr); } @Inject(method = "showCrosshair", at = @At("HEAD"), cancellable = true) @@ -31,4 +44,63 @@ public void scoreboard(ScoreObjective objective, ScaledResolution scaledRes, Cal if (Scoreboard.using) ci.cancel(); } + + /** + * 渲染服务器延迟信息 + */ + private void renderPingInfo(ScaledResolution sr) { + NetHandlerPlayClient netHandler = Minecraft.getMinecraft().getNetHandler(); + if (netHandler != null) { + int ping = netHandler.getPlayerInfo(Minecraft.getMinecraft().thePlayer.getUniqueID()).getResponseTime(); + String pingText = "延迟: " + ping + "ms"; + + // 根据延迟值设置颜色 + int color; + if (ping < 100) { + color = Color.GREEN.getRGB(); + } else if (ping < 200) { + color = Color.YELLOW.getRGB(); + } else { + color = Color.RED.getRGB(); + } + + // 在屏幕右上角显示延迟 + FontManager.fontRegular.drawStringWithShadow( + pingText, + sr.getScaledWidth() - FontManager.fontRegular.getStringWidth(pingText) - 5, + 5, + color + ); + } + } + + /** + * 播放按钮点击音效 + */ + public static void playButtonClickSound() { + Minecraft.getMinecraft().getSoundHandler().playSound( + PositionedSoundRecord.create(BUTTON_CLICK_SOUND, 1.0F) + ); + } + + /** + * 缩小按钮渲染方法 + */ + public static void drawScaledButton(int x, int y, int width, int height, int color) { + // 缩小按钮尺寸(原尺寸的80%) + float scale = 0.8f; + int scaledWidth = (int)(width * scale); + int scaledHeight = (int)(height * scale); + int xOffset = (width - scaledWidth) / 2; + int yOffset = (height - scaledHeight) / 2; + + Render2DUtils.drawRoundedRect( + x + xOffset, + y + yOffset, + x + xOffset + scaledWidth, + y + yOffset + scaledHeight, + 2, + color + ); + } } From c87cad30a8d32632c435bee9ec9ea4caac90621e Mon Sep 17 00:00:00 2001 From: Leng <110669856+xiaoshaziYA@users.noreply.github.com> Date: Sat, 5 Apr 2025 14:05:30 +0800 Subject: [PATCH 005/193] =?UTF-8?q?=E5=9B=9E=E6=BB=9A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../fpsmaster/forge/mixin/MixinGuiIngame.java | 72 ------------------- 1 file changed, 72 deletions(-) diff --git a/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinGuiIngame.java b/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinGuiIngame.java index 964c3d83..5aec71f6 100644 --- a/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinGuiIngame.java +++ b/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinGuiIngame.java @@ -1,12 +1,8 @@ package top.fpsmaster.forge.mixin; -import net.minecraft.client.Minecraft; -import net.minecraft.client.audio.PositionedSoundRecord; import net.minecraft.client.gui.GuiIngame; import net.minecraft.client.gui.ScaledResolution; -import net.minecraft.client.network.NetHandlerPlayClient; import net.minecraft.scoreboard.ScoreObjective; -import net.minecraft.util.ResourceLocation; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; @@ -16,21 +12,12 @@ import top.fpsmaster.event.events.EventRender2D; import top.fpsmaster.features.impl.interfaces.Scoreboard; import top.fpsmaster.features.impl.render.Crosshair; -import top.fpsmaster.utils.render.Render2DUtils; -import top.fpsmaster.utils.render.font.FontManager; - -import java.awt.*; @Mixin(GuiIngame.class) public class MixinGuiIngame { - private static final ResourceLocation BUTTON_CLICK_SOUND = new ResourceLocation("gui.button.press"); - @Inject(method = "renderTooltip", at = @At("RETURN")) private void renderTooltipPost(ScaledResolution sr, float partialTicks, CallbackInfo callbackInfo) { EventDispatcher.dispatchEvent(new EventRender2D(partialTicks)); - - // 渲染服务器延迟信息 - renderPingInfo(sr); } @Inject(method = "showCrosshair", at = @At("HEAD"), cancellable = true) @@ -44,63 +31,4 @@ public void scoreboard(ScoreObjective objective, ScaledResolution scaledRes, Cal if (Scoreboard.using) ci.cancel(); } - - /** - * 渲染服务器延迟信息 - */ - private void renderPingInfo(ScaledResolution sr) { - NetHandlerPlayClient netHandler = Minecraft.getMinecraft().getNetHandler(); - if (netHandler != null) { - int ping = netHandler.getPlayerInfo(Minecraft.getMinecraft().thePlayer.getUniqueID()).getResponseTime(); - String pingText = "延迟: " + ping + "ms"; - - // 根据延迟值设置颜色 - int color; - if (ping < 100) { - color = Color.GREEN.getRGB(); - } else if (ping < 200) { - color = Color.YELLOW.getRGB(); - } else { - color = Color.RED.getRGB(); - } - - // 在屏幕右上角显示延迟 - FontManager.fontRegular.drawStringWithShadow( - pingText, - sr.getScaledWidth() - FontManager.fontRegular.getStringWidth(pingText) - 5, - 5, - color - ); - } - } - - /** - * 播放按钮点击音效 - */ - public static void playButtonClickSound() { - Minecraft.getMinecraft().getSoundHandler().playSound( - PositionedSoundRecord.create(BUTTON_CLICK_SOUND, 1.0F) - ); - } - - /** - * 缩小按钮渲染方法 - */ - public static void drawScaledButton(int x, int y, int width, int height, int color) { - // 缩小按钮尺寸(原尺寸的80%) - float scale = 0.8f; - int scaledWidth = (int)(width * scale); - int scaledHeight = (int)(height * scale); - int xOffset = (width - scaledWidth) / 2; - int yOffset = (height - scaledHeight) / 2; - - Render2DUtils.drawRoundedRect( - x + xOffset, - y + yOffset, - x + xOffset + scaledWidth, - y + yOffset + scaledHeight, - 2, - color - ); - } } From 4c19b2aac61748b388e92ac38866315c8d570531 Mon Sep 17 00:00:00 2001 From: SuperSkidder Date: Sun, 6 Oct 2024 10:19:12 +0800 Subject: [PATCH 006/193] MusicOverlay --- .../features/impl/interfaces/MusicOverlay.kt | 34 ++++ .../fpsmaster/modules/music/IngameOverlay.kt | 76 ++++++++ .../fpsmaster/modules/music/JLayerHelper.kt | 180 ++++++++++++++++++ .../fpsmaster/modules/music/MusicPlayer.kt | 69 +++++++ .../top/fpsmaster/utils/os/HttpRequest.kt | 152 +++++++++++++++ v1.12.2/build.gradle.kts | 3 + v1.8.9/build.gradle.kts | 4 + 7 files changed, 518 insertions(+) create mode 100644 shared/java/top/fpsmaster/features/impl/interfaces/MusicOverlay.kt create mode 100644 shared/java/top/fpsmaster/modules/music/IngameOverlay.kt create mode 100644 shared/java/top/fpsmaster/modules/music/JLayerHelper.kt create mode 100644 shared/java/top/fpsmaster/modules/music/MusicPlayer.kt create mode 100644 shared/java/top/fpsmaster/utils/os/HttpRequest.kt diff --git a/shared/java/top/fpsmaster/features/impl/interfaces/MusicOverlay.kt b/shared/java/top/fpsmaster/features/impl/interfaces/MusicOverlay.kt new file mode 100644 index 00000000..52a3f177 --- /dev/null +++ b/shared/java/top/fpsmaster/features/impl/interfaces/MusicOverlay.kt @@ -0,0 +1,34 @@ +package top.fpsmaster.features.impl.interfaces + +import top.fpsmaster.event.Subscribe +import top.fpsmaster.event.events.EventRender2D +import top.fpsmaster.features.impl.InterfaceModule +import top.fpsmaster.features.manager.Category +import top.fpsmaster.features.settings.impl.ColorSetting +import top.fpsmaster.features.settings.impl.NumberSetting +import top.fpsmaster.modules.music.IngameOverlay +import top.fpsmaster.modules.music.JLayerHelper.updateLoudness +import top.fpsmaster.utils.math.MathTimer +import java.awt.Color + +class MusicOverlay : InterfaceModule("MusicDisplay", Category.Interface) { + init { + addSettings(backgroundColor, progressColor, color, amplitude, bg, rounded, roundRadius) + } + + companion object { + var amplitude = NumberSetting("Amplitude", 10, 0, 10, 0.1) + var progressColor = ColorSetting("ProgressColor", Color(255, 255, 255, 100)) + var color = ColorSetting("Visual", Color(255, 255, 255, 100)) + } + + val timer: MathTimer = MathTimer() + + @Subscribe + fun onRender(e: EventRender2D) { + if (timer.delay(100)) { + updateLoudness() + } + IngameOverlay.onRender() + } +} diff --git a/shared/java/top/fpsmaster/modules/music/IngameOverlay.kt b/shared/java/top/fpsmaster/modules/music/IngameOverlay.kt new file mode 100644 index 00000000..dfb5aff7 --- /dev/null +++ b/shared/java/top/fpsmaster/modules/music/IngameOverlay.kt @@ -0,0 +1,76 @@ +package top.fpsmaster.modules.music + +import net.minecraft.client.gui.ScaledResolution +import net.minecraft.util.ResourceLocation +import top.fpsmaster.FPSMaster +import top.fpsmaster.features.impl.interfaces.MusicOverlay +import top.fpsmaster.modules.music.MusicPlayer.playProgress +import top.fpsmaster.modules.music.netease.Music +import top.fpsmaster.utils.Utility +import top.fpsmaster.utils.math.animation.AnimationUtils.base +import top.fpsmaster.utils.render.Render2DUtils +import java.awt.Color + +object IngameOverlay { + private var songProgress = 0f + var smoothCurve: DoubleArray? = DoubleArray(0) + + fun onRender() { + if (MusicPlayer.playList.getCurrent() != null) { + val sr = ScaledResolution(Utility.Companion.mc) + if (!MusicPlayer.getCurve()!!.isEmpty()) { + val width: Float = ((sr.scaledWidth / 2f - 100) / MusicPlayer.getCurve()!!.size).coerceAtLeast(1f) + var x = 0f + if (smoothCurve!!.size != MusicPlayer.getCurve()!!.size) { + smoothCurve = MusicPlayer.getCurve()!! + } + for (i in 0 until MusicPlayer.getCurve()!!.size) { + smoothCurve?.set(i, base(smoothCurve!![i], MusicPlayer.getCurve()?.get(i) ?: return, 0.15).toFloat().toDouble()) + } + for (musicMagnitude in MusicPlayer.getCurve()!!) { + var musicMagnitude: Double = musicMagnitude + if (musicMagnitude > 0.1f) { + Render2DUtils.drawRect( + x, + sr.scaledHeight - musicMagnitude.toFloat()*100, + width, + musicMagnitude.toFloat(), + MusicOverlay.color.rGB + ) + } + x += width + if (x > (sr.scaledWidth / 2f)) break + } + } + } + } + + fun drawSong(x: Float, y: Float, width: Float, height: Float) { + val sr = ScaledResolution(Utility.Companion.mc) + val current = MusicPlayer.playList.getCurrent() as Music + val s18 = FPSMaster.Companion.fontManager.s18 + Render2DUtils.drawOptimizedRoundedRect(x, y, width, height, Color(0, 0, 0, 180)) + Render2DUtils.drawOptimizedRoundedRect(x, y, songProgress, height, MusicOverlay.progressColor.color) + songProgress = base(songProgress.toDouble(), (6 + (width - 6) * playProgress).toDouble(), 0.1).toFloat() + Render2DUtils.drawImage( + ResourceLocation("music/netease/" + current.id), + x + 5, + y + 5, + height - 10, + height - 10, + -1 + ) + FPSMaster.Companion.fontManager.s18.drawString( + current.name, + x + 40, + y + 6, + FPSMaster.theme.textColorTitle.rgb + ) + FPSMaster.Companion.fontManager.s16.drawString( + current.author, + x + 40, + y + 18, + FPSMaster.theme.textColorDescription.rgb + ) + } +} diff --git a/shared/java/top/fpsmaster/modules/music/JLayerHelper.kt b/shared/java/top/fpsmaster/modules/music/JLayerHelper.kt new file mode 100644 index 00000000..9e18fee5 --- /dev/null +++ b/shared/java/top/fpsmaster/modules/music/JLayerHelper.kt @@ -0,0 +1,180 @@ +package top.fpsmaster.modules.music + +import edu.emory.mathcs.jtransforms.fft.DoubleFFT_1D +import javazoom.jl.converter.Converter +import javazoom.jl.decoder.JavaLayerException +import java.io.File +import java.io.IOException +import javax.sound.sampled.* +import kotlin.math.min +import kotlin.math.sqrt + +object JLayerHelper { + var clip: Clip? = null + var audIn: AudioInputStream? = null + var audioBytes: ByteArray = ByteArray(0) + var loudnessCurve: DoubleArray? = DoubleArray(0) + val progress: Float + get() { + val timeElapsed = clip!!.microsecondPosition + val total = clip!!.microsecondLength + return timeElapsed.toFloat() / total + } + + fun playWAV(wavFile: String) { + // Open an audio input stream. + val soundFile = File(wavFile) //you could also get the sound file with an URL + var audioIn = AudioSystem.getAudioInputStream(soundFile) + audIn = AudioSystem.getAudioInputStream(soundFile) + audioBytes = readAudioData(audIn!!) + // Get a sound clip resource. + clip = AudioSystem.getClip() + // Open audio clip and load samples from the audio input stream. + if (clip == null) + return + clip!!.open(audioIn) + clip!!.start() + } + + @JvmStatic + fun seek(progress: Float) { + val totalTime = clip!!.microsecondLength + val currentTime = (totalTime * progress).toLong() //将播放进度设置为50% + clip!!.microsecondPosition = currentTime + } + + fun updateLoudness() { + if (clip == null) + return + if (audIn == null) { + return + } + val totalTime = clip!!.microsecondLength + val currentTime = (totalTime * progress).toLong() + + val format = audIn?.format + if (format!!.getEncoding() != AudioFormat.Encoding.PCM_SIGNED || + format.getSampleSizeInBits() != 16 + ) { + println("Unsupported audio format: $format"); + return + } + + val targetTime: Float = (currentTime / 1000 / 1000f) + + val segment = getAudioSegment( + audioBytes, + format.sampleRate, + format.frameSize, + targetTime, + 1f + ) + + // 进行 FFT 分析 + val fftData = performFFT(segment) + + // 计算振幅(响度) + val amplitudes = computeAmplitude(fftData) + + loudnessCurve = amplitudes + } + + @Throws(IOException::class) + fun readAudioData(audioInputStream: AudioInputStream): ByteArray { + val bufferSize = (audioInputStream.frameLength * audioInputStream.format.frameSize).toInt() + val audioBytes = ByteArray(bufferSize) + audioInputStream.read(audioBytes) + return audioBytes + } + + fun getAudioSegment( + audioData: ByteArray, + sampleRate: Float, + bytesPerFrame: Int, + startSecond: Float, + durationInSeconds: Float + ): ByteArray { + val startSample = startSecond * sampleRate.toInt() + val numSamples = durationInSeconds * sampleRate.toInt() + val startByte: Int = (startSample * bytesPerFrame).toInt() + val numBytes: Int = (numSamples * bytesPerFrame).toInt() + + return audioData.copyOfRange(startByte, startByte + numBytes) + } + + + fun performFFT(buffer: ByteArray): DoubleArray { + val audioData = DoubleArray(buffer.size / 2) + for (i in audioData.indices) { + audioData[i] = buffer[i] / 128.0 + } + + // 执行傅里叶变换 + val fft = DoubleFFT_1D(1024) + fft.realForward(audioData) + + return audioData + } + + + fun computeAmplitude(fftData: DoubleArray): DoubleArray { + val numFrequencies = fftData.size / 2 + val numBlocks = 300 + val amplitudes = DoubleArray(numFrequencies) + + + // 归一化处理 + val min = amplitudes.minOrNull() ?: 0.0 + val max = amplitudes.maxOrNull() ?: 1.0 + val normalizedAmplitudes = amplitudes.map { amplitude -> + (amplitude - min) / (max - min) + }.toDoubleArray() + + // 每个块的大小 + val blockSize = amplitudes.size / numBlocks + val blockAverages = DoubleArray(numBlocks) + + // 分块并计算均值 + for (block in 0 until numBlocks) { + val startIdx = block * blockSize + val endIdx = if (block == numBlocks - 1) normalizedAmplitudes.size else startIdx + blockSize + val blockSum = normalizedAmplitudes.slice(startIdx until endIdx).sum() + blockAverages[block] = blockSum / (endIdx - startIdx) + } + + return blockAverages + } + + fun setVolume(vol: Float) { + var vol = vol + vol /= 2 + vol += 0.5f + val volumeControl = clip!!.getControl(FloatControl.Type.MASTER_GAIN) as FloatControl + // Change the volume to half way between minimum and maximum + val volume = (volumeControl.maximum - volumeControl.minimum) * vol + volumeControl.minimum + volumeControl.value = volume + } + + fun convert(sourcePath: String, targetPath: String) { + try { + val converter = Converter() + val sourceFile = File(sourcePath) + val targetFile = File(targetPath) + converter.convert(sourceFile.path, targetFile.path) + } catch (e: JavaLayerException) { + e.printStackTrace() + } + } + + fun stop() { + clip!!.stop() + } + + fun start() { + clip!!.start() + } + + @JvmStatic + val duration: Double + get() = (clip!!.microsecondLength / 1000f / 1000f / 60f).toDouble() +} diff --git a/shared/java/top/fpsmaster/modules/music/MusicPlayer.kt b/shared/java/top/fpsmaster/modules/music/MusicPlayer.kt new file mode 100644 index 00000000..2c637254 --- /dev/null +++ b/shared/java/top/fpsmaster/modules/music/MusicPlayer.kt @@ -0,0 +1,69 @@ +package top.fpsmaster.modules.music + +import top.fpsmaster.FPSMaster +import java.io.File +import kotlin.math.min + +object MusicPlayer { + var playList = PlayList() + var mode = 0 + var startTime: Long = 0 + var isPlaying = false + private var volume = 1f + private var curPlayProgress = 0f + val playProgress: Float + get() { + if (isPlaying) if (JLayerHelper.clip != null) curPlayProgress = JLayerHelper.progress + return min(curPlayProgress, 1f) + } + + fun play() { + isPlaying = true + if (JLayerHelper.clip == null) return + JLayerHelper.start() + } + + fun getCurve(): DoubleArray? { + return JLayerHelper.loudnessCurve + } + + fun pause() { + isPlaying = false + if (JLayerHelper.clip == null) return + JLayerHelper.stop() + } + + fun stop() { + isPlaying = false + if (JLayerHelper.clip == null) return + JLayerHelper.stop() + } + + @JvmStatic + fun playFile(path: String) { + val file = File(path) + if (file.exists()) { + JLayerHelper.convert(path, path.replace(".mp3", ".wav")) + if (JLayerHelper.clip != null) { + JLayerHelper.clip!!.stop() + JLayerHelper.clip!!.close() + } + val v = FPSMaster.configManager.configure.getOrCreate("volume", "1").toFloat() + FPSMaster.async.runnable { + JLayerHelper.playWAV(path.replace(".mp3", ".wav")) + setVolume(v) + } + } + } + + fun getVolume(): Float { + return volume + } + + fun setVolume(volume: Float) { + MusicPlayer.volume = volume + if (JLayerHelper.clip == null) return + JLayerHelper.setVolume(volume) + FPSMaster.configManager.configure["volume"] = volume.toString() + } +} diff --git a/shared/java/top/fpsmaster/utils/os/HttpRequest.kt b/shared/java/top/fpsmaster/utils/os/HttpRequest.kt new file mode 100644 index 00000000..e6445e19 --- /dev/null +++ b/shared/java/top/fpsmaster/utils/os/HttpRequest.kt @@ -0,0 +1,152 @@ +package top.fpsmaster.utils.os + +import org.apache.http.client.HttpClient +import org.apache.http.client.methods.HttpGet +import org.apache.http.impl.client.HttpClients +import top.fpsmaster.modules.logger.Logger +import top.fpsmaster.modules.logger.Logger.info +import java.io.* +import java.net.HttpURLConnection +import java.net.URL +import java.nio.charset.StandardCharsets + +object HttpRequest { + @JvmStatic + operator fun get(u: String?): String { + return getWithCookie(u, "") + } + + @JvmStatic + fun getWithCookie(url: String?, cookie: String): String { + val u = url + val url = URL(u) + val connection = url.openConnection() as HttpURLConnection + connection.requestMethod = "GET" + connection.setRequestProperty( + "User-Agent", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36" + ) + val value = cookie.replace("\n","") + if (value.isNotBlank()) { + connection.setRequestProperty("Cookie", value) + } + connection.connectTimeout = 15000 + connection.readTimeout = 5000 + connection.connect() + val reader = BufferedReader(InputStreamReader(connection.inputStream, StandardCharsets.UTF_8)) + val builder = StringBuilder() + var line: String? + while (reader.readLine().also { line = it } != null) { + builder.append(line) + } + reader.close() + connection.disconnect() + return builder.toString() + } + + @JvmStatic + fun downloadFile(url: String, filepath: String) { + try { + val client: HttpClient = HttpClients.createDefault() + val httpget = HttpGet(url) + val response = client.execute(httpget) + val entity = response.entity + val `is` = entity.content + var progress: Long = 0 + val totalLen = entity.contentLength + val unit = totalLen / 100 + val file = File(filepath) + val fileout = FileOutputStream(file) + val buffer = ByteArray(10 * 1024) + var ch: Int + while (`is`.read(buffer).also { ch = it } != -1) { + fileout.write(buffer, 0, ch) + progress += ch.toLong() + } + if (progress % 10 == 0L) info("Downloaded " + progress / unit + "%") + `is`.close() + fileout.flush() + fileout.close() + } catch (e: Exception) { + Logger.error("Failed to download file: $url") + e.printStackTrace() + } + } + + @JvmStatic + fun sendPostRequest(targetUrl: String?, body: String, headers: MutableMap): Array { + val response = arrayOfNulls(2) + val url = URL(targetUrl) + val connection = url.openConnection() as HttpURLConnection + + // 设置请求方式为POST + connection.requestMethod = "POST" + + // 添加headers + for ((key, value) in headers) { + connection.setRequestProperty(key, value.trim()) + } + + // 添加body + connection.doOutput = true + val os = connection.outputStream + os.write(body.toByteArray()) + os.flush() + os.close() + + // 获取响应状态码 + response[0] = connection.responseCode.toString() + val content = StringBuffer() + + if (response[0] == "400" || response[0] == "403") { + // 获取响应内容 + val `in` = connection.errorStream.bufferedReader() + var inputLine: String? + while (`in`.readLine().also { inputLine = it } != null) { + content.append(inputLine) + } + `in`.close() + }else{ + // 获取响应内容 + val `in` = BufferedReader(InputStreamReader(connection.inputStream, StandardCharsets.UTF_8)) + var inputLine: String? + while (`in`.readLine().also { inputLine = it } != null) { + content.append(inputLine) + } + `in`.close() + } + connection.disconnect() + response[1] = content.toString() + return response +} + +fun downloadAsync(url: String?, filepath: String, callback: Runnable) { + Thread { + try { + val client: HttpClient = HttpClients.createDefault() + val httpget = HttpGet(url) + val response = client.execute(httpget) + val entity = response.entity + val `is` = entity.content + var progress: Long = 0 + val totalLen = entity.contentLength + val unit = totalLen / 100 + val file = File(filepath) + val fileout = FileOutputStream(file) + val buffer = ByteArray(10 * 1024) + var ch = 0 + while (`is`.read(buffer).also { ch = it } != -1) { + fileout.write(buffer, 0, ch) + progress += ch.toLong() + } + if (progress % 10 == 0L) info("Downloaded " + progress / unit + "%") + `is`.close() + fileout.flush() + fileout.close() + callback.run() + } catch (e: Exception) { + e.printStackTrace() + } + }.start() + } +} diff --git a/v1.12.2/build.gradle.kts b/v1.12.2/build.gradle.kts index 2ecae16f..807acb25 100644 --- a/v1.12.2/build.gradle.kts +++ b/v1.12.2/build.gradle.kts @@ -92,6 +92,9 @@ dependencies { // If you don't want to log in with your real minecraft account, remove this line // runtimeOnly("me.djtheredstoner:DevAuth-forge-legacy:1.1.2") implementation("javazoom:jlayer:1.0.1") +// https://mvnrepository.com/artifact/net.sourceforge.jtransforms/jtransforms + implementation("net.sourceforge.jtransforms:jtransforms:2.4.0") + implementation(kotlin("stdlib-jdk8")) } diff --git a/v1.8.9/build.gradle.kts b/v1.8.9/build.gradle.kts index bb4d5404..db3989ed 100644 --- a/v1.8.9/build.gradle.kts +++ b/v1.8.9/build.gradle.kts @@ -114,6 +114,10 @@ dependencies { // If you don't want to log in with your real minecraft account, remove this line // runtimeOnly("me.djtheredstoner:DevAuth-forge-legacy:1.1.2") implementation("javazoom:jlayer:1.0.1") +// https://mvnrepository.com/artifact/net.sourceforge.jtransforms/jtransforms + implementation("net.sourceforge.jtransforms:jtransforms:2.4.0") + + } // Tasks: From 9ec3d26b41bd5f0550fb92890857743706c20866 Mon Sep 17 00:00:00 2001 From: SuperSkidder Date: Sat, 5 Apr 2025 11:40:04 +0800 Subject: [PATCH 007/193] fix: music visualization --- .../fpsmaster/modules/music/IngameOverlay.kt | 36 +++--- .../fpsmaster/modules/music/JLayerHelper.kt | 109 +++++++++--------- 2 files changed, 76 insertions(+), 69 deletions(-) diff --git a/shared/java/top/fpsmaster/modules/music/IngameOverlay.kt b/shared/java/top/fpsmaster/modules/music/IngameOverlay.kt index dfb5aff7..1b13e1e4 100644 --- a/shared/java/top/fpsmaster/modules/music/IngameOverlay.kt +++ b/shared/java/top/fpsmaster/modules/music/IngameOverlay.kt @@ -27,20 +27,30 @@ object IngameOverlay { for (i in 0 until MusicPlayer.getCurve()!!.size) { smoothCurve?.set(i, base(smoothCurve!![i], MusicPlayer.getCurve()?.get(i) ?: return, 0.15).toFloat().toDouble()) } - for (musicMagnitude in MusicPlayer.getCurve()!!) { - var musicMagnitude: Double = musicMagnitude - if (musicMagnitude > 0.1f) { - Render2DUtils.drawRect( - x, - sr.scaledHeight - musicMagnitude.toFloat()*100, - width, - musicMagnitude.toFloat(), - MusicOverlay.color.rGB - ) - } - x += width - if (x > (sr.scaledWidth / 2f)) break + val curve = MusicPlayer.getCurve() ?: return + val fftSize = 1024 + val sampleRate = 44100.0 + val frequencies = DoubleArray(fftSize / 2) { i -> i * sampleRate / fftSize } + + val screenWidth = sr.scaledWidth.toFloat() + val screenHeight = sr.scaledHeight.toFloat() + + for (i in curve.indices) { + val freq = frequencies[i] + val magnitude = curve[i].coerceIn(0.0, 1.0) + + val x = (freq / 22050.0 * screenWidth).toFloat() + val height = (magnitude * 100f * MusicOverlay.amplitude.value.toFloat()).toFloat() + + Render2DUtils.drawRect( + x, + screenHeight - height, + 2f, + height, + MusicOverlay.color.rGB + ) } + } } } diff --git a/shared/java/top/fpsmaster/modules/music/JLayerHelper.kt b/shared/java/top/fpsmaster/modules/music/JLayerHelper.kt index 9e18fee5..82b9ab48 100644 --- a/shared/java/top/fpsmaster/modules/music/JLayerHelper.kt +++ b/shared/java/top/fpsmaster/modules/music/JLayerHelper.kt @@ -44,41 +44,33 @@ object JLayerHelper { } fun updateLoudness() { - if (clip == null) - return - if (audIn == null) { - return - } - val totalTime = clip!!.microsecondLength - val currentTime = (totalTime * progress).toLong() + if (clip == null || audIn == null) return - val format = audIn?.format - if (format!!.getEncoding() != AudioFormat.Encoding.PCM_SIGNED || - format.getSampleSizeInBits() != 16 - ) { - println("Unsupported audio format: $format"); + val format = audIn!!.format + if (format.encoding != AudioFormat.Encoding.PCM_SIGNED || format.sampleSizeInBits != 16) { + println("Unsupported format: $format") return } - val targetTime: Float = (currentTime / 1000 / 1000f) + val currentTimeSec = clip!!.microsecondPosition / 1_000_000.0 + val fftSize = 1024 + val fftWindowDuration = fftSize / format.sampleRate - val segment = getAudioSegment( + val audioSegment = getAudioSegment( audioBytes, format.sampleRate, format.frameSize, - targetTime, - 1f + (currentTimeSec - fftWindowDuration / 2).toFloat(), + fftWindowDuration.toFloat() ) - // 进行 FFT 分析 - val fftData = performFFT(segment) - - // 计算振幅(响度) + val fftData = performFFT(audioSegment) val amplitudes = computeAmplitude(fftData) loudnessCurve = amplitudes } + @Throws(IOException::class) fun readAudioData(audioInputStream: AudioInputStream): ByteArray { val bufferSize = (audioInputStream.frameLength * audioInputStream.format.frameSize).toInt() @@ -94,57 +86,62 @@ object JLayerHelper { startSecond: Float, durationInSeconds: Float ): ByteArray { - val startSample = startSecond * sampleRate.toInt() - val numSamples = durationInSeconds * sampleRate.toInt() - val startByte: Int = (startSample * bytesPerFrame).toInt() - val numBytes: Int = (numSamples * bytesPerFrame).toInt() + val startSample = (startSecond * sampleRate).toInt().coerceAtLeast(0) + val numSamples = (durationInSeconds * sampleRate).toInt() + + val startByte = startSample * bytesPerFrame + val numBytes = numSamples * bytesPerFrame - return audioData.copyOfRange(startByte, startByte + numBytes) + val endByte = (startByte + numBytes).coerceAtMost(audioData.size) + + return audioData.copyOfRange(startByte, endByte) } - fun performFFT(buffer: ByteArray): DoubleArray { - val audioData = DoubleArray(buffer.size / 2) - for (i in audioData.indices) { - audioData[i] = buffer[i] / 128.0 + + private fun performFFT(buffer: ByteArray): DoubleArray { + val numSamples = buffer.size / 2 + val audioData = DoubleArray(numSamples) + + // Convert byte pairs (little-endian) to signed 16-bit samples + for (i in 0 until numSamples) { + val low = buffer[i * 2].toInt() and 0xff + val high = buffer[i * 2 + 1].toInt() + val sample = (high shl 8) or low + audioData[i] = sample / 32768.0 // Normalize to [-1, 1] + } + + // Zero-padding to nearest power of 2 (optional, or cut to fixed size like 1024) + val fftSize = 1024 + val paddedData = DoubleArray(fftSize) + for (i in 0 until min(fftSize, audioData.size)) { + paddedData[i] = audioData[i] } - // 执行傅里叶变换 - val fft = DoubleFFT_1D(1024) - fft.realForward(audioData) + val fft = DoubleFFT_1D(fftSize) + fft.realForward(paddedData) - return audioData + return paddedData } + fun computeAmplitude(fftData: DoubleArray): DoubleArray { - val numFrequencies = fftData.size / 2 - val numBlocks = 300 - val amplitudes = DoubleArray(numFrequencies) - - - // 归一化处理 - val min = amplitudes.minOrNull() ?: 0.0 - val max = amplitudes.maxOrNull() ?: 1.0 - val normalizedAmplitudes = amplitudes.map { amplitude -> - (amplitude - min) / (max - min) - }.toDoubleArray() - - // 每个块的大小 - val blockSize = amplitudes.size / numBlocks - val blockAverages = DoubleArray(numBlocks) - - // 分块并计算均值 - for (block in 0 until numBlocks) { - val startIdx = block * blockSize - val endIdx = if (block == numBlocks - 1) normalizedAmplitudes.size else startIdx + blockSize - val blockSum = normalizedAmplitudes.slice(startIdx until endIdx).sum() - blockAverages[block] = blockSum / (endIdx - startIdx) + val n = fftData.size + val amplitudes = DoubleArray(n / 2) + + for (i in amplitudes.indices) { + val real = fftData[2 * i] + val imag = if (2 * i + 1 < fftData.size) fftData[2 * i + 1] else 0.0 + amplitudes[i] = sqrt(real * real + imag * imag) } - return blockAverages + // 简单归一化 + val maxAmp = amplitudes.maxOrNull() ?: 1.0 + return amplitudes.map { it / maxAmp }.toDoubleArray() } + fun setVolume(vol: Float) { var vol = vol vol /= 2 From db3192a90c9d98a27ab829fa058bf3a635c97860 Mon Sep 17 00:00:00 2001 From: SuperSkidder Date: Tue, 8 Apr 2025 18:39:26 +0800 Subject: [PATCH 008/193] to java (untested) --- .../impl/interfaces/MusicOverlay.java | 23 ++- .../features/impl/interfaces/MusicOverlay.kt | 34 ---- .../modules/music/IngameOverlay.java | 98 ++++++++++ .../fpsmaster/modules/music/IngameOverlay.kt | 86 --------- .../fpsmaster/modules/music/JLayerHelper.java | 130 +++++++++++-- .../fpsmaster/modules/music/JLayerHelper.kt | 177 ------------------ .../fpsmaster/modules/music/MusicPlayer.java | 22 ++- .../fpsmaster/modules/music/MusicPlayer.kt | 69 ------- 8 files changed, 246 insertions(+), 393 deletions(-) delete mode 100644 shared/java/top/fpsmaster/features/impl/interfaces/MusicOverlay.kt create mode 100644 shared/java/top/fpsmaster/modules/music/IngameOverlay.java delete mode 100644 shared/java/top/fpsmaster/modules/music/IngameOverlay.kt delete mode 100644 shared/java/top/fpsmaster/modules/music/JLayerHelper.kt delete mode 100644 shared/java/top/fpsmaster/modules/music/MusicPlayer.kt diff --git a/shared/java/top/fpsmaster/features/impl/interfaces/MusicOverlay.java b/shared/java/top/fpsmaster/features/impl/interfaces/MusicOverlay.java index 2092b73b..d92beb08 100644 --- a/shared/java/top/fpsmaster/features/impl/interfaces/MusicOverlay.java +++ b/shared/java/top/fpsmaster/features/impl/interfaces/MusicOverlay.java @@ -1,19 +1,34 @@ package top.fpsmaster.features.impl.interfaces; +import top.fpsmaster.event.Subscribe; +import top.fpsmaster.event.events.EventRender2D; import top.fpsmaster.features.impl.InterfaceModule; import top.fpsmaster.features.manager.Category; import top.fpsmaster.features.settings.impl.ColorSetting; import top.fpsmaster.features.settings.impl.NumberSetting; +import top.fpsmaster.modules.music.IngameOverlay; +import top.fpsmaster.modules.music.JLayerHelper; +import top.fpsmaster.utils.math.MathTimer; import java.awt.Color; public class MusicOverlay extends InterfaceModule { + public static final NumberSetting amplitude = new NumberSetting("Amplitude", 10, 0, 10, 0.1); + public static final ColorSetting progressColor = new ColorSetting("ProgressColor", new Color(255, 255, 255, 100)); + public static final ColorSetting color = new ColorSetting("Visual", new Color(255, 255, 255, 100)); + + private final MathTimer timer = new MathTimer(); + public MusicOverlay() { super("MusicDisplay", Category.Interface); - addSettings(backgroundColor, progressColor, color, amplitude, bg, rounded, roundRadius); + addSettings(amplitude, progressColor, color); } - public static NumberSetting amplitude = new NumberSetting("Amplitude", 10, 0, 10, 0.1); - public static ColorSetting progressColor = new ColorSetting("ProgressColor", new Color(255, 255, 255, 100)); - public static ColorSetting color = new ColorSetting("Visual", new Color(255, 255, 255, 100)); + @Subscribe + public void onRender(EventRender2D e) { + if (timer.delay(100)) { + JLayerHelper.updateLoudness(); + } + IngameOverlay.onRender(); + } } diff --git a/shared/java/top/fpsmaster/features/impl/interfaces/MusicOverlay.kt b/shared/java/top/fpsmaster/features/impl/interfaces/MusicOverlay.kt deleted file mode 100644 index 52a3f177..00000000 --- a/shared/java/top/fpsmaster/features/impl/interfaces/MusicOverlay.kt +++ /dev/null @@ -1,34 +0,0 @@ -package top.fpsmaster.features.impl.interfaces - -import top.fpsmaster.event.Subscribe -import top.fpsmaster.event.events.EventRender2D -import top.fpsmaster.features.impl.InterfaceModule -import top.fpsmaster.features.manager.Category -import top.fpsmaster.features.settings.impl.ColorSetting -import top.fpsmaster.features.settings.impl.NumberSetting -import top.fpsmaster.modules.music.IngameOverlay -import top.fpsmaster.modules.music.JLayerHelper.updateLoudness -import top.fpsmaster.utils.math.MathTimer -import java.awt.Color - -class MusicOverlay : InterfaceModule("MusicDisplay", Category.Interface) { - init { - addSettings(backgroundColor, progressColor, color, amplitude, bg, rounded, roundRadius) - } - - companion object { - var amplitude = NumberSetting("Amplitude", 10, 0, 10, 0.1) - var progressColor = ColorSetting("ProgressColor", Color(255, 255, 255, 100)) - var color = ColorSetting("Visual", Color(255, 255, 255, 100)) - } - - val timer: MathTimer = MathTimer() - - @Subscribe - fun onRender(e: EventRender2D) { - if (timer.delay(100)) { - updateLoudness() - } - IngameOverlay.onRender() - } -} diff --git a/shared/java/top/fpsmaster/modules/music/IngameOverlay.java b/shared/java/top/fpsmaster/modules/music/IngameOverlay.java new file mode 100644 index 00000000..39281b66 --- /dev/null +++ b/shared/java/top/fpsmaster/modules/music/IngameOverlay.java @@ -0,0 +1,98 @@ +package top.fpsmaster.modules.music; + +import net.minecraft.client.gui.ScaledResolution; +import net.minecraft.util.ResourceLocation; +import top.fpsmaster.FPSMaster; +import top.fpsmaster.features.impl.interfaces.MusicOverlay; +import top.fpsmaster.font.impl.UFontRenderer; +import top.fpsmaster.modules.music.MusicPlayer; +import top.fpsmaster.modules.music.netease.Music; +import top.fpsmaster.utils.Utility; +import top.fpsmaster.utils.math.animation.AnimationUtils; +import top.fpsmaster.utils.render.Render2DUtils; + +import java.awt.Color; + +public class IngameOverlay { + private static float songProgress = 0f; + private static Double[] smoothCurve = new Double[0]; + + public static void onRender() { + if (MusicPlayer.playList.getCurrent() != -1) { + ScaledResolution sr = new ScaledResolution(Utility.mc); + if (MusicPlayer.getCurve().length !=0) { + float width = Math.max((sr.getScaledWidth() / 2f - 100) / MusicPlayer.getCurve().length, 1f); + float x = 0f; + + if (smoothCurve.length != MusicPlayer.getCurve().length) { + smoothCurve = new Double[MusicPlayer.getCurve().length]; + } + + for (int i = 0; i < MusicPlayer.getCurve().length; i++) { + smoothCurve[i] = AnimationUtils.base(smoothCurve[i], MusicPlayer.getCurve()[i], 0.15); + } + + double[] curve = MusicPlayer.getCurve(); + int fftSize = 1024; + double sampleRate = 44100.0; + double[] frequencies = new double[fftSize / 2]; + for (int i = 0; i < frequencies.length; i++) { + frequencies[i] = i * sampleRate / fftSize; + } + + float screenWidth = sr.getScaledWidth(); + float screenHeight = sr.getScaledHeight(); + + for (int i = 0; i < curve.length; i++) { + double freq = frequencies[i]; + double magnitude = Math.min(Math.max(curve[i], 0.0), 1.0); + + float xPos = (float) (freq / 22050.0 * screenWidth); + float height = (float) (magnitude * 100f * MusicOverlay.amplitude.value.floatValue()); + + Render2DUtils.drawRect( + xPos, + screenHeight - height, + 2f, + height, + MusicOverlay.color.getRGB() + ); + } + } + } + } + + public static void drawSong(float x, float y, float width, float height) { + ScaledResolution sr = new ScaledResolution(Utility.mc); + Music current = (Music) MusicPlayer.playList.musics.get(MusicPlayer.playList.getCurrent()); + UFontRenderer s18 = FPSMaster.fontManager.s18; + + Render2DUtils.drawOptimizedRoundedRect(x, y, width, height, new Color(0, 0, 0, 180)); + Render2DUtils.drawOptimizedRoundedRect(x, y, songProgress, height, MusicOverlay.progressColor.getColor()); + + songProgress = (float) AnimationUtils.base((double) songProgress, 6 + (width - 6) * MusicPlayer.curPlayProgress, 0.1); + + Render2DUtils.drawImage( + new ResourceLocation("music/netease/" + current.id), + x + 5, + y + 5, + height - 10, + height - 10, + -1 + ); + + FPSMaster.fontManager.s18.drawString( + current.name, + x + 40, + y + 6, + FPSMaster.theme.getTextColorTitle().getRGB() + ); + + FPSMaster.fontManager.s16.drawString( + current.author, + x + 40, + y + 18, + FPSMaster.theme.getTextColorDescription().getRGB() + ); + } +} diff --git a/shared/java/top/fpsmaster/modules/music/IngameOverlay.kt b/shared/java/top/fpsmaster/modules/music/IngameOverlay.kt deleted file mode 100644 index 1b13e1e4..00000000 --- a/shared/java/top/fpsmaster/modules/music/IngameOverlay.kt +++ /dev/null @@ -1,86 +0,0 @@ -package top.fpsmaster.modules.music - -import net.minecraft.client.gui.ScaledResolution -import net.minecraft.util.ResourceLocation -import top.fpsmaster.FPSMaster -import top.fpsmaster.features.impl.interfaces.MusicOverlay -import top.fpsmaster.modules.music.MusicPlayer.playProgress -import top.fpsmaster.modules.music.netease.Music -import top.fpsmaster.utils.Utility -import top.fpsmaster.utils.math.animation.AnimationUtils.base -import top.fpsmaster.utils.render.Render2DUtils -import java.awt.Color - -object IngameOverlay { - private var songProgress = 0f - var smoothCurve: DoubleArray? = DoubleArray(0) - - fun onRender() { - if (MusicPlayer.playList.getCurrent() != null) { - val sr = ScaledResolution(Utility.Companion.mc) - if (!MusicPlayer.getCurve()!!.isEmpty()) { - val width: Float = ((sr.scaledWidth / 2f - 100) / MusicPlayer.getCurve()!!.size).coerceAtLeast(1f) - var x = 0f - if (smoothCurve!!.size != MusicPlayer.getCurve()!!.size) { - smoothCurve = MusicPlayer.getCurve()!! - } - for (i in 0 until MusicPlayer.getCurve()!!.size) { - smoothCurve?.set(i, base(smoothCurve!![i], MusicPlayer.getCurve()?.get(i) ?: return, 0.15).toFloat().toDouble()) - } - val curve = MusicPlayer.getCurve() ?: return - val fftSize = 1024 - val sampleRate = 44100.0 - val frequencies = DoubleArray(fftSize / 2) { i -> i * sampleRate / fftSize } - - val screenWidth = sr.scaledWidth.toFloat() - val screenHeight = sr.scaledHeight.toFloat() - - for (i in curve.indices) { - val freq = frequencies[i] - val magnitude = curve[i].coerceIn(0.0, 1.0) - - val x = (freq / 22050.0 * screenWidth).toFloat() - val height = (magnitude * 100f * MusicOverlay.amplitude.value.toFloat()).toFloat() - - Render2DUtils.drawRect( - x, - screenHeight - height, - 2f, - height, - MusicOverlay.color.rGB - ) - } - - } - } - } - - fun drawSong(x: Float, y: Float, width: Float, height: Float) { - val sr = ScaledResolution(Utility.Companion.mc) - val current = MusicPlayer.playList.getCurrent() as Music - val s18 = FPSMaster.Companion.fontManager.s18 - Render2DUtils.drawOptimizedRoundedRect(x, y, width, height, Color(0, 0, 0, 180)) - Render2DUtils.drawOptimizedRoundedRect(x, y, songProgress, height, MusicOverlay.progressColor.color) - songProgress = base(songProgress.toDouble(), (6 + (width - 6) * playProgress).toDouble(), 0.1).toFloat() - Render2DUtils.drawImage( - ResourceLocation("music/netease/" + current.id), - x + 5, - y + 5, - height - 10, - height - 10, - -1 - ) - FPSMaster.Companion.fontManager.s18.drawString( - current.name, - x + 40, - y + 6, - FPSMaster.theme.textColorTitle.rgb - ) - FPSMaster.Companion.fontManager.s16.drawString( - current.author, - x + 40, - y + 18, - FPSMaster.theme.textColorDescription.rgb - ) - } -} diff --git a/shared/java/top/fpsmaster/modules/music/JLayerHelper.java b/shared/java/top/fpsmaster/modules/music/JLayerHelper.java index 78105295..9ea4c08a 100644 --- a/shared/java/top/fpsmaster/modules/music/JLayerHelper.java +++ b/shared/java/top/fpsmaster/modules/music/JLayerHelper.java @@ -1,32 +1,42 @@ package top.fpsmaster.modules.music; +import edu.emory.mathcs.jtransforms.fft.DoubleFFT_1D; import javazoom.jl.converter.Converter; import javazoom.jl.decoder.JavaLayerException; + import javax.sound.sampled.*; import java.io.File; +import java.io.IOException; +import java.util.Arrays; +import static java.lang.Math.min; +import static java.lang.Math.sqrt; public class JLayerHelper { - public static Clip clip; + private static AudioInputStream audIn; + private static byte[] audioBytes = new byte[0]; + public static double[] loudnessCurve = new double[0]; public static float getProgress() { + if (clip == null) return 0; long timeElapsed = clip.getMicrosecondPosition(); long total = clip.getMicrosecondLength(); return (float) timeElapsed / total; } - public static void playWAV(String wavFile) { + public static void playWAV(String wavFile) throws IOException, LineUnavailableException { + File soundFile = new File(wavFile); try { - File soundFile = new File(wavFile); - AudioInputStream audioIn = AudioSystem.getAudioInputStream(soundFile); - clip = AudioSystem.getClip(); - if (clip != null) { - clip.open(audioIn); - clip.start(); - } - } catch (Exception e) { + audIn = AudioSystem.getAudioInputStream(soundFile); + } catch (UnsupportedAudioFileException e) { e.printStackTrace(); + return; } + audioBytes = readAudioData(audIn); + clip = AudioSystem.getClip(); + if (clip == null) return; + clip.open(audIn); + clip.start(); } public static void seek(float progress) { @@ -35,16 +45,100 @@ public static void seek(float progress) { clip.setMicrosecondPosition(currentTime); } + public static void updateLoudness() { + if (clip == null || audIn == null) return; + + AudioFormat format = audIn.getFormat(); + if (format.getEncoding() != AudioFormat.Encoding.PCM_SIGNED || format.getSampleSizeInBits() != 16) { + System.out.println("Unsupported format: " + format); + return; + } + + double currentTimeSec = clip.getMicrosecondPosition() / 1_000_000.0; + int fftSize = 1024; + double fftWindowDuration = fftSize / format.getSampleRate(); + + byte[] audioSegment = getAudioSegment( + audioBytes, + format.getSampleRate(), + format.getFrameSize(), + (float) (currentTimeSec - fftWindowDuration / 2), + (float) fftWindowDuration + ); + + double[] fftData = performFFT(audioSegment); + double[] amplitudes = computeAmplitude(fftData); + + loudnessCurve = amplitudes; + } + + private static byte[] readAudioData(AudioInputStream audioInputStream) throws IOException { + int bufferSize = (int) (audioInputStream.getFrameLength() * audioInputStream.getFormat().getFrameSize()); + byte[] audioBytes = new byte[bufferSize]; + audioInputStream.read(audioBytes); + return audioBytes; + } + + private static byte[] getAudioSegment(byte[] audioData, float sampleRate, int bytesPerFrame, float startSecond, float durationInSeconds) { + int startSample = (int) (startSecond * sampleRate); + int numSamples = (int) (durationInSeconds * sampleRate); + + int startByte = startSample * bytesPerFrame; + int numBytes = numSamples * bytesPerFrame; + + int endByte = Math.min(startByte + numBytes, audioData.length); + + return Arrays.copyOfRange(audioData, startByte, endByte); + } + + private static double[] performFFT(byte[] buffer) { + int numSamples = buffer.length / 2; + double[] audioData = new double[numSamples]; + + for (int i = 0; i < numSamples; i++) { + int low = buffer[i * 2] & 0xff; + int high = buffer[i * 2 + 1]; + int sample = (high << 8) | low; + audioData[i] = sample / 32768.0; // Normalize to [-1, 1] + } + + int fftSize = 1024; + double[] paddedData = new double[fftSize]; + for (int i = 0; i < min(fftSize, audioData.length); i++) { + paddedData[i] = audioData[i]; + } + + DoubleFFT_1D fft = new DoubleFFT_1D(fftSize); + fft.realForward(paddedData); + + return paddedData; + } + + public static double[] computeAmplitude(double[] fftData) { + int n = fftData.length; + double[] amplitudes = new double[n / 2]; + + for (int i = 0; i < amplitudes.length; i++) { + double real = fftData[2 * i]; + double imag = (2 * i + 1 < fftData.length) ? fftData[2 * i + 1] : 0.0; + amplitudes[i] = sqrt(real * real + imag * imag); + } + + // Simple normalization + double maxAmp = Arrays.stream(amplitudes).max().orElse(1.0); + for (int i = 0; i < amplitudes.length; i++) { + amplitudes[i] /= maxAmp; + } + + return amplitudes; + } + public static void setVolume(float vol) { vol /= 2; vol += 0.5f; - try { - FloatControl volumeControl = (FloatControl) clip.getControl(FloatControl.Type.MASTER_GAIN); - float volume = (volumeControl.getMaximum() - volumeControl.getMinimum()) * vol + volumeControl.getMinimum(); - volumeControl.setValue(volume); - } catch (Exception e) { - e.printStackTrace(); - } + FloatControl volumeControl = (FloatControl) clip.getControl(FloatControl.Type.MASTER_GAIN); + float volume = (volumeControl.getMaximum() - volumeControl.getMinimum()) * vol + volumeControl.getMinimum(); + volumeControl.setValue(volume); } public static void convert(String sourcePath, String targetPath) { @@ -71,6 +165,6 @@ public static void start() { } public static double getDuration() { - return clip.getMicrosecondLength() / 1000000.0 / 60.0; + return (clip.getMicrosecondLength() / 1_000_000.0 / 60.0); } } diff --git a/shared/java/top/fpsmaster/modules/music/JLayerHelper.kt b/shared/java/top/fpsmaster/modules/music/JLayerHelper.kt deleted file mode 100644 index 82b9ab48..00000000 --- a/shared/java/top/fpsmaster/modules/music/JLayerHelper.kt +++ /dev/null @@ -1,177 +0,0 @@ -package top.fpsmaster.modules.music - -import edu.emory.mathcs.jtransforms.fft.DoubleFFT_1D -import javazoom.jl.converter.Converter -import javazoom.jl.decoder.JavaLayerException -import java.io.File -import java.io.IOException -import javax.sound.sampled.* -import kotlin.math.min -import kotlin.math.sqrt - -object JLayerHelper { - var clip: Clip? = null - var audIn: AudioInputStream? = null - var audioBytes: ByteArray = ByteArray(0) - var loudnessCurve: DoubleArray? = DoubleArray(0) - val progress: Float - get() { - val timeElapsed = clip!!.microsecondPosition - val total = clip!!.microsecondLength - return timeElapsed.toFloat() / total - } - - fun playWAV(wavFile: String) { - // Open an audio input stream. - val soundFile = File(wavFile) //you could also get the sound file with an URL - var audioIn = AudioSystem.getAudioInputStream(soundFile) - audIn = AudioSystem.getAudioInputStream(soundFile) - audioBytes = readAudioData(audIn!!) - // Get a sound clip resource. - clip = AudioSystem.getClip() - // Open audio clip and load samples from the audio input stream. - if (clip == null) - return - clip!!.open(audioIn) - clip!!.start() - } - - @JvmStatic - fun seek(progress: Float) { - val totalTime = clip!!.microsecondLength - val currentTime = (totalTime * progress).toLong() //将播放进度设置为50% - clip!!.microsecondPosition = currentTime - } - - fun updateLoudness() { - if (clip == null || audIn == null) return - - val format = audIn!!.format - if (format.encoding != AudioFormat.Encoding.PCM_SIGNED || format.sampleSizeInBits != 16) { - println("Unsupported format: $format") - return - } - - val currentTimeSec = clip!!.microsecondPosition / 1_000_000.0 - val fftSize = 1024 - val fftWindowDuration = fftSize / format.sampleRate - - val audioSegment = getAudioSegment( - audioBytes, - format.sampleRate, - format.frameSize, - (currentTimeSec - fftWindowDuration / 2).toFloat(), - fftWindowDuration.toFloat() - ) - - val fftData = performFFT(audioSegment) - val amplitudes = computeAmplitude(fftData) - - loudnessCurve = amplitudes - } - - - @Throws(IOException::class) - fun readAudioData(audioInputStream: AudioInputStream): ByteArray { - val bufferSize = (audioInputStream.frameLength * audioInputStream.format.frameSize).toInt() - val audioBytes = ByteArray(bufferSize) - audioInputStream.read(audioBytes) - return audioBytes - } - - fun getAudioSegment( - audioData: ByteArray, - sampleRate: Float, - bytesPerFrame: Int, - startSecond: Float, - durationInSeconds: Float - ): ByteArray { - val startSample = (startSecond * sampleRate).toInt().coerceAtLeast(0) - val numSamples = (durationInSeconds * sampleRate).toInt() - - val startByte = startSample * bytesPerFrame - val numBytes = numSamples * bytesPerFrame - - val endByte = (startByte + numBytes).coerceAtMost(audioData.size) - - return audioData.copyOfRange(startByte, endByte) - } - - - - private fun performFFT(buffer: ByteArray): DoubleArray { - val numSamples = buffer.size / 2 - val audioData = DoubleArray(numSamples) - - // Convert byte pairs (little-endian) to signed 16-bit samples - for (i in 0 until numSamples) { - val low = buffer[i * 2].toInt() and 0xff - val high = buffer[i * 2 + 1].toInt() - val sample = (high shl 8) or low - audioData[i] = sample / 32768.0 // Normalize to [-1, 1] - } - - // Zero-padding to nearest power of 2 (optional, or cut to fixed size like 1024) - val fftSize = 1024 - val paddedData = DoubleArray(fftSize) - for (i in 0 until min(fftSize, audioData.size)) { - paddedData[i] = audioData[i] - } - - val fft = DoubleFFT_1D(fftSize) - fft.realForward(paddedData) - - return paddedData - } - - - - fun computeAmplitude(fftData: DoubleArray): DoubleArray { - val n = fftData.size - val amplitudes = DoubleArray(n / 2) - - for (i in amplitudes.indices) { - val real = fftData[2 * i] - val imag = if (2 * i + 1 < fftData.size) fftData[2 * i + 1] else 0.0 - amplitudes[i] = sqrt(real * real + imag * imag) - } - - // 简单归一化 - val maxAmp = amplitudes.maxOrNull() ?: 1.0 - return amplitudes.map { it / maxAmp }.toDoubleArray() - } - - - fun setVolume(vol: Float) { - var vol = vol - vol /= 2 - vol += 0.5f - val volumeControl = clip!!.getControl(FloatControl.Type.MASTER_GAIN) as FloatControl - // Change the volume to half way between minimum and maximum - val volume = (volumeControl.maximum - volumeControl.minimum) * vol + volumeControl.minimum - volumeControl.value = volume - } - - fun convert(sourcePath: String, targetPath: String) { - try { - val converter = Converter() - val sourceFile = File(sourcePath) - val targetFile = File(targetPath) - converter.convert(sourceFile.path, targetFile.path) - } catch (e: JavaLayerException) { - e.printStackTrace() - } - } - - fun stop() { - clip!!.stop() - } - - fun start() { - clip!!.start() - } - - @JvmStatic - val duration: Double - get() = (clip!!.microsecondLength / 1000f / 1000f / 60f).toDouble() -} diff --git a/shared/java/top/fpsmaster/modules/music/MusicPlayer.java b/shared/java/top/fpsmaster/modules/music/MusicPlayer.java index 865f2ffb..967b0f84 100644 --- a/shared/java/top/fpsmaster/modules/music/MusicPlayer.java +++ b/shared/java/top/fpsmaster/modules/music/MusicPlayer.java @@ -2,10 +2,13 @@ import top.fpsmaster.FPSMaster; +import javax.sound.sampled.LineUnavailableException; import java.io.File; +import java.io.IOException; -public class MusicPlayer { +import static java.lang.Math.min; +public class MusicPlayer { public static PlayList playList = new PlayList(); public static int mode = 0; public static long startTime = 0; @@ -17,7 +20,7 @@ public static float getPlayProgress() { if (isPlaying && JLayerHelper.clip != null) { curPlayProgress = JLayerHelper.getProgress(); } - return Math.min(curPlayProgress, 1f); + return min(curPlayProgress, 1f); } public static void play() { @@ -26,6 +29,10 @@ public static void play() { JLayerHelper.start(); } + public static double[] getCurve() { + return JLayerHelper.loudnessCurve; + } + public static void pause() { isPlaying = false; if (JLayerHelper.clip == null) return; @@ -46,10 +53,15 @@ public static void playFile(String path) { JLayerHelper.clip.stop(); JLayerHelper.clip.close(); } - final String filePath = path.replace(".mp3", ".wav"); - final float v = Float.parseFloat(FPSMaster.configManager.configure.getOrCreate("volume", "1")); + float v = Float.parseFloat(FPSMaster.configManager.configure.getOrCreate("volume", "1")); FPSMaster.async.runnable(() -> { - JLayerHelper.playWAV(filePath); + try { + JLayerHelper.playWAV(path.replace(".mp3", ".wav")); + } catch (IOException e) { + throw new RuntimeException(e); + } catch (LineUnavailableException e) { + throw new RuntimeException(e); + } setVolume(v); }); } diff --git a/shared/java/top/fpsmaster/modules/music/MusicPlayer.kt b/shared/java/top/fpsmaster/modules/music/MusicPlayer.kt deleted file mode 100644 index 2c637254..00000000 --- a/shared/java/top/fpsmaster/modules/music/MusicPlayer.kt +++ /dev/null @@ -1,69 +0,0 @@ -package top.fpsmaster.modules.music - -import top.fpsmaster.FPSMaster -import java.io.File -import kotlin.math.min - -object MusicPlayer { - var playList = PlayList() - var mode = 0 - var startTime: Long = 0 - var isPlaying = false - private var volume = 1f - private var curPlayProgress = 0f - val playProgress: Float - get() { - if (isPlaying) if (JLayerHelper.clip != null) curPlayProgress = JLayerHelper.progress - return min(curPlayProgress, 1f) - } - - fun play() { - isPlaying = true - if (JLayerHelper.clip == null) return - JLayerHelper.start() - } - - fun getCurve(): DoubleArray? { - return JLayerHelper.loudnessCurve - } - - fun pause() { - isPlaying = false - if (JLayerHelper.clip == null) return - JLayerHelper.stop() - } - - fun stop() { - isPlaying = false - if (JLayerHelper.clip == null) return - JLayerHelper.stop() - } - - @JvmStatic - fun playFile(path: String) { - val file = File(path) - if (file.exists()) { - JLayerHelper.convert(path, path.replace(".mp3", ".wav")) - if (JLayerHelper.clip != null) { - JLayerHelper.clip!!.stop() - JLayerHelper.clip!!.close() - } - val v = FPSMaster.configManager.configure.getOrCreate("volume", "1").toFloat() - FPSMaster.async.runnable { - JLayerHelper.playWAV(path.replace(".mp3", ".wav")) - setVolume(v) - } - } - } - - fun getVolume(): Float { - return volume - } - - fun setVolume(volume: Float) { - MusicPlayer.volume = volume - if (JLayerHelper.clip == null) return - JLayerHelper.setVolume(volume) - FPSMaster.configManager.configure["volume"] = volume.toString() - } -} From ea4dcc13a3aad785fd7b1b2c013e069aedd71aa2 Mon Sep 17 00:00:00 2001 From: SuperSkidder Date: Sat, 12 Apr 2025 00:07:51 +0800 Subject: [PATCH 009/193] =?UTF-8?q?fix:=20music=20visualization=EF=BC=88ja?= =?UTF-8?q?va=EF=BC=89=20change:=20add=20better=20font=20option=20to=20Mus?= =?UTF-8?q?icOverlay=20fix:=20music=20play=20bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../fpsmaster/features/GlobalSubmitter.java | 1 + .../impl/interfaces/MusicOverlay.java | 4 +- .../modules/music/IngameOverlay.java | 49 +++++++++---------- .../fpsmaster/modules/music/JLayerHelper.java | 15 +++--- .../ui/custom/impl/LyricsComponent.java | 5 +- 5 files changed, 37 insertions(+), 37 deletions(-) diff --git a/shared/java/top/fpsmaster/features/GlobalSubmitter.java b/shared/java/top/fpsmaster/features/GlobalSubmitter.java index f60ba856..7b4b8cac 100644 --- a/shared/java/top/fpsmaster/features/GlobalSubmitter.java +++ b/shared/java/top/fpsmaster/features/GlobalSubmitter.java @@ -41,6 +41,7 @@ public void onChatSend(EventSendChatMessage e) { public void onTick(EventTick e) { if (musicSwitchTimer.delay(1000)) { if (MusicPlayer.isPlaying && MusicPlayer.getPlayProgress() > 0.999) { + MusicPlayer.curPlayProgress = 0f; MusicPlayer.playList.next(); } } diff --git a/shared/java/top/fpsmaster/features/impl/interfaces/MusicOverlay.java b/shared/java/top/fpsmaster/features/impl/interfaces/MusicOverlay.java index d92beb08..40b1aec3 100644 --- a/shared/java/top/fpsmaster/features/impl/interfaces/MusicOverlay.java +++ b/shared/java/top/fpsmaster/features/impl/interfaces/MusicOverlay.java @@ -21,12 +21,12 @@ public class MusicOverlay extends InterfaceModule { public MusicOverlay() { super("MusicDisplay", Category.Interface); - addSettings(amplitude, progressColor, color); + addSettings(amplitude, progressColor, color, betterFont, fontShadow); } @Subscribe public void onRender(EventRender2D e) { - if (timer.delay(100)) { + if (timer.delay(50)) { JLayerHelper.updateLoudness(); } IngameOverlay.onRender(); diff --git a/shared/java/top/fpsmaster/modules/music/IngameOverlay.java b/shared/java/top/fpsmaster/modules/music/IngameOverlay.java index 39281b66..b156b26f 100644 --- a/shared/java/top/fpsmaster/modules/music/IngameOverlay.java +++ b/shared/java/top/fpsmaster/modules/music/IngameOverlay.java @@ -15,47 +15,44 @@ public class IngameOverlay { private static float songProgress = 0f; - private static Double[] smoothCurve = new Double[0]; + private static double[] smoothCurve = new double[0]; public static void onRender() { if (MusicPlayer.playList.getCurrent() != -1) { ScaledResolution sr = new ScaledResolution(Utility.mc); - if (MusicPlayer.getCurve().length !=0) { - float width = Math.max((sr.getScaledWidth() / 2f - 100) / MusicPlayer.getCurve().length, 1f); - float x = 0f; - - if (smoothCurve.length != MusicPlayer.getCurve().length) { - smoothCurve = new Double[MusicPlayer.getCurve().length]; + double[] curve = MusicPlayer.getCurve(); + if (curve.length != 0) { + int numBars = 60; // 你希望显示的频谱柱条数 + if (smoothCurve.length != numBars) { + smoothCurve = new double[numBars]; } - for (int i = 0; i < MusicPlayer.getCurve().length; i++) { - smoothCurve[i] = AnimationUtils.base(smoothCurve[i], MusicPlayer.getCurve()[i], 0.15); - } - - double[] curve = MusicPlayer.getCurve(); - int fftSize = 1024; - double sampleRate = 44100.0; - double[] frequencies = new double[fftSize / 2]; - for (int i = 0; i < frequencies.length; i++) { - frequencies[i] = i * sampleRate / fftSize; - } + float width = (float) sr.getScaledWidth() / numBars; float screenWidth = sr.getScaledWidth(); float screenHeight = sr.getScaledHeight(); - for (int i = 0; i < curve.length; i++) { - double freq = frequencies[i]; - double magnitude = Math.min(Math.max(curve[i], 0.0), 1.0); - - float xPos = (float) (freq / 22050.0 * screenWidth); - float height = (float) (magnitude * 100f * MusicOverlay.amplitude.value.floatValue()); + int binsPerBar = curve.length / numBars; + + for (int bar = 0; bar < numBars; bar++) { + double sum = 0.0; + for (int j = 0; j < binsPerBar; j++) { + int idx = bar * binsPerBar + j; + sum += Math.max(curve[idx], 0.0); + } + double averageMagnitude = sum / binsPerBar; + averageMagnitude = Math.min(averageMagnitude, 1.0); + averageMagnitude = Math.sqrt(averageMagnitude); + smoothCurve[bar] = AnimationUtils.base(smoothCurve[bar], averageMagnitude, 0.1); + float xPos = (float) bar / numBars * screenWidth; + float height = (float) (smoothCurve[bar] * 100f * MusicOverlay.amplitude.value.floatValue()); Render2DUtils.drawRect( xPos, screenHeight - height, - 2f, + width, height, - MusicOverlay.color.getRGB() + MusicOverlay.color.getColor() ); } } diff --git a/shared/java/top/fpsmaster/modules/music/JLayerHelper.java b/shared/java/top/fpsmaster/modules/music/JLayerHelper.java index 9ea4c08a..d3d7369a 100644 --- a/shared/java/top/fpsmaster/modules/music/JLayerHelper.java +++ b/shared/java/top/fpsmaster/modules/music/JLayerHelper.java @@ -27,16 +27,16 @@ public static float getProgress() { public static void playWAV(String wavFile) throws IOException, LineUnavailableException { File soundFile = new File(wavFile); try { + AudioInputStream aud = AudioSystem.getAudioInputStream(soundFile); audIn = AudioSystem.getAudioInputStream(soundFile); + audioBytes = readAudioData(audIn); + clip = AudioSystem.getClip(); + if (clip == null) return; + clip.open(aud); + clip.start(); } catch (UnsupportedAudioFileException e) { e.printStackTrace(); - return; } - audioBytes = readAudioData(audIn); - clip = AudioSystem.getClip(); - if (clip == null) return; - clip.open(audIn); - clip.start(); } public static void seek(float progress) { @@ -50,7 +50,6 @@ public static void updateLoudness() { AudioFormat format = audIn.getFormat(); if (format.getEncoding() != AudioFormat.Encoding.PCM_SIGNED || format.getSampleSizeInBits() != 16) { - System.out.println("Unsupported format: " + format); return; } @@ -165,6 +164,6 @@ public static void start() { } public static double getDuration() { - return (clip.getMicrosecondLength() / 1_000_000.0 / 60.0); + return clip.getMicrosecondLength() / 1000000.0 / 60.0; } } diff --git a/shared/java/top/fpsmaster/ui/custom/impl/LyricsComponent.java b/shared/java/top/fpsmaster/ui/custom/impl/LyricsComponent.java index c2086530..723cf98d 100644 --- a/shared/java/top/fpsmaster/ui/custom/impl/LyricsComponent.java +++ b/shared/java/top/fpsmaster/ui/custom/impl/LyricsComponent.java @@ -102,8 +102,11 @@ private float drawWord(Word word, float xOffset, float y, Line line) { drawString(20, word.content, xOffset, y + 7 - Math.min(animation2, 1f) * 3, Render2DUtils.reAlpha(LyricsDisplay.textColor.getColor(), (int) Math.min(animation * 255, 255)).getRGB()); return getStringWidth(20, word.content); + }else{ + drawString(20, word.content, xOffset, y + 7, + Render2DUtils.reAlpha(LyricsDisplay.textColor.getColor(), (int) Math.min(line.alpha * 120, 255)).getRGB()); + return getStringWidth(20, word.content); } - return 0; } private float drawWordBG(Word word, float xOffset, float y, Line line) { From 5809f7ad786dc5ee5c1bb00c2dc9e22bcca04327 Mon Sep 17 00:00:00 2001 From: SuperSkidder <61504912+SuperSkidder@users.noreply.github.com> Date: Sat, 12 Apr 2025 00:12:56 +0800 Subject: [PATCH 010/193] Update README.md --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 5e71ef3d..fb951091 100644 --- a/README.md +++ b/README.md @@ -26,11 +26,11 @@ FPSMaster 是一个免费、强大的 Minecraft PvP 客户端。 - [x] 组件尺寸自定义 - [ ] 重构MusicPlayer界面 - [ ] 支持播放无损/VIP音乐 -- [ ] 修复音乐可视化 -- [ ] 添加脚本插件系统 +- [x] 修复音乐可视化 +- [x] 添加脚本插件系统 - [ ] 添加界面自动对齐 - [ ] 添加翻译功能 -- [ ] 迁移优化代码 +- [x] 迁移优化代码 - [ ] 自动更新 - [ ] 多语言界面 - [ ] 重写IRC模块 From d17ea624d7670dea7fdd17489875670ecc846a54 Mon Sep 17 00:00:00 2001 From: SuperSkidder <61504912+SuperSkidder@users.noreply.github.com> Date: Sat, 12 Apr 2025 00:22:06 +0800 Subject: [PATCH 011/193] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index fb951091..434ca639 100644 --- a/README.md +++ b/README.md @@ -64,7 +64,7 @@ FPSMaster 是一个免费、强大的 Minecraft PvP 客户端。 -![Alt](https://repobeats.axiom.co/api/embed/e686f6313e4406de4286bf27e0db4a2bf5a31b7f.svg "Repobeats analytics image") +![Alt](https://repobeats.axiom.co/api/embed/7d755c063aa9a34d74edb7045541e8bfe6e09b89.svg "Repobeats analytics image") ## 引用的开源项目: [eventbus](https://github.com/therealbush/eventbus) From ccc9789fda429b63d48acc2072d4e367ba57ac93 Mon Sep 17 00:00:00 2001 From: SuperSkidder Date: Thu, 1 May 2025 21:38:48 +0800 Subject: [PATCH 012/193] =?UTF-8?q?feat:=20=E6=B7=BB=E5=8A=A0=E6=A0=BC?= =?UTF-8?q?=E6=8C=A1=E6=91=87=E6=91=86=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../fpsmaster/features/impl/optimizes/OldAnimations.java | 7 ++++++- shared/resources/assets/minecraft/client/lang/zh_cn.lang | 6 ++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/shared/java/top/fpsmaster/features/impl/optimizes/OldAnimations.java b/shared/java/top/fpsmaster/features/impl/optimizes/OldAnimations.java index 617077a3..785ef619 100644 --- a/shared/java/top/fpsmaster/features/impl/optimizes/OldAnimations.java +++ b/shared/java/top/fpsmaster/features/impl/optimizes/OldAnimations.java @@ -2,6 +2,7 @@ import net.minecraft.client.Minecraft; import net.minecraft.client.entity.EntityPlayerSP; +import net.minecraft.entity.EntityLivingBase; import top.fpsmaster.event.Subscribe; import top.fpsmaster.event.events.EventTick; import top.fpsmaster.features.manager.Category; @@ -19,6 +20,7 @@ public class OldAnimations extends Module { public static BooleanSetting oldBow = new BooleanSetting("OldBow", true); public static BooleanSetting oldSwing = new BooleanSetting("OldSwing", true); public static BooleanSetting oldUsing = new BooleanSetting("OldUsing", true); + public static BooleanSetting blockSwing = new BooleanSetting("BlockSwing", true); public static BooleanSetting oldDamage = new BooleanSetting("OldDamage", true); public static BooleanSetting blockHit = new BooleanSetting("BlockHit", true); public static NumberSetting x = new NumberSetting("X", 0, -1, 1, 0.01); @@ -34,7 +36,7 @@ public class OldAnimations extends Module { public OldAnimations() { super("OldAnimations", Category.OPTIMIZE); - addSettings(noShield, animationSneak, oldRod, oldBow, oldSwing, oldDamage, oldUsing, blockHit, oldBlock, x, y, z); + addSettings(noShield, animationSneak, oldRod, oldBow, oldSwing, blockSwing, oldDamage, oldUsing, blockHit, oldBlock, x, y, z); } @Override @@ -66,6 +68,9 @@ public void onTick(EventTick event) { delta *= 0.4f; eyeHeight = START_HEIGHT - delta; } + if (Minecraft.getMinecraft().gameSettings.keyBindAttack.isKeyDown() && thePlayer.isUsingItem() && blockSwing.value) { + ((EntityLivingBase) thePlayer).swingItem(); + } } public static float getClientEyeHeight(float partialTicks) { diff --git a/shared/resources/assets/minecraft/client/lang/zh_cn.lang b/shared/resources/assets/minecraft/client/lang/zh_cn.lang index 848f78d1..ed7dec85 100644 --- a/shared/resources/assets/minecraft/client/lang/zh_cn.lang +++ b/shared/resources/assets/minecraft/client/lang/zh_cn.lang @@ -175,6 +175,11 @@ performance.screenshot=截图方式 performance.screenshot.fast=快速 performance.screenshot.vanilla=原版 performance.blur=界面高斯模糊 +performance.fontoptimize=字体优化 +performance.staticparticlecolor=静态粒子颜色 +performance.limitchunks=限制区块加载 +performance..chunkupdatelimit=区块更新限制 + fullbright=保持亮度 fullbright.desc=保持亮度 @@ -226,6 +231,7 @@ oldanimations.noshield=不显示盾牌 oldanimations.oldrod=旧鱼竿 oldanimations.oldbow=旧弓 oldanimations.oldswing=旧挥动 +oldanimations.blockswing=格挡挥动 oldanimations.oldblock=旧格挡 oldanimations.olddamage=旧伤害动画 oldanimations.oldusing=旧使用动画 From 0b1b3e72c2aff9132c00c5e2cb54b4e3cfac7aaa Mon Sep 17 00:00:00 2001 From: SuperSkidder Date: Thu, 1 May 2025 21:39:05 +0800 Subject: [PATCH 013/193] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E7=89=A9?= =?UTF-8?q?=E5=93=81=E6=B8=B2=E6=9F=93=E9=94=99=E8=AF=AF=20close=20#72?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ui/custom/impl/ArmorDisplayComponent.java | 41 +++++++++++-------- .../impl/InventoryDisplayComponent.java | 2 + 2 files changed, 26 insertions(+), 17 deletions(-) diff --git a/shared/java/top/fpsmaster/ui/custom/impl/ArmorDisplayComponent.java b/shared/java/top/fpsmaster/ui/custom/impl/ArmorDisplayComponent.java index 4c867d45..c24ad7f5 100644 --- a/shared/java/top/fpsmaster/ui/custom/impl/ArmorDisplayComponent.java +++ b/shared/java/top/fpsmaster/ui/custom/impl/ArmorDisplayComponent.java @@ -16,7 +16,7 @@ import static top.fpsmaster.utils.Utility.mc; public class ArmorDisplayComponent extends Component { - + public ArmorDisplayComponent() { super(ArmorDisplay.class); } @@ -25,7 +25,7 @@ public ArmorDisplayComponent() { public void draw(float x, float y) { super.draw(x, y); List armorInventory = Arrays.asList(ProviderManager.mcProvider.getArmorInventory()); - + for (int i = 0; i < armorInventory.size(); i++) { ItemStack itemStack = armorInventory.get(i); int x1 = (int) (x + i * 18); @@ -46,38 +46,45 @@ public void draw(float x, float y) { drawRect(x1, y1, 16f, 16f, mod.backgroundColor.getColor()); if (itemStack == null) continue; + GlStateManager.disableCull(); + GlStateManager.disableBlend(); + GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F); + GlStateManager.enableRescaleNormal(); + GlStateManager.enableBlend(); + GlStateManager.tryBlendFuncSeparate(770, 771, 1, 0); RenderHelper.enableGUIStandardItemLighting(); - mc.getRenderItem().renderItemAndEffectIntoGUI(itemStack, x1, y1); + + + GlStateManager.pushMatrix(); + mc.getRenderItem().renderItemIntoGUI(itemStack, x1, y1); + GlStateManager.popMatrix(); mc.getRenderItem().renderItemOverlays(ProviderManager.mcProvider.getFontRenderer(), itemStack, x1, y1); + RenderHelper.disableStandardItemLighting(); - - GlStateManager.enableAlpha(); - GlStateManager.disableCull(); + GlStateManager.disableRescaleNormal(); GlStateManager.disableBlend(); - GlStateManager.disableLighting(); - GlStateManager.clear(256); if (ArmorDisplay.mode.value == 2) { // Draw durability int durability = itemStack.getMaxDamage() - itemStack.getItemDamage(); float dura = (float) durability / itemStack.getMaxDamage(); int color = -1; - + if (dura < 0.5) { color = (dura < 0.2) ? new Color(255, 20, 20).getRGB() : new Color(255, 255, 20).getRGB(); } - + String durabilityString = durability > 0 ? durability + "/" + itemStack.getMaxDamage() : "0/" + itemStack.getMaxDamage(); - + drawRect( - x1 + 18, - y1, - getStringWidth(16, durabilityString) + 4, - 16f, - mod.backgroundColor.getColor() + x1 + 18, + y1, + getStringWidth(16, durabilityString) + 4, + 16f, + mod.backgroundColor.getColor() ); - + drawString(16, durabilityString, x1 + 20, y1 + 2, color); } } diff --git a/shared/java/top/fpsmaster/ui/custom/impl/InventoryDisplayComponent.java b/shared/java/top/fpsmaster/ui/custom/impl/InventoryDisplayComponent.java index f98e4425..e674a56f 100644 --- a/shared/java/top/fpsmaster/ui/custom/impl/InventoryDisplayComponent.java +++ b/shared/java/top/fpsmaster/ui/custom/impl/InventoryDisplayComponent.java @@ -38,6 +38,8 @@ public void draw(float x, float y) { int x1 = (int) (x + count * 18); int y1 = (int) (y + linecount * 20); + GlStateManager.disableCull(); + GlStateManager.disableBlend(); RenderHelper.enableGUIStandardItemLighting(); mc.getRenderItem().renderItemAndEffectIntoGUI(itemStack, x1, y1); mc.getRenderItem().renderItemOverlays(ProviderManager.mcProvider.getFontRenderer(), itemStack, x1, y1); From 21d75bad3cffcd38f1eb978b6aa6afabddad8b9c Mon Sep 17 00:00:00 2001 From: SuperSkidder Date: Thu, 1 May 2025 21:46:24 +0800 Subject: [PATCH 014/193] =?UTF-8?q?fix:=20=E6=98=BE=E7=A4=BA=E5=8E=9F?= =?UTF-8?q?=E7=89=88=E5=A4=9A=E4=BA=BA=E6=B8=B8=E6=88=8F=E7=95=8C=E9=9D=A2?= =?UTF-8?q?=20close=20#78?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../forge/mixin/MixinGuiMultiplayer.java | 16 ++++++++++++++++ v1.8.9/src/main/resources/mixins.fpsmaster.json | 1 + 2 files changed, 17 insertions(+) create mode 100644 v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinGuiMultiplayer.java diff --git a/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinGuiMultiplayer.java b/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinGuiMultiplayer.java new file mode 100644 index 00000000..ce4f0c9f --- /dev/null +++ b/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinGuiMultiplayer.java @@ -0,0 +1,16 @@ +package top.fpsmaster.forge.mixin; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.GuiMultiplayer; +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(GuiMultiplayer.class) +public class MixinGuiMultiplayer { + @Inject(method = "initGui", at = @At("HEAD")) + public void initGui(CallbackInfo ci) { + Minecraft.getMinecraft().displayGuiScreen(new top.fpsmaster.ui.mc.GuiMultiplayer()); + } +} diff --git a/v1.8.9/src/main/resources/mixins.fpsmaster.json b/v1.8.9/src/main/resources/mixins.fpsmaster.json index 07bdac2b..b033ef42 100644 --- a/v1.8.9/src/main/resources/mixins.fpsmaster.json +++ b/v1.8.9/src/main/resources/mixins.fpsmaster.json @@ -25,6 +25,7 @@ "MixinGuiContainer", "MixinGuiIngame", "MixinGuiIngameForge", + "MixinGuiMultiplayer", "MixinGuiNewChat", "MixinGuiPlayerOverlay", "MixinGuiScreen", From 46a4a5c9aee1b0bb26462e58f9009761504bda88 Mon Sep 17 00:00:00 2001 From: SuperSkidder Date: Thu, 1 May 2025 21:54:43 +0800 Subject: [PATCH 015/193] =?UTF-8?q?fix:=20=E9=BE=99=E7=BF=85=E8=86=80?= =?UTF-8?q?=E4=B8=8D=E6=98=BE=E7=A4=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- shared/java/top/fpsmaster/features/impl/render/DragonWings.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/shared/java/top/fpsmaster/features/impl/render/DragonWings.java b/shared/java/top/fpsmaster/features/impl/render/DragonWings.java index 4ab83609..d3671289 100644 --- a/shared/java/top/fpsmaster/features/impl/render/DragonWings.java +++ b/shared/java/top/fpsmaster/features/impl/render/DragonWings.java @@ -36,10 +36,12 @@ public void onEnable() { if (renderWings == null) { renderWings = new RenderWings(); } + EventDispatcher.registerListener(renderWings); } @Override public void onDisable() { + EventDispatcher.unregisterListener(renderWings); } public float[] getColors() { From dee76051394b78fe5a9ebe91ad71610980fa0e59 Mon Sep 17 00:00:00 2001 From: SuperSkidder Date: Fri, 2 May 2025 11:45:11 +0800 Subject: [PATCH 016/193] =?UTF-8?q?feat:=20=E6=8E=A8=E8=8D=90=E6=9C=8D?= =?UTF-8?q?=E5=8A=A1=E5=99=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../top/fpsmaster/ui/mc/GuiMultiplayer.java | 52 ++++++++++++++++--- 1 file changed, 46 insertions(+), 6 deletions(-) diff --git a/shared/java/top/fpsmaster/ui/mc/GuiMultiplayer.java b/shared/java/top/fpsmaster/ui/mc/GuiMultiplayer.java index e8c6747f..72a4bc87 100644 --- a/shared/java/top/fpsmaster/ui/mc/GuiMultiplayer.java +++ b/shared/java/top/fpsmaster/ui/mc/GuiMultiplayer.java @@ -1,6 +1,10 @@ package top.fpsmaster.ui.mc; import com.google.common.collect.Lists; +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; import net.minecraft.client.gui.*; import net.minecraft.client.multiplayer.ServerData; import net.minecraft.client.multiplayer.ServerList; @@ -17,11 +21,14 @@ import top.fpsmaster.FPSMaster; import top.fpsmaster.font.impl.UFontRenderer; import top.fpsmaster.interfaces.ProviderManager; +import top.fpsmaster.modules.client.AsyncTask; import top.fpsmaster.ui.click.component.ScrollContainer; import top.fpsmaster.ui.common.GuiButton; import top.fpsmaster.ui.screens.mainmenu.MainMenu; +import top.fpsmaster.utils.os.HttpRequest; import top.fpsmaster.utils.render.Render2DUtils; import top.fpsmaster.utils.render.ScaledGuiScreen; +import top.fpsmaster.utils.thirdparty.github.UpdateChecker; import top.fpsmaster.wrapper.ChatFormattingProvider; import java.awt.*; @@ -33,9 +40,13 @@ public class GuiMultiplayer extends ScaledGuiScreen { private ServerData selectedServer; private static final Logger logger = LogManager.getLogger(); private final List servers = Lists.newArrayList(); + private final List serverListDisplay = Lists.newArrayList(); private final List serverListInternet = Lists.newArrayList(); + private static List serverListRecommended = Lists.newArrayList(); public final OldServerPinger oldServerPinger = new OldServerPinger(); + private Gson gson = new GsonBuilder().setPrettyPrinting().create(); + String action = ""; GuiButton join = new GuiButton("加入服务器", () -> { @@ -87,6 +98,19 @@ public void initGui() { for (ServerData server : servers) { this.serverListInternet.add(new ServerListEntry(this, server)); } + serverListDisplay.clear(); + serverListDisplay.addAll(serverListInternet); + if (serverListRecommended.size() == 0) { + AsyncTask asyncTask = new AsyncTask(100); + asyncTask.runnable(() -> { + String s = HttpRequest.get("https://service.fpsmaster.top/getServers"); + System.out.println(s); + JsonObject jsonObject = gson.fromJson(s, JsonObject.class); + jsonObject.get("data").getAsJsonArray().forEach(e -> { + this.serverListRecommended.add(new ServerListEntry(this, new ServerData(e.getAsJsonObject().get("name").getAsString() + " - 推荐服务器", e.getAsJsonObject().get("address").getAsString(), false))); + }); + }); + } } @Override @@ -135,6 +159,8 @@ public void saveServerList() { } ScrollContainer scrollContainer = new ScrollContainer(); + int tab = 0; + @Override public void render(int mouseX, int mouseY, float partialTicks) { @@ -146,11 +172,10 @@ public void render(int mouseX, int mouseY, float partialTicks) { title.drawCenteredString("多人游戏", width / 2f, 16, -1); Render2DUtils.drawOptimizedRoundedRect((width - 180) / 2f, 30, 180, 24, 3, new Color(255, 255, 255, 80).getRGB()); - Render2DUtils.drawOptimizedRoundedRect((width - 176) / 2f, 32, 86, 20, 3, new Color(113, 127, 254).getRGB()); + Render2DUtils.drawOptimizedRoundedRect((width - 176) / 2f + 90 * tab, 32, 86, 20, 3, new Color(113, 127, 254).getRGB()); FPSMaster.fontManager.s16.drawCenteredString("服务器列表", (width - 90) / 2f, 36, -1); FPSMaster.fontManager.s16.drawCenteredString("推荐服务器", (width + 90) / 2f, 36, -1); - GL11.glPushMatrix(); GL11.glEnable(GL11.GL_SCISSOR_TEST); Render2DUtils.doGlScissor((width - 400) / 2f, 60f, 400f, height - 120, scaleFactor); @@ -158,7 +183,7 @@ public void render(int mouseX, int mouseY, float partialTicks) { float y = 70 + scrollContainer.getScroll(); Render2DUtils.drawOptimizedRoundedRect((width - 400) / 2f, y - 10, 400, height - y, 5, new Color(0, 0, 0, 100).getRGB()); int index = 0; - for (ServerListEntry server : serverListInternet) { + for (ServerListEntry server : serverListDisplay) { if (server.getServerData() == null) { return; } @@ -173,7 +198,7 @@ public void render(int mouseX, int mouseY, float partialTicks) { index++; y += 58; } - scrollContainer.setHeight(y - 70 - scrollContainer.getScroll()); + scrollContainer.setHeight(y - 50 - scrollContainer.getScroll()); }); GL11.glDisable(GL11.GL_SCISSOR_TEST); GL11.glPopMatrix(); @@ -219,10 +244,24 @@ public void onClick(int mouseX, int mouseY, int mouseButton) { back.mouseClick(mouseX, mouseY, mouseButton); - int y = 80; + Render2DUtils.drawOptimizedRoundedRect((width - 180) / 2f, 30, 180, 24, 3, new Color(255, 255, 255, 80).getRGB()); + Render2DUtils.drawOptimizedRoundedRect((width - 176) / 2f, 32, 86, 20, 3, new Color(113, 127, 254).getRGB()); + FPSMaster.fontManager.s16.drawCenteredString("服务器列表", (width - 90) / 2f, 36, -1); + FPSMaster.fontManager.s16.drawCenteredString("推荐服务器", (width + 90) / 2f, 36, -1); + if (Render2DUtils.isHovered((width - 180) / 2f, 30, 90, 24, mouseX, mouseY)) { + tab = 0; + serverListDisplay.clear(); + serverListDisplay.addAll(serverListInternet); + } else if (Render2DUtils.isHovered((width) / 2f, 30, 90, 24, mouseX, mouseY)) { + tab = 1; + serverListDisplay.clear(); + serverListDisplay.addAll(serverListRecommended); + } + + int y = 80; int index = 0; - for (ServerListEntry server : serverListInternet) { + for (ServerListEntry server : serverListDisplay) { if (server.getServerData() == null) { return; } @@ -237,6 +276,7 @@ public void onClick(int mouseX, int mouseY, int mouseButton) { y += 54; } + } From 8cb1745fe0ff1b9429fab481083ce03ba82a2c44 Mon Sep 17 00:00:00 2001 From: SuperSkidder Date: Fri, 2 May 2025 11:47:09 +0800 Subject: [PATCH 017/193] =?UTF-8?q?fix:=20=E6=98=BE=E7=A4=BA=E6=8E=A8?= =?UTF-8?q?=E8=8D=90=E6=9C=8D=E5=8A=A1=E5=99=A8=E7=9A=84description?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- shared/java/top/fpsmaster/ui/mc/GuiMultiplayer.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/shared/java/top/fpsmaster/ui/mc/GuiMultiplayer.java b/shared/java/top/fpsmaster/ui/mc/GuiMultiplayer.java index 72a4bc87..c71e7483 100644 --- a/shared/java/top/fpsmaster/ui/mc/GuiMultiplayer.java +++ b/shared/java/top/fpsmaster/ui/mc/GuiMultiplayer.java @@ -107,7 +107,7 @@ public void initGui() { System.out.println(s); JsonObject jsonObject = gson.fromJson(s, JsonObject.class); jsonObject.get("data").getAsJsonArray().forEach(e -> { - this.serverListRecommended.add(new ServerListEntry(this, new ServerData(e.getAsJsonObject().get("name").getAsString() + " - 推荐服务器", e.getAsJsonObject().get("address").getAsString(), false))); + this.serverListRecommended.add(new ServerListEntry(this, new ServerData(e.getAsJsonObject().get("name").getAsString() + " - " + e.getAsJsonObject().get("description").getAsString(), e.getAsJsonObject().get("address").getAsString(), false))); }); }); } From f7b6ae41afe6dffe14f824543f10bdc557627994 Mon Sep 17 00:00:00 2001 From: SuperSkidder Date: Fri, 2 May 2025 12:43:22 +0800 Subject: [PATCH 018/193] =?UTF-8?q?feat:=20=E6=A0=BC=E6=8C=A1=E5=8A=A8?= =?UTF-8?q?=E7=94=BB=E3=80=81=E6=9B=B4=E5=A5=BD=E7=9A=84=E4=BC=A4=E5=AE=B3?= =?UTF-8?q?=E6=98=BE=E7=A4=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../impl/optimizes/OldAnimations.java | 6 +- .../features/impl/render/DamageIndicator.java | 29 ++--- .../assets/minecraft/client/lang/zh_cn.lang | 13 +++ .../forge/mixin/MixinItemRenderer.java | 101 +++++++++++++++++- 4 files changed, 131 insertions(+), 18 deletions(-) diff --git a/shared/java/top/fpsmaster/features/impl/optimizes/OldAnimations.java b/shared/java/top/fpsmaster/features/impl/optimizes/OldAnimations.java index 785ef619..eb11e6a4 100644 --- a/shared/java/top/fpsmaster/features/impl/optimizes/OldAnimations.java +++ b/shared/java/top/fpsmaster/features/impl/optimizes/OldAnimations.java @@ -8,6 +8,7 @@ import top.fpsmaster.features.manager.Category; import top.fpsmaster.features.manager.Module; import top.fpsmaster.features.settings.impl.BooleanSetting; +import top.fpsmaster.features.settings.impl.ModeSetting; import top.fpsmaster.features.settings.impl.NumberSetting; import top.fpsmaster.interfaces.ProviderManager; @@ -16,16 +17,17 @@ public class OldAnimations extends Module { public static BooleanSetting noShield = new BooleanSetting("NoShield", true); public static BooleanSetting animationSneak = new BooleanSetting("AnimationSneak", true); public static BooleanSetting oldBlock = new BooleanSetting("OldBlock", true); + public static ModeSetting animationMode = new ModeSetting("AnimationMode", 0, () -> oldBlock.getValue(), "1.7", "Swang", "Sigma", "Swank", "Swong", "Debug", "Luna", "Jigsaw", "Jello", "Push"); public static BooleanSetting oldRod = new BooleanSetting("OldRod", true); public static BooleanSetting oldBow = new BooleanSetting("OldBow", true); public static BooleanSetting oldSwing = new BooleanSetting("OldSwing", true); public static BooleanSetting oldUsing = new BooleanSetting("OldUsing", true); public static BooleanSetting blockSwing = new BooleanSetting("BlockSwing", true); public static BooleanSetting oldDamage = new BooleanSetting("OldDamage", true); - public static BooleanSetting blockHit = new BooleanSetting("BlockHit", true); public static NumberSetting x = new NumberSetting("X", 0, -1, 1, 0.01); public static NumberSetting y = new NumberSetting("Y", 0, -1, 1, 0.01); public static NumberSetting z = new NumberSetting("Z", 0, -1, 1, 0.01); + public static NumberSetting scale = new NumberSetting("Scale", 1, 0, 3, 0.01); public static boolean using = false; @@ -36,7 +38,7 @@ public class OldAnimations extends Module { public OldAnimations() { super("OldAnimations", Category.OPTIMIZE); - addSettings(noShield, animationSneak, oldRod, oldBow, oldSwing, blockSwing, oldDamage, oldUsing, blockHit, oldBlock, x, y, z); + addSettings(noShield, animationSneak, oldRod, oldBow, oldSwing, blockSwing, oldDamage, oldUsing, oldBlock, animationMode, x, y, z); } @Override diff --git a/shared/java/top/fpsmaster/features/impl/render/DamageIndicator.java b/shared/java/top/fpsmaster/features/impl/render/DamageIndicator.java index a7f8f3d0..effe6190 100644 --- a/shared/java/top/fpsmaster/features/impl/render/DamageIndicator.java +++ b/shared/java/top/fpsmaster/features/impl/render/DamageIndicator.java @@ -35,19 +35,20 @@ public static void addIndicator(float x, float y, float z, float damage) { @Subscribe public void onRender(EventRender3D event) { ArrayList indicatorsRemove = new ArrayList<>(); - for (int i = 0; i < indicators.size(); i++) { - Damage indicator = indicators.get(i); + for (Damage indicator : indicators) { doRender(indicator); - if (timer.delay(50)) { - indicator.animation += 0.1f; + } + if (timer.delay(20)) { + for (Damage indicator : indicators) { + indicator.animation += 0.05f; + if (indicator.animation > 1) { + indicatorsRemove.add(indicator); + } } - if (indicator.animation > 1) { - indicatorsRemove.add(indicator); + if (!indicatorsRemove.isEmpty()) { + indicators.removeAll(indicatorsRemove); } } - if (!indicatorsRemove.isEmpty()) { - indicators.removeAll(indicatorsRemove); - } } public void doRender(Damage indicator) { @@ -63,7 +64,7 @@ public void doRender(Damage indicator) { GL11.glDisable(3553); float partialTicks = ProviderManager.timerProvider.getRenderPartialTicks(); double x = indicator.x + 1 - ProviderManager.renderManagerProvider.renderPosX(); - double y = indicator.y - ProviderManager.renderManagerProvider.renderPosY(); + double y = indicator.y - ProviderManager.renderManagerProvider.renderPosY() + 1; double z = indicator.z + 1 - ProviderManager.renderManagerProvider.renderPosZ(); float scale = 0.065f; GlStateManager.translate(x, y + 1 + 0.5f - 1 / 2.0f, z); @@ -74,17 +75,21 @@ public void doRender(Damage indicator) { GlStateManager.disableDepth(); GlStateManager.disableBlend(); GlStateManager.disableLighting(); - Color color = new Color(20, 255, 20); + Color color = new Color(50, 255, 50, (int) (255 - indicator.animation * 255)); if (indicator.damage > 0) { - color = new Color(255, 20, 20); + color = new Color(224, 41, 41, (int) (255 - indicator.animation * 255)); } GL11.glEnable(3553); GL11.glDisable(3042); GL11.glDisable(2848); + GL11.glEnable(GL11.GL_ALPHA); + GlStateManager.enableBlend(); ProviderManager.mcProvider.getFontRenderer().drawStringWithShadow(damage, -width + 5, indicator.animation * 10, color.getRGB()); GlStateManager.enableLighting(); GlStateManager.enableBlend(); GlStateManager.enableDepth(); + GlStateManager.disableBlend(); + GL11.glDisable(GL11.GL_ALPHA); GL11.glEnable(3553); GL11.glEnable(2929); GlStateManager.disableBlend(); diff --git a/shared/resources/assets/minecraft/client/lang/zh_cn.lang b/shared/resources/assets/minecraft/client/lang/zh_cn.lang index ed7dec85..fd416ffa 100644 --- a/shared/resources/assets/minecraft/client/lang/zh_cn.lang +++ b/shared/resources/assets/minecraft/client/lang/zh_cn.lang @@ -239,10 +239,23 @@ oldanimations.blockhit=格挡挥手 oldanimations.x=X oldanimations.y=Y oldanimations.z=Z +oldanimations.scale=缩放 oldanimations.blockx=格挡X oldanimations.blocky=格挡Y oldanimations.blockz=格挡Z +oldanimations.animationmode=格挡动画 oldanimations.animationsneak=潜行动画 +oldanimations.animationmode.1.7=1.7 +oldanimations.animationmode.swang=Swang +oldanimations.animationmode.sigma=Sigma +oldanimations.animationmode.swank=Swank +oldanimations.animationmode.swong=Swong +oldanimations.animationmode.debug=Debug +oldanimations.animationmode.luna=Luna +oldanimations.animationmode.jigsaw=Jigsaw +oldanimations.animationmode.jello=Jello +oldanimations.animationmode.push=Push + irc=客户端聊天 irc.desc=与相同客户端的用户聊天 diff --git a/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinItemRenderer.java b/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinItemRenderer.java index 8c88c13b..1d641b32 100644 --- a/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinItemRenderer.java +++ b/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinItemRenderer.java @@ -9,6 +9,7 @@ import net.minecraft.client.renderer.vertex.DefaultVertexFormats; import net.minecraft.entity.EntityLivingBase; import net.minecraft.item.*; +import net.minecraft.util.MathHelper; import org.lwjgl.opengl.GL11; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Overwrite; @@ -119,6 +120,99 @@ public void renderFireInFirstPerson(CallbackInfo ci) { } + private void drawBlocking(float swingProgress, float equippedProgress) { + GL11.glTranslated(OldAnimations.x.getValue().floatValue(), OldAnimations.y.getValue().floatValue(), OldAnimations.z.getValue().floatValue()); +// GL11.glScaled(OldAnimations.scale.getValue().floatValue(), OldAnimations.scale.getValue().floatValue(), 0); + if (OldAnimations.animationMode.isMode("Sigma")) { + this.transformFirstPersonItem(equippedProgress, 0.0f); + float swong = MathHelper.sin((float) (MathHelper.sqrt_float(swingProgress) * Math.PI)); + GlStateManager.rotate(-swong * 55 / 2.0F, -8.0F, -0.0F, 9.0F); + GlStateManager.rotate(-swong * 45, 1.0F, swong / 2, -0.0F); + this.doBlockTransformations(); + GL11.glTranslated(1.2, 0.3, 0.5); + GL11.glTranslatef(-1, mc.thePlayer.isSneaking() ? -0.1F : -0.2F, 0.2F); + } else if (OldAnimations.animationMode.isMode("Debug")) { + this.transformFirstPersonItem(0.2f, equippedProgress); + this.doBlockTransformations(); + GlStateManager.translate(-0.5, 0.2, 0.0); + } else if (OldAnimations.animationMode.isMode("Luna")) { + this.transformFirstPersonItem(swingProgress, 0.0F); + this.doBlockTransformations(); + final float sin2 = MathHelper.sin((float) (MathHelper.sqrt_float(equippedProgress) * Math.PI)); + GlStateManager.scale(1.0f, 1.0f, 1.0f); + GlStateManager.translate(-0.2f, 0.45f, 0.25f); + GlStateManager.rotate(-sin2 * 20.0f, -5.0f, -5.0f, 9.0f); + } else if (OldAnimations.animationMode.isMode("1.7")) { + this.transformFirstPersonItem(swingProgress - 0.3F, equippedProgress); + this.doBlockTransformations(); + } else if (OldAnimations.animationMode.isMode("Swang")) { + this.transformFirstPersonItem(swingProgress / 2.0F, equippedProgress); + float var15; + var15 = MathHelper.sin((float) (MathHelper.sqrt_float(equippedProgress) * Math.PI)); + GlStateManager.rotate(var15 * 30.0F / 2.0F, -var15, -0.0F, 9.0F); + GlStateManager.rotate(var15 * 40.0F, 1.0F, -var15 / 2.0F, -0.0F); + + this.doBlockTransformations(); + } else if (OldAnimations.animationMode.isMode("Swank")) { + this.transformFirstPersonItem(swingProgress / 2.0F, equippedProgress); + float var15; + var15 = MathHelper.sin((float) (MathHelper.sqrt_float(swingProgress) * Math.PI)); + GlStateManager.rotate(var15 * 30.0F, -var15, -0.0F, 9.0F); + GlStateManager.rotate(var15 * 40.0F, 1.0F, -var15, -0.0F); + + this.doBlockTransformations(); + } else if (OldAnimations.animationMode.isMode("Swong")) { + this.transformFirstPersonItem(swingProgress / 2.0F, 0.0F); + float var151 = MathHelper.sin((float) (MathHelper.sqrt_float(equippedProgress) * Math.PI)); + GlStateManager.rotate(-var151 * 40.0F / 2.0F, var151 / 2.0F, -0.0F, 9.0F); + GlStateManager.rotate(-var151 * 30.0F, 1.0F, var151 / 2.0F, -0.0F); + + this.doBlockTransformations(); + } else if (OldAnimations.animationMode.isMode("Jigsaw")) { + this.transformFirstPersonItem(0.1f, equippedProgress); + this.doBlockTransformations(); + GlStateManager.translate(-0.5, 0, 0); + } else if (OldAnimations.animationMode.isMode("Jello")) { + GlStateManager.translate(0.56F, -0.52F, -0.71999997F); + GlStateManager.translate(0.0F, 0 * -0.6F, 0.0F); + GlStateManager.rotate(45.0F, 0.0F, 1.0F, 0.0F); + float var3 = MathHelper.sin((float) (0.0F * 0.0F * Math.PI)); + float var4 = MathHelper.sin((float) (MathHelper.sqrt_float(0.0F) * Math.PI)); + GlStateManager.rotate(var3 * -20.0F, 0.0F, 1.0F, 0.0F); + GlStateManager.rotate(var4 * -20.0F, 0.0F, 0.0F, 1.0F); + GlStateManager.rotate(var4 * -80.0F, 1.0F, 0.0F, 0.0F); + GlStateManager.scale(0.4F, 0.4F, 0.4F); + + GlStateManager.translate(-0.5F, 0.2F, 0.0F); + GlStateManager.rotate(30.0F, 0.0F, 1.0F, 0.0F); + GlStateManager.rotate(-80.0F, 1.0F, 0.0F, 0.0F); + GlStateManager.rotate(60.0F, 0.0F, 1.0F, 0.0F); + int alpha = (int) Math.min(255, + ((System.currentTimeMillis() % 255) > 255 / 2 + ? (Math.abs(Math.abs(System.currentTimeMillis()) % 255 - 255)) + : System.currentTimeMillis() % 255) * 2); + GlStateManager.translate(0.3f, -0.0f, 0.40f); + GlStateManager.rotate(0.0f, 0.0f, 0.0f, 1.0f); + GlStateManager.translate(0, 0.5f, 0); + + GlStateManager.rotate(90, 1.0f, 0.0f, -1.0f); + GlStateManager.translate(0.6f, 0.5f, 0); + GlStateManager.rotate(-90, 1.0f, 0.0f, -1.0f); + + GlStateManager.rotate(-10, 1.0f, 0.0f, -1.0f); + GlStateManager.rotate(mc.thePlayer.isSwingInProgress ? -alpha / 5f : 1, 1.0f, -0.0f, 1.0f); + } else if (OldAnimations.animationMode.isMode("Push")) { + this.transformFirstPersonItem(swingProgress, 0.0F); + this.doBlockTransformations(); + GlStateManager.rotate(-MathHelper.sin((float) (MathHelper.sqrt_float(equippedProgress) * Math.PI)) * 35.0F, -8.0F, -0.0F, 9.0F); + GlStateManager.rotate(-MathHelper.sin((float) (MathHelper.sqrt_float(equippedProgress) * Math.PI)) * 10.0F, 1.0F, -0.4F, -0.5F); + }else{ + this.transformFirstPersonItem(swingProgress - 0.3F, equippedProgress); + this.doBlockTransformations(); + } + } + + /** * @author SuperSkidder * @reason animation @@ -173,13 +267,12 @@ public void renderItemInFirstPerson(float partialTicks) { EventAnimation block = new EventAnimation(EventAnimation.Type.USE, f, f1); EventDispatcher.dispatchEvent(block); if (!block.isCanceled()) { - if (OldAnimations.blockHit.getValue()) { - GL11.glTranslated(OldAnimations.x.getValue().floatValue(), OldAnimations.y.getValue().floatValue(), OldAnimations.z.getValue().floatValue()); - this.transformFirstPersonItem(f, f1); + if (OldAnimations.oldBlock.getValue()) { + this.drawBlocking(f, f1); } else { this.transformFirstPersonItem(f, 0.0F); + this.doBlockTransformations(); } - this.doBlockTransformations(); } break; From bf18d937cb0f66c0d63f0e862f436df69777587d Mon Sep 17 00:00:00 2001 From: SuperSkidder Date: Fri, 2 May 2025 12:50:30 +0800 Subject: [PATCH 019/193] change: make damageindicator better --- .../features/impl/render/DamageIndicator.java | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/shared/java/top/fpsmaster/features/impl/render/DamageIndicator.java b/shared/java/top/fpsmaster/features/impl/render/DamageIndicator.java index effe6190..e189ab75 100644 --- a/shared/java/top/fpsmaster/features/impl/render/DamageIndicator.java +++ b/shared/java/top/fpsmaster/features/impl/render/DamageIndicator.java @@ -54,7 +54,7 @@ public void onRender(EventRender3D event) { public void doRender(Damage indicator) { Minecraft mc = Minecraft.getMinecraft(); DecimalFormat df = new DecimalFormat("0.00"); - String damage = df.format(indicator.damage); + String damage = df.format(-indicator.damage); GL11.glPushMatrix(); GL11.glEnable(3042); GL11.glDisable(2929); @@ -75,24 +75,23 @@ public void doRender(Damage indicator) { GlStateManager.disableDepth(); GlStateManager.disableBlend(); GlStateManager.disableLighting(); - Color color = new Color(50, 255, 50, (int) (255 - indicator.animation * 255)); + int alpha = (int) (255 - indicator.animation * 255); + alpha = Math.max(0, Math.min(255, alpha)); + + Color color = new Color(50, 255, 50, alpha); if (indicator.damage > 0) { - color = new Color(224, 41, 41, (int) (255 - indicator.animation * 255)); + color = new Color(224, 41, 41, alpha); } GL11.glEnable(3553); GL11.glDisable(3042); GL11.glDisable(2848); - GL11.glEnable(GL11.GL_ALPHA); GlStateManager.enableBlend(); ProviderManager.mcProvider.getFontRenderer().drawStringWithShadow(damage, -width + 5, indicator.animation * 10, color.getRGB()); GlStateManager.enableLighting(); - GlStateManager.enableBlend(); GlStateManager.enableDepth(); GlStateManager.disableBlend(); - GL11.glDisable(GL11.GL_ALPHA); GL11.glEnable(3553); GL11.glEnable(2929); - GlStateManager.disableBlend(); GL11.glDisable(3042); GL11.glColor4f(1.0f, 1.0f, 1.0f, 1.0f); GL11.glNormal3f(1.0f, 1.0f, 1.0f); From 77b98875e665153821d6faa5c501335b42ce7151 Mon Sep 17 00:00:00 2001 From: SuperSkidder Date: Fri, 2 May 2025 12:56:36 +0800 Subject: [PATCH 020/193] =?UTF-8?q?feat:=20=E6=B7=BB=E5=8A=A0=E5=AF=B9?= =?UTF-8?q?=E5=AE=89=E5=8D=93=E5=92=8Cmac=E7=9A=84=E9=80=82=E9=85=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../modules/impl/ColorSettingRender.java | 36 +++-- .../top/fpsmaster/utils/os/HttpRequest.kt | 152 ------------------ .../java/top/fpsmaster/utils/os/OSUtil.java | 28 ++++ .../fpsmaster/utils/render/Render2DUtils.java | 45 +++--- 4 files changed, 72 insertions(+), 189 deletions(-) delete mode 100644 shared/java/top/fpsmaster/utils/os/HttpRequest.kt create mode 100644 shared/java/top/fpsmaster/utils/os/OSUtil.java diff --git a/shared/java/top/fpsmaster/ui/click/modules/impl/ColorSettingRender.java b/shared/java/top/fpsmaster/ui/click/modules/impl/ColorSettingRender.java index a13b1d2b..269f04b7 100644 --- a/shared/java/top/fpsmaster/ui/click/modules/impl/ColorSettingRender.java +++ b/shared/java/top/fpsmaster/ui/click/modules/impl/ColorSettingRender.java @@ -9,6 +9,7 @@ import top.fpsmaster.ui.click.MainPanel; import top.fpsmaster.ui.click.modules.SettingRender; import top.fpsmaster.utils.math.animation.AnimationUtils; +import top.fpsmaster.utils.os.OSUtil; import top.fpsmaster.utils.render.shader.GradientUtils; import top.fpsmaster.utils.render.Render2DUtils; @@ -47,19 +48,20 @@ public void render( ); if (aHeight > 1) { - // Saturation and brightness adjustment - GradientUtils.applyGradient( - x + tW + 26, y + 15, 80f, aHeight, 1f, - Color.getHSBColor(customColor.hue, 0.0f, 0f), - Color.getHSBColor(customColor.hue, 0f, 1f), - Color.getHSBColor(customColor.hue, 1f, 0f), - Color.getHSBColor(customColor.hue, 1f, 1f), - Render2DUtils.getFixedScale(), - () -> Render2DUtils.drawRoundedRectImage( - x + tW + 26, y + 16, 80f, max(aHeight, 1f), 4, - new Color(255,255,255) - ) - ); + if (OSUtil.supportShader()) { + GradientUtils.applyGradient( + x + tW + 26, y + 15, 80f, aHeight, 1f, + Color.getHSBColor(customColor.hue, 0.0f, 0f), + Color.getHSBColor(customColor.hue, 0f, 1f), + Color.getHSBColor(customColor.hue, 1f, 0f), + Color.getHSBColor(customColor.hue, 1f, 1f), + Render2DUtils.getFixedScale(), + () -> Render2DUtils.drawRoundedRectImage( + x + tW + 26, y + 16, 80f, max(aHeight, 1f), 4, + new Color(255, 255, 255) + ) + ); + } float saturation = customColor.saturation; float brightness = customColor.brightness; @@ -110,9 +112,11 @@ public void render( new ResourceLocation("client/gui/settings/values/alpha.png"), x + tW + 122, y + 16, 10f, aHeight, -1 ); - GradientUtils.drawGradientVertical( - x + tW + 122, y + 16, 10f, aHeight, new Color(255, 255, 255), new Color(255, 255, 255, 0) - ); + if (OSUtil.supportShader()) { + GradientUtils.drawGradientVertical( + x + tW + 122, y + 16, 10f, aHeight, new Color(255, 255, 255), new Color(255, 255, 255, 0) + ); + } Render2DUtils.drawImage( new ResourceLocation("client/gui/settings/values/color.png"), diff --git a/shared/java/top/fpsmaster/utils/os/HttpRequest.kt b/shared/java/top/fpsmaster/utils/os/HttpRequest.kt deleted file mode 100644 index e6445e19..00000000 --- a/shared/java/top/fpsmaster/utils/os/HttpRequest.kt +++ /dev/null @@ -1,152 +0,0 @@ -package top.fpsmaster.utils.os - -import org.apache.http.client.HttpClient -import org.apache.http.client.methods.HttpGet -import org.apache.http.impl.client.HttpClients -import top.fpsmaster.modules.logger.Logger -import top.fpsmaster.modules.logger.Logger.info -import java.io.* -import java.net.HttpURLConnection -import java.net.URL -import java.nio.charset.StandardCharsets - -object HttpRequest { - @JvmStatic - operator fun get(u: String?): String { - return getWithCookie(u, "") - } - - @JvmStatic - fun getWithCookie(url: String?, cookie: String): String { - val u = url - val url = URL(u) - val connection = url.openConnection() as HttpURLConnection - connection.requestMethod = "GET" - connection.setRequestProperty( - "User-Agent", - "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36" - ) - val value = cookie.replace("\n","") - if (value.isNotBlank()) { - connection.setRequestProperty("Cookie", value) - } - connection.connectTimeout = 15000 - connection.readTimeout = 5000 - connection.connect() - val reader = BufferedReader(InputStreamReader(connection.inputStream, StandardCharsets.UTF_8)) - val builder = StringBuilder() - var line: String? - while (reader.readLine().also { line = it } != null) { - builder.append(line) - } - reader.close() - connection.disconnect() - return builder.toString() - } - - @JvmStatic - fun downloadFile(url: String, filepath: String) { - try { - val client: HttpClient = HttpClients.createDefault() - val httpget = HttpGet(url) - val response = client.execute(httpget) - val entity = response.entity - val `is` = entity.content - var progress: Long = 0 - val totalLen = entity.contentLength - val unit = totalLen / 100 - val file = File(filepath) - val fileout = FileOutputStream(file) - val buffer = ByteArray(10 * 1024) - var ch: Int - while (`is`.read(buffer).also { ch = it } != -1) { - fileout.write(buffer, 0, ch) - progress += ch.toLong() - } - if (progress % 10 == 0L) info("Downloaded " + progress / unit + "%") - `is`.close() - fileout.flush() - fileout.close() - } catch (e: Exception) { - Logger.error("Failed to download file: $url") - e.printStackTrace() - } - } - - @JvmStatic - fun sendPostRequest(targetUrl: String?, body: String, headers: MutableMap): Array { - val response = arrayOfNulls(2) - val url = URL(targetUrl) - val connection = url.openConnection() as HttpURLConnection - - // 设置请求方式为POST - connection.requestMethod = "POST" - - // 添加headers - for ((key, value) in headers) { - connection.setRequestProperty(key, value.trim()) - } - - // 添加body - connection.doOutput = true - val os = connection.outputStream - os.write(body.toByteArray()) - os.flush() - os.close() - - // 获取响应状态码 - response[0] = connection.responseCode.toString() - val content = StringBuffer() - - if (response[0] == "400" || response[0] == "403") { - // 获取响应内容 - val `in` = connection.errorStream.bufferedReader() - var inputLine: String? - while (`in`.readLine().also { inputLine = it } != null) { - content.append(inputLine) - } - `in`.close() - }else{ - // 获取响应内容 - val `in` = BufferedReader(InputStreamReader(connection.inputStream, StandardCharsets.UTF_8)) - var inputLine: String? - while (`in`.readLine().also { inputLine = it } != null) { - content.append(inputLine) - } - `in`.close() - } - connection.disconnect() - response[1] = content.toString() - return response -} - -fun downloadAsync(url: String?, filepath: String, callback: Runnable) { - Thread { - try { - val client: HttpClient = HttpClients.createDefault() - val httpget = HttpGet(url) - val response = client.execute(httpget) - val entity = response.entity - val `is` = entity.content - var progress: Long = 0 - val totalLen = entity.contentLength - val unit = totalLen / 100 - val file = File(filepath) - val fileout = FileOutputStream(file) - val buffer = ByteArray(10 * 1024) - var ch = 0 - while (`is`.read(buffer).also { ch = it } != -1) { - fileout.write(buffer, 0, ch) - progress += ch.toLong() - } - if (progress % 10 == 0L) info("Downloaded " + progress / unit + "%") - `is`.close() - fileout.flush() - fileout.close() - callback.run() - } catch (e: Exception) { - e.printStackTrace() - } - }.start() - } -} diff --git a/shared/java/top/fpsmaster/utils/os/OSUtil.java b/shared/java/top/fpsmaster/utils/os/OSUtil.java new file mode 100644 index 00000000..806e17e6 --- /dev/null +++ b/shared/java/top/fpsmaster/utils/os/OSUtil.java @@ -0,0 +1,28 @@ +package top.fpsmaster.utils.os; + +public class OSUtil { + + public static boolean isMac() { + return System.getProperty("os.name").toLowerCase().contains("mac"); + } + + public static boolean isUnix() { + return System.getProperty("os.name").toLowerCase().contains("nix"); + } + + public static boolean isSolaris() { + return System.getProperty("os.name").toLowerCase().contains("sunos"); + } + + public static boolean isLinux() { + return System.getProperty("os.name").toLowerCase().contains("linux"); + } + + public static boolean isWindows() { + return System.getProperty("os.name").toLowerCase().contains("windows"); + } + + public static boolean supportShader() { + return isWindows() || isLinux(); + } +} diff --git a/shared/java/top/fpsmaster/utils/render/Render2DUtils.java b/shared/java/top/fpsmaster/utils/render/Render2DUtils.java index 9af3d786..62bc2054 100644 --- a/shared/java/top/fpsmaster/utils/render/Render2DUtils.java +++ b/shared/java/top/fpsmaster/utils/render/Render2DUtils.java @@ -22,6 +22,7 @@ import top.fpsmaster.utils.awt.AWTUtils; import top.fpsmaster.utils.math.animation.AnimationUtils; import top.fpsmaster.utils.os.FileUtils; +import top.fpsmaster.utils.os.OSUtil; import top.fpsmaster.utils.render.shader.GLSLSandboxShader; import top.fpsmaster.utils.render.shader.KawaseBlur; import top.fpsmaster.utils.render.shader.RoundedUtil; @@ -272,29 +273,31 @@ public static void drawBackground(int guiWidth, int guiHeight, int mouseX, int m Render2DUtils.drawImage(textureLocation, 0f, 0f, guiWidth, guiHeight, -1); Render2DUtils.drawRect(0f, 0f, guiWidth, guiHeight, new Color(22, 22, 22, 50)); } else { - if (mc.currentScreen instanceof MainMenu) { - animation = (float) AnimationUtils.base(animation, 1.0f, 0.05f); + if (OSUtil.supportShader()) { + if (mc.currentScreen instanceof MainMenu) { + animation = (float) AnimationUtils.base(animation, 1.0f, 0.05f); + } else { + animation = (float) AnimationUtils.base(animation, 0.0f, 0.05f); + } + GlStateManager.disableCull(); + shader.useShader(guiWidth, guiHeight, mouseX, mouseY, (System.currentTimeMillis() - initTime) / 1000f, animation); + GL11.glBegin(GL11.GL_QUADS); + + GL11.glVertex2f(-1f, -1f); + GL11.glVertex2f(-1f, 1f); + GL11.glVertex2f(1f, 1f); + GL11.glVertex2f(1f, -1f); + + GL11.glEnd(); + + GL20.glUseProgram(0); + + GL11.glEnable(GL11.GL_TEXTURE_2D); + GL11.glEnable(GL11.GL_ALPHA_TEST); + Render2DUtils.drawRect(0f, 0f, guiWidth, guiHeight, new Color(26, 59, 109, 60)); } else { - animation = (float) AnimationUtils.base(animation, 0.0f, 0.05f); + ProviderManager.mainmenuProvider.renderSkybox(mouseX, mouseY, partialTicks, guiWidth, guiHeight, zLevel); } - GlStateManager.disableCull(); - shader.useShader(guiWidth, guiHeight, mouseX, mouseY, (System.currentTimeMillis() - initTime) / 1000f, animation); - GL11.glBegin(GL11.GL_QUADS); - - GL11.glVertex2f(-1f, -1f); - GL11.glVertex2f(-1f, 1f); - GL11.glVertex2f(1f, 1f); - GL11.glVertex2f(1f, -1f); - - GL11.glEnd(); - - GL20.glUseProgram(0); - - GL11.glEnable(GL11.GL_TEXTURE_2D); - GL11.glEnable(GL11.GL_ALPHA_TEST); - //ProviderManager.mainmenuProvider.renderSkybox(mouseX, mouseY, partialTicks, guiWidth, guiHeight, zLevel); - - Render2DUtils.drawRect(0f, 0f, guiWidth, guiHeight, new Color(26, 59, 109, 60)); } } } From df4a20303b70858679f7e18acaeeef5877ec7334 Mon Sep 17 00:00:00 2001 From: vlouboos Date: Fri, 2 May 2025 14:08:57 +0800 Subject: [PATCH 021/193] =?UTF-8?q?Fix=20=E5=BE=AE=E8=BD=AF=E7=99=BB?= =?UTF-8?q?=E5=BD=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ui/screens/account/GuiWaiting.java | 11 ++++----- .../thirdparty/microsoft/MicrosoftLogin.java | 24 +++++++++---------- 2 files changed, 15 insertions(+), 20 deletions(-) diff --git a/shared/java/top/fpsmaster/ui/screens/account/GuiWaiting.java b/shared/java/top/fpsmaster/ui/screens/account/GuiWaiting.java index 7c296702..8f1e22bd 100644 --- a/shared/java/top/fpsmaster/ui/screens/account/GuiWaiting.java +++ b/shared/java/top/fpsmaster/ui/screens/account/GuiWaiting.java @@ -12,8 +12,7 @@ import java.io.IOException; public class GuiWaiting extends GuiScreen { - - private boolean isLogged = false; + public static boolean loggedIn = false; @Override public void initGui() { @@ -49,9 +48,9 @@ public void drawScreen(int mouseX, int mouseY, float partialTicks) { FPSMaster.theme.getPrimary().getRGB() ); - // Check if logged in and switch to main menu - if (isLogged) { - isLogged = false; + // Check if logged in and switch to the main menu + if (loggedIn) { + loggedIn = false; Minecraft.getMinecraft().displayGuiScreen(new GuiMainMenu()); } } @@ -63,6 +62,4 @@ public void keyTyped(char typedChar, int keyCode) throws IOException { Minecraft.getMinecraft().displayGuiScreen(new GuiMainMenu()); } } - - public static boolean logged = false; } diff --git a/shared/java/top/fpsmaster/utils/thirdparty/microsoft/MicrosoftLogin.java b/shared/java/top/fpsmaster/utils/thirdparty/microsoft/MicrosoftLogin.java index f1967fa6..2b6aecd1 100644 --- a/shared/java/top/fpsmaster/utils/thirdparty/microsoft/MicrosoftLogin.java +++ b/shared/java/top/fpsmaster/utils/thirdparty/microsoft/MicrosoftLogin.java @@ -2,11 +2,9 @@ import com.google.gson.GsonBuilder; import com.google.gson.JsonObject; -import com.sun.net.httpserver.HttpExchange; import com.sun.net.httpserver.HttpServer; import net.minecraft.util.Session; import org.apache.http.NameValuePair; -import org.apache.http.client.ClientProtocolException; import org.apache.http.client.config.RequestConfig; import org.apache.http.client.entity.UrlEncodedFormEntity; import org.apache.http.client.methods.CloseableHttpResponse; @@ -56,7 +54,7 @@ public static void start() { map.put("grant_type", "authorization_code"); map.put("redirect_uri", "http://127.0.0.1:17342"); - String oauthResponse = postMap("https://login.live.com/oauth20_token.srf", map); + String oauthResponse = postMap(map); String accessToken = gsonBuilder.create().fromJson(oauthResponse, JsonObject.class).get("access_token").getAsString(); Map map2 = new HashMap<>(); @@ -74,7 +72,7 @@ public static void start() { String xblToken = xblJson.get("Token").getAsString(); String xstsResponse = authorizeWithXsts(gsonBuilder, xblToken); - String xstsToken = new JsonObject().getAsJsonObject("Token").getAsString(); + String xstsToken = gsonBuilder.create().fromJson(xstsResponse, JsonObject.class).get("Token").getAsString(); String xstsUserHash = getXstsUserHash(xstsResponse); JsonObject properties = new JsonObject(); @@ -86,13 +84,13 @@ public static void start() { // Get profile Map profileMap = new HashMap<>(); profileMap.put("Authorization", "Bearer " + accessToken); - String profile = get("https://api.minecraftservices.com/minecraft/profile", profileMap); + String profile = getProfile(profileMap); JsonObject profileJson = gsonBuilder.create().fromJson(profile, JsonObject.class); String uuid = profileJson.get("id").getAsString(); String name = profileJson.get("name").getAsString(); ProviderManager.mcProvider.setSession(new Session(name, uuid, accessToken, "mojang")); - GuiWaiting.logged = true; + GuiWaiting.loggedIn = true; }); httpServer.setExecutor(null); @@ -111,7 +109,7 @@ public static boolean login() { map.put("redirect_uri", "http://127.0.0.1:17342"); map.put("scope", "XboxLive.signin%20XboxLive.offline_access"); - String url = buildUrl("https://login.live.com/oauth20_authorize.srf", map); + String url = buildOAuthUrl(map); start(); Desktop.getDesktop().browse(URI.create(url)); } catch (IOException e) { @@ -120,9 +118,9 @@ public static boolean login() { return flag.get(); } - private static String postMap(String url, Map param) { + private static String postMap(Map param) { try (CloseableHttpClient httpClient = HttpClients.createDefault()) { - HttpPost httpPost = new HttpPost(url); + HttpPost httpPost = new HttpPost("https://login.live.com/oauth20_token.srf"); if (param != null) { List paramList = new ArrayList<>(); for (Map.Entry entry : param.entrySet()) { @@ -140,9 +138,9 @@ private static String postMap(String url, Map param) { return ""; } - private static String get(String url, Map headers) { + private static String getProfile(Map headers) { try (CloseableHttpClient httpClient = HttpClients.createDefault()) { - HttpGet httpGet = new HttpGet(url); + HttpGet httpGet = new HttpGet("https://api.minecraftservices.com/minecraft/profile"); RequestConfig requestConfig = RequestConfig.custom() .setConnectTimeout(35000) .setConnectionRequestTimeout(35000) @@ -182,8 +180,8 @@ private static String postJson(String url, JsonObject jsonObject) { return ""; } - private static String buildUrl(String url, Map map) { - StringBuilder sb = new StringBuilder(url); + private static String buildOAuthUrl(Map map) { + StringBuilder sb = new StringBuilder("https://login.live.com/oauth20_authorize.srf"); if (!map.isEmpty()) { sb.append("?"); for (Map.Entry entry : map.entrySet()) { From b8c7d7b7266dfdb209350053b42c9eafc93e9965 Mon Sep 17 00:00:00 2001 From: vlouboos Date: Fri, 2 May 2025 14:48:52 +0800 Subject: [PATCH 022/193] Fix blend bugs & mapping bugs --- .../java/top/fpsmaster/features/manager/Module.java | 7 ++++--- .../ui/custom/impl/CoordsDisplayComponent.java | 6 +++--- .../top/fpsmaster/utils/render/Render2DUtils.java | 12 ++++-------- .../top/fpsmaster/forge/mixin/MixinMinecraft.java | 2 +- .../top/fpsmaster/forge/mixin/MixinSplashScreen.java | 2 +- 5 files changed, 13 insertions(+), 16 deletions(-) diff --git a/shared/java/top/fpsmaster/features/manager/Module.java b/shared/java/top/fpsmaster/features/manager/Module.java index 769e6ffb..5c768908 100644 --- a/shared/java/top/fpsmaster/features/manager/Module.java +++ b/shared/java/top/fpsmaster/features/manager/Module.java @@ -62,9 +62,9 @@ public void toggle() { } public void set(boolean state) { - isEnabled = state; try { - if (state) { + if (state && !isEnabled) { + isEnabled = true; onEnable(); if (Minecraft.getMinecraft() != null && ProviderManager.mcProvider.getPlayer() != null) { NotificationManager.addNotification( @@ -76,7 +76,8 @@ public void set(boolean state) { 2f ); } - } else { + } else if (!state && isEnabled){ + isEnabled = false; onDisable(); if (Minecraft.getMinecraft() != null && ProviderManager.mcProvider.getPlayer() != null) { NotificationManager.addNotification( diff --git a/shared/java/top/fpsmaster/ui/custom/impl/CoordsDisplayComponent.java b/shared/java/top/fpsmaster/ui/custom/impl/CoordsDisplayComponent.java index 23184bc9..5f7fe593 100644 --- a/shared/java/top/fpsmaster/ui/custom/impl/CoordsDisplayComponent.java +++ b/shared/java/top/fpsmaster/ui/custom/impl/CoordsDisplayComponent.java @@ -18,7 +18,7 @@ public CoordsDisplayComponent() { @Override public void draw(float x, float y) { super.draw(x, y); - String s = String.format("X:%d Y:%d Z:%d", + String s = String.format("X:%d Y:%d Z:%d", (int) ProviderManager.mcProvider.getPlayer().posX, (int) ProviderManager.mcProvider.getPlayer().posY, (int) ProviderManager.mcProvider.getPlayer().posZ); @@ -41,8 +41,8 @@ public void draw(float x, float y) { } private @NotNull String getString() { - int restHeight = (int) ((CoordsDisplay) mod).limitDisplayY.value - (int) ProviderManager.mcProvider.getPlayer().posY; - String yStr = ""; + int restHeight = ((CoordsDisplay) mod).limitDisplayY.value.intValue() - (int) ProviderManager.mcProvider.getPlayer().posY; + String yStr; // color if (restHeight < 5) { diff --git a/shared/java/top/fpsmaster/utils/render/Render2DUtils.java b/shared/java/top/fpsmaster/utils/render/Render2DUtils.java index 62bc2054..2f87cbba 100644 --- a/shared/java/top/fpsmaster/utils/render/Render2DUtils.java +++ b/shared/java/top/fpsmaster/utils/render/Render2DUtils.java @@ -122,10 +122,8 @@ public static int limit(double i) { } public static void drawRect(float x, float y, float width, float height, int color) { - GlStateManager.disableBlend(); - - glEnable(GL_BLEND); - glDisable(GL_TEXTURE_2D); + GlStateManager.enableBlend(); + GlStateManager.disableTexture2D(); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glEnable(GL_LINE_SMOOTH); glColor(color); @@ -135,11 +133,9 @@ public static void drawRect(float x, float y, float width, float height, int col GL11.glVertex2d(x + width, y + height); GL11.glVertex2d(x + width, y); GL11.glEnd(); - glEnable(GL_TEXTURE_2D); - glDisable(GL_BLEND); glDisable(GL_LINE_SMOOTH); - GlStateManager.enableBlend(); - + GlStateManager.enableTexture2D(); + GlStateManager.disableBlend(); } public static Color intToColor(Integer c) { diff --git a/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinMinecraft.java b/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinMinecraft.java index 7972f9e0..2cb0114a 100644 --- a/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinMinecraft.java +++ b/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinMinecraft.java @@ -220,7 +220,7 @@ public void cpsr(CallbackInfo ci) { EventDispatcher.dispatchEvent(new EventMouseClick(1)); } - @Inject(method = "dispatchKeypresses", at = @At(value = "INVOKE", target = "Lorg/lwjgl/input/Keyboard;getEventKey()I", shift = At.Shift.AFTER)) + @Inject(method = "dispatchKeypresses", at = @At(value = "INVOKE", target = "Lorg/lwjgl/input/Keyboard;getEventKey()I", shift = At.Shift.AFTER), remap = false) public void keyEvent(CallbackInfo ci) { EventKey key = new EventKey(Keyboard.getEventKey() == 0 ? Keyboard.getEventCharacter() + 256 : Keyboard.getEventKey()); EventDispatcher.dispatchEvent(key); diff --git a/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinSplashScreen.java b/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinSplashScreen.java index 4a0a37e5..801d80b9 100644 --- a/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinSplashScreen.java +++ b/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinSplashScreen.java @@ -14,7 +14,7 @@ import java.awt.*; -@Mixin(SplashProgress.class) +@Mixin(value = SplashProgress.class, remap = false) @SuppressWarnings("all") public class MixinSplashScreen { From f712763bdffd5df4210df84e4710f7afbca1292a Mon Sep 17 00:00:00 2001 From: SuperSkidder Date: Fri, 2 May 2025 15:15:38 +0800 Subject: [PATCH 023/193] fix: linux support --- shared/java/top/fpsmaster/ui/mc/GuiMultiplayer.java | 6 ++---- shared/java/top/fpsmaster/utils/os/OSUtil.java | 4 +++- shared/java/top/fpsmaster/utils/render/Render2DUtils.java | 4 ++-- .../fpsmaster/utils/render/shader/GLSLSandboxShader.java | 2 +- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/shared/java/top/fpsmaster/ui/mc/GuiMultiplayer.java b/shared/java/top/fpsmaster/ui/mc/GuiMultiplayer.java index c71e7483..cd5d82b8 100644 --- a/shared/java/top/fpsmaster/ui/mc/GuiMultiplayer.java +++ b/shared/java/top/fpsmaster/ui/mc/GuiMultiplayer.java @@ -260,19 +260,17 @@ public void onClick(int mouseX, int mouseY, int mouseButton) { } int y = 80; - int index = 0; for (ServerListEntry server : serverListDisplay) { if (server.getServerData() == null) { return; } if (Render2DUtils.isHovered((width - 340) / 2f, y, 340, 54, mouseX, mouseY)) { - if (selectedServer != servers.get(index)) { - selectedServer = servers.get(index); + if (selectedServer != server.getServerData()) { + selectedServer = server.getServerData(); } else { selectedServer = null; } } - index++; y += 54; } diff --git a/shared/java/top/fpsmaster/utils/os/OSUtil.java b/shared/java/top/fpsmaster/utils/os/OSUtil.java index 806e17e6..f5cfe0ba 100644 --- a/shared/java/top/fpsmaster/utils/os/OSUtil.java +++ b/shared/java/top/fpsmaster/utils/os/OSUtil.java @@ -2,6 +2,8 @@ public class OSUtil { + public static boolean supportShader; + public static boolean isMac() { return System.getProperty("os.name").toLowerCase().contains("mac"); } @@ -23,6 +25,6 @@ public static boolean isWindows() { } public static boolean supportShader() { - return isWindows() || isLinux(); + return supportShader; } } diff --git a/shared/java/top/fpsmaster/utils/render/Render2DUtils.java b/shared/java/top/fpsmaster/utils/render/Render2DUtils.java index 2f87cbba..34e726fd 100644 --- a/shared/java/top/fpsmaster/utils/render/Render2DUtils.java +++ b/shared/java/top/fpsmaster/utils/render/Render2DUtils.java @@ -251,8 +251,8 @@ public static void drawBlurArea(int x, int y, int width, int height, int radius, static { try { shader = new GLSLSandboxShader("bg1.frag"); - } catch (IOException e) { - throw new RuntimeException(e); + } catch (Exception e) { + OSUtil.supportShader = false; } } diff --git a/shared/java/top/fpsmaster/utils/render/shader/GLSLSandboxShader.java b/shared/java/top/fpsmaster/utils/render/shader/GLSLSandboxShader.java index 566e1749..67828093 100644 --- a/shared/java/top/fpsmaster/utils/render/shader/GLSLSandboxShader.java +++ b/shared/java/top/fpsmaster/utils/render/shader/GLSLSandboxShader.java @@ -14,7 +14,7 @@ public class GLSLSandboxShader { private final int resolutionUniform; private final int animationUniform; - public GLSLSandboxShader(String fragmentShaderLocation) throws IOException { + public GLSLSandboxShader(String fragmentShaderLocation) throws Exception { int program = glCreateProgram(); glAttachShader(program, createShader(GLSLSandboxShader.class.getResourceAsStream("/assets/minecraft/client/shaders/passthrough.glsl"), GL_VERTEX_SHADER)); From bafaf0783728cfe5feb469272f7d767611785983 Mon Sep 17 00:00:00 2001 From: SuperSkidder Date: Fri, 2 May 2025 15:23:10 +0800 Subject: [PATCH 024/193] fix: multiplayer crash remove unused feature update language --- .../java/top/fpsmaster/features/impl/utility/LevelTag.java | 5 +---- shared/java/top/fpsmaster/ui/mc/GuiMultiplayer.java | 4 +--- shared/resources/assets/minecraft/client/lang/zh_cn.lang | 4 +++- 3 files changed, 5 insertions(+), 8 deletions(-) diff --git a/shared/java/top/fpsmaster/features/impl/utility/LevelTag.java b/shared/java/top/fpsmaster/features/impl/utility/LevelTag.java index 244a3595..9c75d5e8 100644 --- a/shared/java/top/fpsmaster/features/impl/utility/LevelTag.java +++ b/shared/java/top/fpsmaster/features/impl/utility/LevelTag.java @@ -1,6 +1,5 @@ package top.fpsmaster.features.impl.utility; -import net.minecraft.client.Minecraft; import net.minecraft.client.gui.FontRenderer; import net.minecraft.client.renderer.GlStateManager; import net.minecraft.client.renderer.Tessellator; @@ -11,7 +10,6 @@ import top.fpsmaster.features.manager.Category; import top.fpsmaster.features.manager.Module; import top.fpsmaster.features.settings.impl.BooleanSetting; -import top.fpsmaster.features.settings.impl.ModeSetting; import top.fpsmaster.interfaces.ProviderManager; import static top.fpsmaster.utils.Utility.mc; @@ -21,11 +19,10 @@ public class LevelTag extends Module { public static boolean using = false; public static final BooleanSetting showSelf = new BooleanSetting("ShowSelf", true); public static final BooleanSetting health = new BooleanSetting("Health", true); - public static final ModeSetting levelMode = new ModeSetting("RankMode", 0, "None", "Bedwars", "Bedwars-xp", "Skywars", "Kit"); public LevelTag() { super("Nametags", Category.Utility); - addSettings(showSelf, health, levelMode); + addSettings(showSelf, health); } public static void renderHealth(Entity entityIn, String str, double x, double y, double z, int maxDistance) { diff --git a/shared/java/top/fpsmaster/ui/mc/GuiMultiplayer.java b/shared/java/top/fpsmaster/ui/mc/GuiMultiplayer.java index cd5d82b8..644efdfa 100644 --- a/shared/java/top/fpsmaster/ui/mc/GuiMultiplayer.java +++ b/shared/java/top/fpsmaster/ui/mc/GuiMultiplayer.java @@ -182,7 +182,6 @@ public void render(int mouseX, int mouseY, float partialTicks) { scrollContainer.draw((width - 400) / 2f, 60, 396, height - 120, mouseX, mouseY, () -> { float y = 70 + scrollContainer.getScroll(); Render2DUtils.drawOptimizedRoundedRect((width - 400) / 2f, y - 10, 400, height - y, 5, new Color(0, 0, 0, 100).getRGB()); - int index = 0; for (ServerListEntry server : serverListDisplay) { if (server.getServerData() == null) { return; @@ -191,11 +190,10 @@ public void render(int mouseX, int mouseY, float partialTicks) { if (Render2DUtils.isHovered((width - 340) / 2f, y, 340, 54, mouseX, mouseY)) { Render2DUtils.drawOptimizedRoundedRect((width - 340) / 2f, y, 340, 54, new Color(0, 0, 0, 50)); } - if (selectedServer != null && servers.indexOf(selectedServer) == index) { + if (selectedServer != null && selectedServer == server.getServerData()) { Render2DUtils.drawOptimizedRoundedRect((width - 340) / 2f, y, 340, 54, new Color(255, 255, 255, 50)); } server.drawEntry(0, (width - 340) / 2, (int) y, 340, 54, mouseX, mouseY, false); - index++; y += 58; } scrollContainer.setHeight(y - 50 - scrollContainer.getScroll()); diff --git a/shared/resources/assets/minecraft/client/lang/zh_cn.lang b/shared/resources/assets/minecraft/client/lang/zh_cn.lang index fd416ffa..8c11c66f 100644 --- a/shared/resources/assets/minecraft/client/lang/zh_cn.lang +++ b/shared/resources/assets/minecraft/client/lang/zh_cn.lang @@ -178,7 +178,7 @@ performance.blur=界面高斯模糊 performance.fontoptimize=字体优化 performance.staticparticlecolor=静态粒子颜色 performance.limitchunks=限制区块加载 -performance..chunkupdatelimit=区块更新限制 +performance.chunkupdatelimit=区块更新限制 fullbright=保持亮度 @@ -223,6 +223,7 @@ musicdisplay.visual=音频可视化颜色 musicdisplay.amplitude=可视化幅度 musicdisplay.roundradius=圆角半径 musicdisplay.round=圆角 +musicdisplay.betterfont=更好的字体 musicdisplay.background=背景 oldanimations=旧动画 @@ -319,6 +320,7 @@ timechanger.time=时间 tnttimer=TNT时间显示 tnttimer.desc=显示TNT爆炸的时间 +tnttimer.duration=TNT爆炸时间 hitboxes=碰撞箱 hitboxes.desc=显示碰撞箱 From 8d6218d2bd9b02add996053d78565da3d4aa5191 Mon Sep 17 00:00:00 2001 From: vlouboos Date: Fri, 2 May 2025 23:25:52 +0800 Subject: [PATCH 025/193] =?UTF-8?q?=E9=87=8D=E5=86=99=E5=90=AF=E5=8A=A8?= =?UTF-8?q?=E5=8A=A8=E7=94=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../fpsmaster/features/impl/utility/LevelTag.java | 2 +- .../top/fpsmaster/ui/screens/mainmenu/MainMenu.java | 13 +++++++++---- .../fpsmaster/utils/math/animation/Animation.java | 2 ++ .../utils/math/animation/AnimationUtils.java | 5 +++++ .../top/fpsmaster/utils/math/animation/Type.java | 3 ++- 5 files changed, 19 insertions(+), 6 deletions(-) diff --git a/shared/java/top/fpsmaster/features/impl/utility/LevelTag.java b/shared/java/top/fpsmaster/features/impl/utility/LevelTag.java index 9c75d5e8..eb9441c9 100644 --- a/shared/java/top/fpsmaster/features/impl/utility/LevelTag.java +++ b/shared/java/top/fpsmaster/features/impl/utility/LevelTag.java @@ -35,7 +35,7 @@ public static void renderHealth(Entity entityIn, String str, double x, double y, GL11.glNormal3f(0.0F, 1.0F, 0.0F); GlStateManager.rotate(-mc.getRenderManager().playerViewY, 0.0F, 1.0F, 0.0F); if (mc.gameSettings.thirdPersonView == 2) - GlStateManager.rotate(-mc.getRenderManager().playerViewX, 1.0F, 0.0F, 0.0F); + GlStateManager.rotate(mc.getRenderManager().playerViewX, 1.0F, 0.0F, 0.0F); else if (mc.gameSettings.thirdPersonView == 1) GlStateManager.rotate(mc.getRenderManager().playerViewX, 1.0F, 0.0F, 0.0F); diff --git a/shared/java/top/fpsmaster/ui/screens/mainmenu/MainMenu.java b/shared/java/top/fpsmaster/ui/screens/mainmenu/MainMenu.java index eb68a2c7..ca6fed02 100644 --- a/shared/java/top/fpsmaster/ui/screens/mainmenu/MainMenu.java +++ b/shared/java/top/fpsmaster/ui/screens/mainmenu/MainMenu.java @@ -35,7 +35,8 @@ public class MainMenu extends ScaledGuiScreen { private String welcome = "Failed to get version update"; private boolean needUpdate = false; - private static Animation startAnimation = new Animation(); + private static final Animation startAnimation = new Animation(); + private static final Animation backgroundAnimation = new Animation(); public MainMenu() { @@ -64,8 +65,12 @@ public void initGui() { @Override public void render(int mouseX, int mouseY, float partialTicks) { Render2DUtils.drawBackground((int) guiWidth, (int) guiHeight, mouseX, mouseY, partialTicks, (int) zLevel); - startAnimation.start(0, 1.5, 2f, Type.EASE_IN_OUT_QUAD); + startAnimation.start(0, 1.1, 1.5f, Type.EASE_OUT_QUINT); startAnimation.update(); + if (startAnimation.value >= 0.5) { + backgroundAnimation.start(0, 1.5, 2.0f, Type.LINEAR); + backgroundAnimation.update(); + } // Display user info and avatar @@ -114,8 +119,8 @@ public void render(int mouseX, int mouseY, float partialTicks) { Render2DUtils.drawRect(0f, 0f, 0f, 0f, -1); FPSMaster.fontManager.s16.drawString(FPSMaster.COPYRIGHT, 4, guiHeight - 14, Color.WHITE.getRGB()); FPSMaster.fontManager.s16.drawString(FPSMaster.CLIENT_NAME + " Client " + FPSMaster.CLIENT_VERSION + " (Minecraft " + FPSMaster.EDITION + ")", 4, guiHeight - 28, Color.WHITE.getRGB()); - Render2DUtils.drawRect(0, 0, width, height, new Color(20, 20, 20, (int) (255 - 255 * Math.max(0, (float) startAnimation.value - 0.5f)))); - Render2DUtils.drawImage(new ResourceLocation("client/gui/logo.png"), guiWidth / 2f - 153 / 4f, guiHeight / 2f - 30 - 70 * ((float)Math.min(startAnimation.value, 1)), 153 / 2f, 67f, -1); + Render2DUtils.drawRect(0, 0, width, height, new Color(20, 20, 20, (int) (255 - 255 * Math.max(0, (float) backgroundAnimation.value - 0.5f)))); + Render2DUtils.drawImage(new ResourceLocation("client/gui/logo.png"), guiWidth / 2f - 153 / 4f, guiHeight / 2f - 30 - 70 * ((float) Math.min(startAnimation.value, 1)), 153 / 2f, 67f, -1); } diff --git a/shared/java/top/fpsmaster/utils/math/animation/Animation.java b/shared/java/top/fpsmaster/utils/math/animation/Animation.java index 20dd7971..41aef620 100644 --- a/shared/java/top/fpsmaster/utils/math/animation/Animation.java +++ b/shared/java/top/fpsmaster/utils/math/animation/Animation.java @@ -56,6 +56,8 @@ public void update() { case EASE_OUT_BACK: result = AnimationUtils.easeOutBack(elapsedTime, start, end - start, (double) duration); break; + case EASE_OUT_QUINT: + result = AnimationUtils.easeOutQuint(elapsedTime, start, end - start, (double) duration); default: break; } diff --git a/shared/java/top/fpsmaster/utils/math/animation/AnimationUtils.java b/shared/java/top/fpsmaster/utils/math/animation/AnimationUtils.java index 56f9fe4b..9298a52e 100644 --- a/shared/java/top/fpsmaster/utils/math/animation/AnimationUtils.java +++ b/shared/java/top/fpsmaster/utils/math/animation/AnimationUtils.java @@ -115,4 +115,9 @@ public static double easeOutBack(double t, double b, double c, double d) { t = t / d - 1; return c * (t * t * ((s + 1) * t + s) + 1) + b; } + + public static double easeOutQuint(long elapsedTime, double start, double rest, double duration) { + double percent = 1.0 - Math.pow(1.0 - elapsedTime / duration, 5); + return start + (rest * percent); + } } diff --git a/shared/java/top/fpsmaster/utils/math/animation/Type.java b/shared/java/top/fpsmaster/utils/math/animation/Type.java index 1995f7e0..39cac261 100644 --- a/shared/java/top/fpsmaster/utils/math/animation/Type.java +++ b/shared/java/top/fpsmaster/utils/math/animation/Type.java @@ -9,5 +9,6 @@ public enum Type { EASE_OUT_ELASTIC, EASE_IN_OUT_ELASTIC, EASE_IN_BACK, - EASE_OUT_BACK + EASE_OUT_BACK, + EASE_OUT_QUINT } From 616f070400019296a14df3ae65ff00cf5fba576c Mon Sep 17 00:00:00 2001 From: SuperSkidder Date: Sat, 3 May 2025 02:28:36 +0800 Subject: [PATCH 026/193] feat: more lua api --- .../top/fpsmaster/modules/lua/LuaManager.java | 34 +++++++++++++++++++ .../top/fpsmaster/modules/lua/LuaModule.java | 2 +- 2 files changed, 35 insertions(+), 1 deletion(-) diff --git a/shared/java/top/fpsmaster/modules/lua/LuaManager.java b/shared/java/top/fpsmaster/modules/lua/LuaManager.java index cc155dd1..2d5a970d 100644 --- a/shared/java/top/fpsmaster/modules/lua/LuaManager.java +++ b/shared/java/top/fpsmaster/modules/lua/LuaManager.java @@ -1,10 +1,13 @@ package top.fpsmaster.modules.lua; +import net.minecraft.client.Minecraft; +import net.minecraft.util.BlockPos; import party.iroiro.luajava.Lua; import party.iroiro.luajava.lua53.Lua53; import party.iroiro.luajava.value.LuaValue; import top.fpsmaster.FPSMaster; import top.fpsmaster.features.manager.Module; +import top.fpsmaster.interfaces.ProviderManager; import top.fpsmaster.modules.dev.DevMode; import top.fpsmaster.modules.i18n.Language; import top.fpsmaster.modules.lua.parser.LuaParser; @@ -12,6 +15,7 @@ import top.fpsmaster.utils.Utility; import top.fpsmaster.utils.os.FileUtils; import top.fpsmaster.utils.render.Render2DUtils; +import top.fpsmaster.wrapper.blockpos.WrapperBlockPos; import java.awt.*; import java.io.File; @@ -86,6 +90,35 @@ public static LuaScript loadLua(RawLua rawLua) { }); lua.setGlobal("drawRect"); + + lua.push(L -> { + boolean sneak = L.toBoolean(1); + ProviderManager.gameSettings.setKeyPress(Utility.mc.gameSettings.keyBindSneak, sneak); + return 0; // 返回值数量 + }); + lua.setGlobal("sneak"); + + lua.push(L -> { + double posX = ProviderManager.mcProvider.getPlayer().posX; + double posY = ProviderManager.mcProvider.getPlayer().posY; + double posZ = ProviderManager.mcProvider.getPlayer().posZ; + lua.push(posX); + lua.push(posY); + lua.push(posZ); + return 3; + }); + lua.setGlobal("getPlayerPosition"); + + lua.push(L -> { + double x = L.toNumber(1); + double y = L.toNumber(2); + double z = L.toNumber(3); + + lua.push(Minecraft.getMinecraft().theWorld.getBlockState(new BlockPos(x, y, z)).getBlock().getUnlocalizedName()); + return 1; // 返回值数量 + }); + lua.setGlobal("getBlockNameByPos"); + // 获取颜色 lua.push(L -> { int r = (int) L.toInteger(1); @@ -121,6 +154,7 @@ public static LuaScript loadLua(RawLua rawLua) { // Module object lua.pushJavaObject(FPSMaster.moduleManager); lua.setGlobal("moduleManager"); + lua.pushJavaClass(LuaModule.class); lua.setGlobal("module"); diff --git a/shared/java/top/fpsmaster/modules/lua/LuaModule.java b/shared/java/top/fpsmaster/modules/lua/LuaModule.java index 86b00454..f7d5349f 100644 --- a/shared/java/top/fpsmaster/modules/lua/LuaModule.java +++ b/shared/java/top/fpsmaster/modules/lua/LuaModule.java @@ -48,7 +48,7 @@ public void callEvent(String name, Object... args) { v.call(args); }); } catch (Exception e) { - System.out.println("error when calling " + name); + System.out.println("error when calling " + name + " " + e.getMessage()); } } From f490a29e091edcd20a360962b6697c9fd6f98f69 Mon Sep 17 00:00:00 2001 From: SuperSkidder Date: Sat, 3 May 2025 08:34:29 +0800 Subject: [PATCH 027/193] =?UTF-8?q?feat:=20=E5=8F=8C=E5=87=BB=E5=8A=A0?= =?UTF-8?q?=E5=85=A5=E6=9C=8D=E5=8A=A1=E5=99=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- shared/java/top/fpsmaster/ui/mc/GuiMultiplayer.java | 11 ++++++++++- shared/java/top/fpsmaster/utils/math/MathTimer.java | 2 +- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/shared/java/top/fpsmaster/ui/mc/GuiMultiplayer.java b/shared/java/top/fpsmaster/ui/mc/GuiMultiplayer.java index 644efdfa..e3176527 100644 --- a/shared/java/top/fpsmaster/ui/mc/GuiMultiplayer.java +++ b/shared/java/top/fpsmaster/ui/mc/GuiMultiplayer.java @@ -25,6 +25,7 @@ import top.fpsmaster.ui.click.component.ScrollContainer; import top.fpsmaster.ui.common.GuiButton; import top.fpsmaster.ui.screens.mainmenu.MainMenu; +import top.fpsmaster.utils.math.MathTimer; import top.fpsmaster.utils.os.HttpRequest; import top.fpsmaster.utils.render.Render2DUtils; import top.fpsmaster.utils.render.ScaledGuiScreen; @@ -49,6 +50,8 @@ public class GuiMultiplayer extends ScaledGuiScreen { String action = ""; + MathTimer timer = new MathTimer(); + GuiButton join = new GuiButton("加入服务器", () -> { if (selectedServer == null) return; @@ -190,6 +193,7 @@ public void render(int mouseX, int mouseY, float partialTicks) { if (Render2DUtils.isHovered((width - 340) / 2f, y, 340, 54, mouseX, mouseY)) { Render2DUtils.drawOptimizedRoundedRect((width - 340) / 2f, y, 340, 54, new Color(0, 0, 0, 50)); } + if (selectedServer != null && selectedServer == server.getServerData()) { Render2DUtils.drawOptimizedRoundedRect((width - 340) / 2f, y, 340, 54, new Color(255, 255, 255, 50)); } @@ -265,8 +269,13 @@ public void onClick(int mouseX, int mouseY, int mouseButton) { if (Render2DUtils.isHovered((width - 340) / 2f, y, 340, 54, mouseX, mouseY)) { if (selectedServer != server.getServerData()) { selectedServer = server.getServerData(); + timer.reset(); } else { - selectedServer = null; + if (timer.delay(200)) { + selectedServer = null; + }else{ + FMLClientHandler.instance().connectToServer(this, selectedServer); + } } } y += 54; diff --git a/shared/java/top/fpsmaster/utils/math/MathTimer.java b/shared/java/top/fpsmaster/utils/math/MathTimer.java index 39d9e8a2..92e9bf18 100644 --- a/shared/java/top/fpsmaster/utils/math/MathTimer.java +++ b/shared/java/top/fpsmaster/utils/math/MathTimer.java @@ -15,7 +15,7 @@ public boolean delay(long delay) { return false; } - private void reset() { + public void reset() { start = System.currentTimeMillis(); } } From 501024f7b131693498dd4cad84073ad568433f1b Mon Sep 17 00:00:00 2001 From: vlouboos Date: Sat, 3 May 2025 14:53:00 +0800 Subject: [PATCH 028/193] Fixed Minimized Bobbing --- .../java/top/fpsmaster/ui/screens/mainmenu/MainMenu.java | 8 ++------ .../top/fpsmaster/forge/mixin/MixinEntityRenderer.java | 8 ++++---- 2 files changed, 6 insertions(+), 10 deletions(-) diff --git a/shared/java/top/fpsmaster/ui/screens/mainmenu/MainMenu.java b/shared/java/top/fpsmaster/ui/screens/mainmenu/MainMenu.java index ca6fed02..197fefaf 100644 --- a/shared/java/top/fpsmaster/ui/screens/mainmenu/MainMenu.java +++ b/shared/java/top/fpsmaster/ui/screens/mainmenu/MainMenu.java @@ -2,7 +2,6 @@ import net.minecraft.client.Minecraft; import net.minecraft.client.gui.GuiOptions; -import net.minecraft.client.renderer.GlStateManager; import net.minecraft.util.ResourceLocation; import org.lwjgl.input.Mouse; import top.fpsmaster.FPSMaster; @@ -11,9 +10,7 @@ import top.fpsmaster.ui.mc.GuiMultiplayer; import top.fpsmaster.ui.screens.account.GuiWaiting; import top.fpsmaster.ui.screens.oobe.GuiLogin; -import top.fpsmaster.utils.math.MathUtils; import top.fpsmaster.utils.math.animation.Animation; -import top.fpsmaster.utils.math.animation.AnimationUtils; import top.fpsmaster.utils.math.animation.Type; import top.fpsmaster.utils.render.Render2DUtils; import top.fpsmaster.utils.render.ScaledGuiScreen; @@ -32,7 +29,6 @@ public class MainMenu extends ScaledGuiScreen { private final MenuButton exit; private String info = "Failed to get version update"; - private String welcome = "Failed to get version update"; private boolean needUpdate = false; private static final Animation startAnimation = new Animation(); @@ -99,7 +95,7 @@ public void render(int mouseX, int mouseY, float partialTicks) { FPSMaster.fontManager.s16.drawString("Copyright Mojang AB. Do not distribute!", guiWidth - w - 4, guiHeight - 14, Color.WHITE.getRGB()); // Display welcome message - welcome = FPSMaster.INSTANCE.loggedIn ? TextFormattingProvider.getGreen() + String.format(FPSMaster.i18n.get("mainmenu.welcome"), FPSMaster.configManager.configure.getOrCreate("username", "")) : TextFormattingProvider.getRed().toString() + TextFormattingProvider.getBold().toString() + FPSMaster.i18n.get("mainmenu.notlogin"); + String welcome = FPSMaster.INSTANCE.loggedIn ? TextFormattingProvider.getGreen() + String.format(FPSMaster.i18n.get("mainmenu.welcome"), FPSMaster.configManager.configure.getOrCreate("username", "")) : TextFormattingProvider.getRed().toString() + TextFormattingProvider.getBold().toString() + FPSMaster.i18n.get("mainmenu.notlogin"); FPSMaster.fontManager.s16.drawString(welcome, 4, guiHeight - 52, Color.WHITE.getRGB()); // Version info @@ -141,7 +137,7 @@ public void onClick(int mouseX, int mouseY, int mouseButton) { if (Render2DUtils.isHovered(4f, guiHeight - 40, uw, 14f, mouseX, mouseY) && needUpdate) { try { - Desktop.getDesktop().browse(new URI("https://fpsmaster.top/download")); + Desktop.getDesktop().browse(new URI("https://www.fpsmaster.top/download")); } catch (Exception e) { e.printStackTrace(); } diff --git a/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinEntityRenderer.java b/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinEntityRenderer.java index 55b76615..d6fadd0f 100644 --- a/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinEntityRenderer.java +++ b/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinEntityRenderer.java @@ -7,6 +7,7 @@ import net.minecraft.client.renderer.ActiveRenderInfo; import net.minecraft.client.renderer.EntityRenderer; import net.minecraft.client.renderer.GlStateManager; +import net.minecraft.client.settings.GameSettings; import net.minecraft.client.shader.ShaderGroup; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityLivingBase; @@ -44,10 +45,9 @@ private void renderWorldPass(int pass, float partialTicks, long finishTimeNano, EventDispatcher.dispatchEvent(new EventRender3D(partialTicks)); } - @Inject(method = "setupViewBobbing", at = @At("HEAD"), cancellable = true) - public void bobbing(float partialTicks, CallbackInfo ci) { - if (MinimizedBobbing.using) - ci.cancel(); + @Redirect(method = "setupCameraTransform", at = @At(value = "FIELD", target = "Lnet/minecraft/client/settings/GameSettings;viewBobbing:Z")) + public boolean bobbing(GameSettings instance) { + return mc.gameSettings.viewBobbing && !MinimizedBobbing.using; } @Inject(method = "hurtCameraEffect", at = @At("HEAD"), cancellable = true) From d2698c40df67e8f895acd448946f4a210fc317cf Mon Sep 17 00:00:00 2001 From: vlouboos Date: Sat, 3 May 2025 14:59:58 +0800 Subject: [PATCH 029/193] Fixed 1.7 Animation --- .../forge/mixin/MixinItemRenderer.java | 42 ++++++++----------- 1 file changed, 18 insertions(+), 24 deletions(-) diff --git a/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinItemRenderer.java b/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinItemRenderer.java index 1d641b32..f7cda7e2 100644 --- a/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinItemRenderer.java +++ b/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinItemRenderer.java @@ -80,7 +80,6 @@ public void renderFireInFirstPerson(CallbackInfo ci) { GlStateManager.depthMask(false); GlStateManager.enableBlend(); GlStateManager.tryBlendFuncSeparate(770, 771, 1, 0); - float f = 1.0F; for (int i = 0; i < 2; ++i) { GlStateManager.pushMatrix(); @@ -90,11 +89,6 @@ public void renderFireInFirstPerson(CallbackInfo ci) { float f2 = textureatlassprite.getMaxU(); float f3 = textureatlassprite.getMinV(); float f4 = textureatlassprite.getMaxV(); - float f5 = -0.5F; - float f6 = 0.5F; - float f7 = -0.5F; - float f8 = 0.5F; - float f9 = -0.5F; GlStateManager.translate(0, FireModifier.using ? -FireModifier.height.getValue().floatValue() : 0, 0); if (FireModifier.using && FireModifier.customColor.getValue()) { Color color = FireModifier.colorSetting.getColor(); @@ -120,56 +114,56 @@ public void renderFireInFirstPerson(CallbackInfo ci) { } - private void drawBlocking(float swingProgress, float equippedProgress) { + private void drawBlocking(float equippedProgress, float swingProgress) { GL11.glTranslated(OldAnimations.x.getValue().floatValue(), OldAnimations.y.getValue().floatValue(), OldAnimations.z.getValue().floatValue()); // GL11.glScaled(OldAnimations.scale.getValue().floatValue(), OldAnimations.scale.getValue().floatValue(), 0); if (OldAnimations.animationMode.isMode("Sigma")) { - this.transformFirstPersonItem(equippedProgress, 0.0f); - float swong = MathHelper.sin((float) (MathHelper.sqrt_float(swingProgress) * Math.PI)); + this.transformFirstPersonItem(swingProgress, 0.0f); + float swong = MathHelper.sin((float) (MathHelper.sqrt_float(equippedProgress) * Math.PI)); GlStateManager.rotate(-swong * 55 / 2.0F, -8.0F, -0.0F, 9.0F); GlStateManager.rotate(-swong * 45, 1.0F, swong / 2, -0.0F); this.doBlockTransformations(); GL11.glTranslated(1.2, 0.3, 0.5); GL11.glTranslatef(-1, mc.thePlayer.isSneaking() ? -0.1F : -0.2F, 0.2F); } else if (OldAnimations.animationMode.isMode("Debug")) { - this.transformFirstPersonItem(0.2f, equippedProgress); + this.transformFirstPersonItem(0.2f, swingProgress); this.doBlockTransformations(); GlStateManager.translate(-0.5, 0.2, 0.0); } else if (OldAnimations.animationMode.isMode("Luna")) { - this.transformFirstPersonItem(swingProgress, 0.0F); + this.transformFirstPersonItem(equippedProgress, 0.0F); this.doBlockTransformations(); - final float sin2 = MathHelper.sin((float) (MathHelper.sqrt_float(equippedProgress) * Math.PI)); + final float sin2 = MathHelper.sin((float) (MathHelper.sqrt_float(swingProgress) * Math.PI)); GlStateManager.scale(1.0f, 1.0f, 1.0f); GlStateManager.translate(-0.2f, 0.45f, 0.25f); GlStateManager.rotate(-sin2 * 20.0f, -5.0f, -5.0f, 9.0f); } else if (OldAnimations.animationMode.isMode("1.7")) { - this.transformFirstPersonItem(swingProgress - 0.3F, equippedProgress); + this.transformFirstPersonItem(equippedProgress, swingProgress); this.doBlockTransformations(); } else if (OldAnimations.animationMode.isMode("Swang")) { - this.transformFirstPersonItem(swingProgress / 2.0F, equippedProgress); + this.transformFirstPersonItem(equippedProgress / 2.0F, swingProgress); float var15; - var15 = MathHelper.sin((float) (MathHelper.sqrt_float(equippedProgress) * Math.PI)); + var15 = MathHelper.sin((float) (MathHelper.sqrt_float(swingProgress) * Math.PI)); GlStateManager.rotate(var15 * 30.0F / 2.0F, -var15, -0.0F, 9.0F); GlStateManager.rotate(var15 * 40.0F, 1.0F, -var15 / 2.0F, -0.0F); this.doBlockTransformations(); } else if (OldAnimations.animationMode.isMode("Swank")) { - this.transformFirstPersonItem(swingProgress / 2.0F, equippedProgress); + this.transformFirstPersonItem(equippedProgress / 2.0F, swingProgress); float var15; - var15 = MathHelper.sin((float) (MathHelper.sqrt_float(swingProgress) * Math.PI)); + var15 = MathHelper.sin((float) (MathHelper.sqrt_float(equippedProgress) * Math.PI)); GlStateManager.rotate(var15 * 30.0F, -var15, -0.0F, 9.0F); GlStateManager.rotate(var15 * 40.0F, 1.0F, -var15, -0.0F); this.doBlockTransformations(); } else if (OldAnimations.animationMode.isMode("Swong")) { - this.transformFirstPersonItem(swingProgress / 2.0F, 0.0F); - float var151 = MathHelper.sin((float) (MathHelper.sqrt_float(equippedProgress) * Math.PI)); + this.transformFirstPersonItem(equippedProgress / 2.0F, 0.0F); + float var151 = MathHelper.sin((float) (MathHelper.sqrt_float(swingProgress) * Math.PI)); GlStateManager.rotate(-var151 * 40.0F / 2.0F, var151 / 2.0F, -0.0F, 9.0F); GlStateManager.rotate(-var151 * 30.0F, 1.0F, var151 / 2.0F, -0.0F); this.doBlockTransformations(); } else if (OldAnimations.animationMode.isMode("Jigsaw")) { - this.transformFirstPersonItem(0.1f, equippedProgress); + this.transformFirstPersonItem(0.1f, swingProgress); this.doBlockTransformations(); GlStateManager.translate(-0.5, 0, 0); } else if (OldAnimations.animationMode.isMode("Jello")) { @@ -202,12 +196,12 @@ private void drawBlocking(float swingProgress, float equippedProgress) { GlStateManager.rotate(-10, 1.0f, 0.0f, -1.0f); GlStateManager.rotate(mc.thePlayer.isSwingInProgress ? -alpha / 5f : 1, 1.0f, -0.0f, 1.0f); } else if (OldAnimations.animationMode.isMode("Push")) { - this.transformFirstPersonItem(swingProgress, 0.0F); + this.transformFirstPersonItem(equippedProgress, 0.0F); this.doBlockTransformations(); - GlStateManager.rotate(-MathHelper.sin((float) (MathHelper.sqrt_float(equippedProgress) * Math.PI)) * 35.0F, -8.0F, -0.0F, 9.0F); - GlStateManager.rotate(-MathHelper.sin((float) (MathHelper.sqrt_float(equippedProgress) * Math.PI)) * 10.0F, 1.0F, -0.4F, -0.5F); + GlStateManager.rotate(-MathHelper.sin((float) (MathHelper.sqrt_float(swingProgress) * Math.PI)) * 35.0F, -8.0F, -0.0F, 9.0F); + GlStateManager.rotate(-MathHelper.sin((float) (MathHelper.sqrt_float(swingProgress) * Math.PI)) * 10.0F, 1.0F, -0.4F, -0.5F); }else{ - this.transformFirstPersonItem(swingProgress - 0.3F, equippedProgress); + this.transformFirstPersonItem(equippedProgress - 0.3F, swingProgress); this.doBlockTransformations(); } } From e4d4b7a37f4546b842da5b0ee3fd037b0a936a43 Mon Sep 17 00:00:00 2001 From: vlouboos <87124020+vlouboos@users.noreply.github.com> Date: Wed, 7 May 2025 21:15:08 +0800 Subject: [PATCH 030/193] Fixed an earlier bug --- .../src/main/java/top/fpsmaster/forge/mixin/MixinMinecraft.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinMinecraft.java b/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinMinecraft.java index 2cb0114a..7972f9e0 100644 --- a/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinMinecraft.java +++ b/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinMinecraft.java @@ -220,7 +220,7 @@ public void cpsr(CallbackInfo ci) { EventDispatcher.dispatchEvent(new EventMouseClick(1)); } - @Inject(method = "dispatchKeypresses", at = @At(value = "INVOKE", target = "Lorg/lwjgl/input/Keyboard;getEventKey()I", shift = At.Shift.AFTER), remap = false) + @Inject(method = "dispatchKeypresses", at = @At(value = "INVOKE", target = "Lorg/lwjgl/input/Keyboard;getEventKey()I", shift = At.Shift.AFTER)) public void keyEvent(CallbackInfo ci) { EventKey key = new EventKey(Keyboard.getEventKey() == 0 ? Keyboard.getEventCharacter() + 256 : Keyboard.getEventKey()); EventDispatcher.dispatchEvent(key); From b74ee3aa927765b3c9a643d1fab76223139f05e8 Mon Sep 17 00:00:00 2001 From: vlouboos <87124020+vlouboos@users.noreply.github.com> Date: Wed, 7 May 2025 21:17:39 +0800 Subject: [PATCH 031/193] Fixed an earlier bug --- .../main/java/top/fpsmaster/forge/mixin/MixinSplashScreen.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinSplashScreen.java b/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinSplashScreen.java index 801d80b9..2fa158a9 100644 --- a/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinSplashScreen.java +++ b/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinSplashScreen.java @@ -14,7 +14,7 @@ import java.awt.*; -@Mixin(value = SplashProgress.class, remap = false) +@Mixin(value = SplashProgress.class) @SuppressWarnings("all") public class MixinSplashScreen { From b1973df9c26c81abe4a4f518ce46971958808a10 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B2=99=E5=AD=90awa?= <110669856+xiaoshaziYA@users.noreply.github.com> Date: Wed, 7 May 2025 21:26:21 +0800 Subject: [PATCH 032/193] =?UTF-8?q?=E6=96=B0=E5=A2=9Emod=E7=95=8C=E9=9D=A2?= =?UTF-8?q?=E7=9A=84fpsmaster=E5=AE=A2=E6=88=B7=E7=AB=AF=E5=9B=BE=E6=A0=87?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * 更新图标 * Create 1.md * 新增图标 * 删除md --- .../resources/assets/fpsmaster/textures/icon.png | Bin 0 -> 1184 bytes v1.8.9/src/main/resources/mcmod.info | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) create mode 100644 v1.8.9/src/main/resources/assets/fpsmaster/textures/icon.png diff --git a/v1.8.9/src/main/resources/assets/fpsmaster/textures/icon.png b/v1.8.9/src/main/resources/assets/fpsmaster/textures/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..673ac21e651e49d3fec27ef2bbb5c374361ae216 GIT binary patch literal 1184 zcmV;R1Yi4!P)Px(T1iAfRCr$Pn>|bvK@`XTdx5*duwaa(iIPxgM9J(HZ~^G8XEyYxRYCbcP!kkySHy?Ity?D}xY?0(Eh~jyZwe{0(IO zxDM&R7o-3Tce{%>dr|>GuLn}SCCqKNv)&N{WO*Ww?*M2pULbJAQ$PLV1~M5D`I1{< z5ex8Q2_oVH4?xrsM8#JG04@X>@f8EW4T7xriUQyS!Hf8^0%*{I?hbw^bn?rE(Sh0= z?r{%wrF{IrxPf#zq5$mxFSMo6+OjPcb8Oxw2sHCv#Z%KgDMNVUCAAO8rIK z_5?xGH0b)j>G$~bjT+e55pP5qfC>l)Ek38gYf4Pk5`rLJ2>=;O2#R=R07M`JNxV`3 z90)-ZuN*)r2$4tx_4WVaoySMk+dFmZ*$LV;Y;}x574M4$m_P`^nbR4ZKbsEZ%+X-*mTWWu8ZOv0srPLUGSpwAI;RfJ#w;J)L056%Pvibl&#QOz7xdr$s z-VX>$0hB|$Y6!{zsC0PTt%99Tpn?t63AjZWApo_t`Jq`;&j%sigfudv=V}2IcDt@` z;OLQjVZi*|4JI2vqYfl@Gd80$27a#QDIcWxLI|DL_QlihQ%`klZo0`AI1b+*E)Hp9 zGY05pfvPy~K2)(cMjz;`1PR*$;&EVNz0xs}~v5#bhu!t7Ds)sA2=4 zz7N#_WBuwNn6*4wzsHYdapTekQ=;>0BI2da0;(Wb3z;e)h>Dj2pu!TIs<>Vt$cUE) zK>t`*2aHQB2e%To41~!?I<_S<^g=$sy7CG`BWLlti8tF2h4AHTE#~Iq?9ET%Sfv5P zqQK-3-yw3v%R>10DTal`s4xU60CYuWa?n5V90>QG>FBvxT%P;*DT;-~m=FYE0CwV6 z*MPfE4BHSXI`c*5sR38ow{Wt#xZr0xJiEI}q7Z}t#ACpOW#+&C0Hz-2YjSp*rTI4o zmfrCXCxx?rxqS<#9K@UNIYD@}7y}r$)Yt&%mew81n*aO-cs^HLkhFua{2qAmnlYM! z=_l9&mYZl!q0SBhH!QLNSkD4)KjcN(9XstTMRX}x0k{bw@B^LuK4D^3N1Cx6W&>z! z0Ft{ozU2?VO9%1hBw8VemaZujHq--&j&+Pb)LFN`$V!K9t%Dro`Y%pk7B~&kfGG5l zAro0n!l9-HAP~Q|z&e@nhOG82wgsr|HaM+?0Q@YB1ZSR|M-o~ Date: Wed, 7 May 2025 21:32:12 +0800 Subject: [PATCH 033/193] =?UTF-8?q?=E7=A7=BB=E9=99=A4=E6=9C=AA=E5=90=88?= =?UTF-8?q?=E5=B9=B6=E7=9A=84Pull=20Request=E7=9A=84=E8=87=AA=E5=8A=A8?= =?UTF-8?q?=E6=9E=84=E5=BB=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/gradle.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml index 2d30f4c4..b475bde3 100644 --- a/.github/workflows/gradle.yml +++ b/.github/workflows/gradle.yml @@ -3,8 +3,6 @@ name: Java CI with Gradle on: push: branches: [ "master", "v4" ] - pull_request: - branches: [ "master", "v4" ] jobs: build: From 24f00d21d4af037f239fe56ca995fabea030bdc5 Mon Sep 17 00:00:00 2001 From: vlouboos <87124020+vlouboos@users.noreply.github.com> Date: Fri, 9 May 2025 19:16:59 +0800 Subject: [PATCH 034/193] Unverified Fix --- v1.8.9/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/v1.8.9/build.gradle.kts b/v1.8.9/build.gradle.kts index db3989ed..e8c366cd 100644 --- a/v1.8.9/build.gradle.kts +++ b/v1.8.9/build.gradle.kts @@ -3,7 +3,7 @@ import org.apache.commons.lang3.SystemUtils plugins { idea java - id("gg.essential.loom") version "0.10.0.5" + id("gg.essential.loom") version "1.3-SNAPSHOT" id("dev.architectury.architectury-pack200") version "0.1.3" id("com.github.johnrengelman.shadow") version "8.1.1" id("com.gorylenko.gradle-git-properties") version "2.3.2" From fb6d568582e0d5f879cc3c91ff047df699aac2c0 Mon Sep 17 00:00:00 2001 From: vlouboos <87124020+vlouboos@users.noreply.github.com> Date: Fri, 9 May 2025 19:21:39 +0800 Subject: [PATCH 035/193] Update build.gradle.kts --- v1.8.9/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/v1.8.9/build.gradle.kts b/v1.8.9/build.gradle.kts index e8c366cd..db3989ed 100644 --- a/v1.8.9/build.gradle.kts +++ b/v1.8.9/build.gradle.kts @@ -3,7 +3,7 @@ import org.apache.commons.lang3.SystemUtils plugins { idea java - id("gg.essential.loom") version "1.3-SNAPSHOT" + id("gg.essential.loom") version "0.10.0.5" id("dev.architectury.architectury-pack200") version "0.1.3" id("com.github.johnrengelman.shadow") version "8.1.1" id("com.gorylenko.gradle-git-properties") version "2.3.2" From 12fecf0e76323f87fc523234a24aad07789a921f Mon Sep 17 00:00:00 2001 From: SuperSkidder Date: Sat, 17 May 2025 14:18:15 +0800 Subject: [PATCH 036/193] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E6=94=AF?= =?UTF-8?q?=E6=8C=81shader=E7=9A=84=E5=88=A4=E6=96=AD=E9=80=BB=E8=BE=91?= =?UTF-8?q?=E9=94=99=E8=AF=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- shared/java/top/fpsmaster/utils/os/OSUtil.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/shared/java/top/fpsmaster/utils/os/OSUtil.java b/shared/java/top/fpsmaster/utils/os/OSUtil.java index f5cfe0ba..c2213431 100644 --- a/shared/java/top/fpsmaster/utils/os/OSUtil.java +++ b/shared/java/top/fpsmaster/utils/os/OSUtil.java @@ -2,7 +2,7 @@ public class OSUtil { - public static boolean supportShader; + public static boolean supportShader = true; public static boolean isMac() { return System.getProperty("os.name").toLowerCase().contains("mac"); From 4b0e64fc38f98cf3be2d027779d3fe3900a1878f Mon Sep 17 00:00:00 2001 From: SuperSkidder Date: Sat, 17 May 2025 15:47:55 +0800 Subject: [PATCH 037/193] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8DGUIMultiplayer?= =?UTF-8?q?=E7=9A=84=E7=82=B9=E5=87=BB=E4=BA=8B=E4=BB=B6bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- shared/java/top/fpsmaster/ui/mc/GuiMultiplayer.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/shared/java/top/fpsmaster/ui/mc/GuiMultiplayer.java b/shared/java/top/fpsmaster/ui/mc/GuiMultiplayer.java index e3176527..5c9d3dce 100644 --- a/shared/java/top/fpsmaster/ui/mc/GuiMultiplayer.java +++ b/shared/java/top/fpsmaster/ui/mc/GuiMultiplayer.java @@ -261,7 +261,8 @@ public void onClick(int mouseX, int mouseY, int mouseButton) { serverListDisplay.addAll(serverListRecommended); } - int y = 80; + float y = 70 + scrollContainer.getScroll(); + for (ServerListEntry server : serverListDisplay) { if (server.getServerData() == null) { return; @@ -278,7 +279,7 @@ public void onClick(int mouseX, int mouseY, int mouseButton) { } } } - y += 54; + y += 58; } From 2ab54b539408d68d95c8da0324775cfa74285e25 Mon Sep 17 00:00:00 2001 From: SuperSkidder Date: Sat, 17 May 2025 18:27:06 +0800 Subject: [PATCH 038/193] feat: new clickgui --- .../fpsmaster/ui/click/CategoryComponent.java | 7 +- .../top/fpsmaster/ui/click/MainPanel.java | 260 +++++++----------- .../ui/click/component/ScrollContainer.java | 5 +- .../ui/click/modules/ModuleRenderer.java | 20 +- 4 files changed, 121 insertions(+), 171 deletions(-) diff --git a/shared/java/top/fpsmaster/ui/click/CategoryComponent.java b/shared/java/top/fpsmaster/ui/click/CategoryComponent.java index 51575cdd..51a481fe 100644 --- a/shared/java/top/fpsmaster/ui/click/CategoryComponent.java +++ b/shared/java/top/fpsmaster/ui/click/CategoryComponent.java @@ -7,6 +7,7 @@ import top.fpsmaster.utils.math.animation.Type; import top.fpsmaster.utils.render.Render2DUtils; +import java.awt.*; import java.util.Locale; public class CategoryComponent { @@ -22,7 +23,7 @@ public CategoryComponent(Category category) { public void render(float x, float y, float width, float height, float mouseX, float mouseY, boolean selected) { animationName.start( animationName.getColor(), - selected ? FPSMaster.theme.getCategoryTextSelected() : FPSMaster.theme.getCategoryText(), + selected ? new Color(0,0,0) : new Color(255,255,255), 0.2f, Type.EASE_IN_OUT_QUAD ); @@ -30,8 +31,8 @@ public void render(float x, float y, float width, float height, float mouseX, fl Render2DUtils.drawImage( new ResourceLocation("client/gui/settings/icons/" + category.name().toLowerCase() + ".png"), - x + 12, - y - 2, + x + 10, + y, 12f, 12f, animationName.getColor() diff --git a/shared/java/top/fpsmaster/ui/click/MainPanel.java b/shared/java/top/fpsmaster/ui/click/MainPanel.java index 7b36b860..7352fdc3 100644 --- a/shared/java/top/fpsmaster/ui/click/MainPanel.java +++ b/shared/java/top/fpsmaster/ui/click/MainPanel.java @@ -1,6 +1,5 @@ package top.fpsmaster.ui.click; -import net.minecraft.client.gui.GuiScreen; import net.minecraft.client.gui.ScaledResolution; import net.minecraft.client.renderer.GlStateManager; import net.minecraft.util.ResourceLocation; @@ -21,14 +20,11 @@ import top.fpsmaster.utils.math.animation.Type; import top.fpsmaster.utils.render.Render2DUtils; import top.fpsmaster.utils.render.ScaledGuiScreen; -import top.fpsmaster.utils.render.StencilUtil; -import top.fpsmaster.utils.render.shader.KawaseBloom; -import top.fpsmaster.utils.render.shader.KawaseBlur; -import top.fpsmaster.utils.render.shader.RoundedUtil; import java.awt.Color; import java.io.IOException; import java.util.LinkedList; +import java.util.Locale; public class MainPanel extends ScaledGuiScreen { boolean drag = false; @@ -36,7 +32,7 @@ public class MainPanel extends ScaledGuiScreen { float dragY = 0f; Category curType = Category.OPTIMIZE; LinkedList categories = new LinkedList<>(); - final float leftWidth = 110f; + final float leftWidth = 50f; float modsWheel = 0f; float wheelTemp = 0f; boolean sizeDrag = false; @@ -48,9 +44,11 @@ public class MainPanel extends ScaledGuiScreen { float selection = 0f; ColorAnimation sizeDragBorder = new ColorAnimation(255, 255, 255, 0); - ColorAnimation backgroundColor = new ColorAnimation(FPSMaster.theme.getBackground()); - ColorAnimation modeColor = new ColorAnimation(FPSMaster.theme.getTypeSelectionBackground()); - ColorAnimation logoColor = new ColorAnimation(FPSMaster.theme.getLogo()); + ColorAnimation backgroundColor = new ColorAnimation(39, 39, 39, 120); + ColorAnimation modeColor = new ColorAnimation(70, 70, 70, 200); + ColorAnimation logoColor = new ColorAnimation(255, 255, 255, 255); + + float categoryAnimation = 30; boolean close = false; @@ -118,40 +116,34 @@ public void render(int mouseX, int mouseY, float partialTicks) { GL11.glScaled(scaleAnimation.value, scaleAnimation.value, 0.0); GlStateManager.translate(-guiWidth / 2.0, -height / 2.0, 0.0); - Render2DUtils.drawOptimizedRoundedRect( - (x - 1), - (y - 1), - width + 2, - height + 2, - sizeDragBorder.getColor() - ); - backgroundColor.base(FPSMaster.theme.getBackground()); + backgroundColor.base(new Color(10, 10, 10, 180)); + Render2DUtils.drawBlurArea((int) (x + leftWidth), y, (int) (width - leftWidth), (int) height, 3, backgroundColor.getColor()); Render2DUtils.drawOptimizedRoundedRect( - x, + x + leftWidth, y, - width, + width - leftWidth, height, backgroundColor.getColor() ); - logoColor.base(FPSMaster.theme.getLogo()); - Render2DUtils.drawImage( - new ResourceLocation("client/gui/settings/logo.png"), - x + leftWidth / 2 - 40 - 5, - y + 15f, - 81.5f, - 64 / 2f, - logoColor.getColor() - ); +// logoColor.base(new Color(255, 255, 255)); +// Render2DUtils.drawImage( +// new ResourceLocation("client/gui/settings/logo.png"), +// x + leftWidth / 2 - 40 - 5, +// y + 15f, +// 81.5f, +// 64 / 2f, +// logoColor.getColor() +// ); - if (drag || sizeDrag) { - sizeDragBorder.start(sizeDragBorder.getColor(), new Color(255, 255, 255), 0.15f, Type.EASE_IN_OUT_QUAD); - } else { - sizeDragBorder.start(sizeDragBorder.getColor(), new Color(255, 255, 255, 0), 0.2f, Type.EASE_IN_OUT_QUAD); - } +// if (drag || sizeDrag) { +// sizeDragBorder.start(sizeDragBorder.getColor(), new Color(255, 255, 255), 0.15f, Type.EASE_IN_OUT_QUAD); +// } else { +// sizeDragBorder.start(sizeDragBorder.getColor(), new Color(255, 255, 255, 0), 0.2f, Type.EASE_IN_OUT_QUAD); +// } - sizeDragBorder.update(); +// sizeDragBorder.update(); if (Render2DUtils.isHoveredWithoutScale( x + width - 10, @@ -167,7 +159,7 @@ public void render(int mouseX, int mouseY, float partialTicks) { y + height - 5, 5f, 5f, - FPSMaster.theme.getDragHovered() + new Color(255, 255, 255) ); } else { Render2DUtils.drawImage( @@ -176,105 +168,16 @@ public void render(int mouseX, int mouseY, float partialTicks) { y + height - 5, 5f, 5f, - FPSMaster.theme.getDrag() - ); - } - - float my = (y + 60); - for (CategoryComponent m : categories) { - Render2DUtils.drawOptimizedRoundedRect( - x + 5, - my - 6, - leftWidth - 10, - 20f, - m.categorySelectionColor.getColor() - ); - my += 24f; - } - - my = (y + 60); - Render2DUtils.drawOptimizedRoundedRect( - x + 5, - selection - 6, - leftWidth - 10, - 20f, - FPSMaster.theme.getPrimary() - ); - - for (CategoryComponent m : categories) { - if (Render2DUtils.isHoveredWithoutScale(x, my - 6, leftWidth - 10, 20f, mouseX, mouseY)) { - m.categorySelectionColor.base(FPSMaster.theme.getTypeSelectionBackground()); - } else { - m.categorySelectionColor.base(Render2DUtils.reAlpha(FPSMaster.theme.getTypeSelectionBackground(), 0)); - } - - if (m.category == curType) { - selection = (sizeDrag || drag) - ? my - : (float) AnimationUtils.base(selection, my, 0.2); - } - - m.render( - x + 5, - my, - leftWidth - 10, - 20f, - mouseX, - mouseY, - curType == m.category + new Color(200, 200, 200) ); - my += 24f; } - Render2DUtils.drawOptimizedRoundedRect( - x + 40, - y + height - 22, - 34f, - 14f, - 10, - modeColor.getColor().getRGB() - ); - - Render2DUtils.drawImage( - new ResourceLocation("client/textures/ui/" + FPSMaster.themeSlot + ".png"), - x + 43, - y + height - 19, - 8f, - 8f, - -1 - ); - - FPSMaster.fontManager.s16.drawString( - FPSMaster.i18n.get("theme.title"), - x + 20, - y + height - 20, - FPSMaster.theme.getCategoryText().getRGB() - ); - - FPSMaster.fontManager.s16.drawString( - FPSMaster.i18n.get("theme." + FPSMaster.themeSlot), - x + 52, - y + height - 20, - FPSMaster.theme.getCategoryTextSelected().getRGB() - ); - - if (Render2DUtils.isHoveredWithoutScale( - x + 40, - y + height - 22, - 34f, - 14f, - mouseX, - mouseY - )) { - modeColor.base(FPSMaster.theme.getPrimary()); - } else { - modeColor.base(FPSMaster.theme.getTypeSelectionBackground()); - } + FPSMaster.fontManager.s24.drawStringWithShadow(FPSMaster.i18n.get("category." + curType.name().toLowerCase(Locale.getDefault())), x + leftWidth + 10, y + 10, -1); GL11.glEnable(GL11.GL_SCISSOR_TEST); Render2DUtils.doGlScissor( - x, y, width, - (height - 4), + x, y + 25, width, + (height - 30), scaleFactor ); @@ -284,40 +187,101 @@ public void render(int mouseX, int mouseY, float partialTicks) { MusicPanel.draw(x + leftWidth, y, width - leftWidth, height, mouseX, mouseY, scaleFactor); } else { modHeight = 20f; - float containerWidth = width - leftWidth - 2; + float containerWidth = width - leftWidth - 10; int finalMouseY = mouseY; - modsContainer.draw(x + leftWidth, y + 10f, containerWidth, height - 20f, mouseX, mouseY, () -> { - float modsY = y + 10f; + modsContainer.draw(x + leftWidth, y + 25f, containerWidth, height - 20f, mouseX, mouseY, () -> { + float modsY = y + 22f; for (ModuleRenderer m : mods) { if (m.mod.category == curType) { float moduleY = modsY + modsContainer.getScroll(); if (moduleY + 40 + m.height > y && moduleY < y + height) { m.render( - x + leftWidth, + x + leftWidth + 10, moduleY, - containerWidth, + containerWidth - 10, 40f, mouseX, finalMouseY, curModule == m.mod ); } - modsY += 40 + m.height; - modHeight += 40 + m.height; + modsY += 45 + m.height; + modHeight += 45 + m.height; } } modsContainer.setHeight(modHeight); }); } +// Render2DUtils.drawRect( +// x + leftWidth, y, +// width - leftWidth, height, +// Render2DUtils.reAlpha(new Color(39, 39, 39), Render2DUtils.limit(255 - moduleListAlpha)) +// ); + GL11.glEnable(GL11.GL_BLEND); - Render2DUtils.drawRect( - x + leftWidth, y, - width - leftWidth, height, - Render2DUtils.reAlpha(FPSMaster.theme.getBackground(), Render2DUtils.limit(255 - moduleListAlpha)) + GL11.glDisable(GL11.GL_SCISSOR_TEST); + + + if (Render2DUtils.isHoveredWithoutScale(x, (int) (y + height / 2 - 70), categoryAnimation, 140, mouseX, mouseY)) { + categoryAnimation = (float) AnimationUtils.base(categoryAnimation, 100f, 0.15f); + } else { + categoryAnimation = (float) AnimationUtils.base(categoryAnimation, 30f, 0.15f); + } + + Render2DUtils.drawBlurArea(x, (int) (y + height / 2 - 70), (int) categoryAnimation, 140, 10, backgroundColor.getColor()); + Render2DUtils.drawOptimizedRoundedRect( + x, + y + height / 2 - 70, + categoryAnimation, + 140, + 10, + backgroundColor.getColor().getRGB() + ); + + float my = y + 60; + Render2DUtils.drawOptimizedRoundedRect( + x + 5, + selection - 6, + categoryAnimation - 8, + 22f, + 11, + new Color(255, 255, 255).getRGB() + ); + + + GL11.glEnable(GL11.GL_SCISSOR_TEST); + Render2DUtils.doGlScissor( + x, y, categoryAnimation, + (height - 4), + scaleFactor ); + for (CategoryComponent m : categories) { + if (Render2DUtils.isHoveredWithoutScale(x, my - 6, leftWidth - 10, 20f, mouseX, mouseY)) { + m.categorySelectionColor.base(new Color(70, 70, 70)); + } else { + m.categorySelectionColor.base(Render2DUtils.reAlpha(new Color(70, 70, 70), 0)); + } + + if (m.category == curType) { + selection = (sizeDrag || drag) + ? my + : (float) AnimationUtils.base(selection, my, 0.2); + } + + m.render( + x, + my, + leftWidth - 10, + 20f, + mouseX, + mouseY, + curType == m.category + ); + my += 27f; + } GL11.glDisable(GL11.GL_SCISSOR_TEST); } @@ -387,18 +351,6 @@ public void onClick(int mouseX, int mouseY, int mouseButton) { aiChatPanel.click(mouseX, mouseY, mouseButton); if (!Render2DUtils.isHoveredWithoutScale(x, y, width, height, mouseX, mouseY)) return; - if (mouseButton == 0 && Render2DUtils.isHoveredWithoutScale( - x + 40, y + height - 22, 34f, 14f, mouseX, mouseY - )) { - if ("dark".equals(FPSMaster.themeSlot)) { - FPSMaster.themeSlot = "light"; - FPSMaster.theme = new LightTheme(); - } else { - FPSMaster.themeSlot = "dark"; - FPSMaster.theme = new DarkTheme(); - } - } - if (mouseButton == 0 && Render2DUtils.isHoveredWithoutScale( x, y, leftWidth, 34f, mouseX, mouseY )) { @@ -426,13 +378,13 @@ public void onClick(int mouseX, int mouseY, int mouseButton) { } curType = c; } - my += 24f; + my += 27f; } if (curType == Category.Music) { MusicPanel.mouseClicked(mouseX, mouseY, mouseButton); } else { - float modsY = y + 10 + modsContainer.getRealScroll(); + float modsY = y + 22f + modsContainer.getRealScroll(); for (ModuleRenderer m : mods) { if (m.mod.category == curType) { m.mouseClick( @@ -444,7 +396,7 @@ public void onClick(int mouseX, int mouseY, int mouseButton) { mouseY, mouseButton ); - modsY += 40 + m.height; + modsY += 45 + m.height; } } } diff --git a/shared/java/top/fpsmaster/ui/click/component/ScrollContainer.java b/shared/java/top/fpsmaster/ui/click/component/ScrollContainer.java index deb87127..d399de8a 100644 --- a/shared/java/top/fpsmaster/ui/click/component/ScrollContainer.java +++ b/shared/java/top/fpsmaster/ui/click/component/ScrollContainer.java @@ -27,12 +27,13 @@ public void draw(float x, float y, float width, float height, int mouseX, int mo float scrollPercent = (getScroll() / (this.height - height)); float sY = y - scrollPercent * (height - sHeight); float sX = x + width + 1 - (float) scrollExpand; - Render2DUtils.drawRect( + Render2DUtils.drawOptimizedRoundedRect( sX, sY, 1f + (float) scrollExpand, sHeight, - new Color(255, 255, 255, 200) + 1, + new Color(255, 255, 255, 100).getRGB() ); if (Render2DUtils.isHovered( sX - 1, diff --git a/shared/java/top/fpsmaster/ui/click/modules/ModuleRenderer.java b/shared/java/top/fpsmaster/ui/click/modules/ModuleRenderer.java index 324913ea..4c430679 100644 --- a/shared/java/top/fpsmaster/ui/click/modules/ModuleRenderer.java +++ b/shared/java/top/fpsmaster/ui/click/modules/ModuleRenderer.java @@ -15,6 +15,7 @@ import top.fpsmaster.utils.math.animation.Type; import top.fpsmaster.utils.render.Render2DUtils; +import java.awt.*; import java.util.ArrayList; import java.util.Locale; import java.util.function.Consumer; @@ -66,25 +67,20 @@ public void render(float x, float y, float width, float height, float mouseX, fl background.start(background.getColor(), FPSMaster.theme.getModuleDisabled(), 0.2f, Type.EASE_IN_OUT_QUAD); } - Render2DUtils.drawOptimizedRoundedRect( - x + 4.5f, - y - 0.5f, - width - 9, - settingHeight + 38f, - FPSMaster.theme.getModuleEnabled() - ); Render2DUtils.drawOptimizedRoundedRect( x + 5, y, width - 10, settingHeight + 37f, - FPSMaster.theme.getModuleDisabled().getRGB() - ); - Render2DUtils.drawOptimizedRoundedBorderRect( - x + 5, y, width - 10, 37f, 0.5f, background.getColor(), Render2DUtils.reAlpha( - FPSMaster.theme.getModuleBorder(), (int) border) + 10, + new Color(100, 100, 100, 60).getRGB() ); +// Render2DUtils.drawOptimizedRoundedBorderRect( +// x + 5, y, width - 10, 37f, 0.5f, background.getColor(), Render2DUtils.reAlpha( +// FPSMaster.theme.getModuleBorder(), (int) border) +// ); + if (mod.category == Category.Interface) { Render2DUtils.drawImage( new ResourceLocation("client/textures/modules/interface.png"), From d9b1f2a450a82f16385eea0058bbac51ee1082ba Mon Sep 17 00:00:00 2001 From: SuperSkidder Date: Sun, 18 May 2025 11:43:44 +0800 Subject: [PATCH 039/193] =?UTF-8?q?feat:=20=E5=BE=AE=E8=B0=83?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- shared/java/top/fpsmaster/ui/click/MainPanel.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/shared/java/top/fpsmaster/ui/click/MainPanel.java b/shared/java/top/fpsmaster/ui/click/MainPanel.java index 7352fdc3..b1981f7b 100644 --- a/shared/java/top/fpsmaster/ui/click/MainPanel.java +++ b/shared/java/top/fpsmaster/ui/click/MainPanel.java @@ -172,11 +172,11 @@ public void render(int mouseX, int mouseY, float partialTicks) { ); } - FPSMaster.fontManager.s24.drawStringWithShadow(FPSMaster.i18n.get("category." + curType.name().toLowerCase(Locale.getDefault())), x + leftWidth + 10, y + 10, -1); + FPSMaster.fontManager.s24.drawStringWithShadow(FPSMaster.i18n.get("category." + curType.name().toLowerCase(Locale.getDefault())), x + leftWidth + 10, y + 9, -1); GL11.glEnable(GL11.GL_SCISSOR_TEST); Render2DUtils.doGlScissor( - x, y + 25, width, + x, y + 22, width, (height - 30), scaleFactor ); @@ -232,7 +232,7 @@ public void render(int mouseX, int mouseY, float partialTicks) { Render2DUtils.drawBlurArea(x, (int) (y + height / 2 - 70), (int) categoryAnimation, 140, 10, backgroundColor.getColor()); Render2DUtils.drawOptimizedRoundedRect( - x, + x + categoryAnimation / 50f, y + height / 2 - 70, categoryAnimation, 140, @@ -242,7 +242,7 @@ public void render(int mouseX, int mouseY, float partialTicks) { float my = y + 60; Render2DUtils.drawOptimizedRoundedRect( - x + 5, + x + 5 + categoryAnimation / 50f, selection - 6, categoryAnimation - 8, 22f, @@ -272,7 +272,7 @@ public void render(int mouseX, int mouseY, float partialTicks) { } m.render( - x, + x + categoryAnimation / 50f, my, leftWidth - 10, 20f, From ddf65a9cc8ae90ea21267904f751f100386fbf23 Mon Sep 17 00:00:00 2001 From: SuperSkidder Date: Fri, 30 May 2025 18:47:13 +0800 Subject: [PATCH 040/193] =?UTF-8?q?fix:=20=E9=9F=B3=E4=B9=90=E5=8D=A1?= =?UTF-8?q?=E9=A1=BF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../top/fpsmaster/features/impl/interfaces/MusicOverlay.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/shared/java/top/fpsmaster/features/impl/interfaces/MusicOverlay.java b/shared/java/top/fpsmaster/features/impl/interfaces/MusicOverlay.java index 40b1aec3..08ca7f7b 100644 --- a/shared/java/top/fpsmaster/features/impl/interfaces/MusicOverlay.java +++ b/shared/java/top/fpsmaster/features/impl/interfaces/MusicOverlay.java @@ -1,5 +1,6 @@ package top.fpsmaster.features.impl.interfaces; +import top.fpsmaster.FPSMaster; import top.fpsmaster.event.Subscribe; import top.fpsmaster.event.events.EventRender2D; import top.fpsmaster.features.impl.InterfaceModule; @@ -27,7 +28,7 @@ public MusicOverlay() { @Subscribe public void onRender(EventRender2D e) { if (timer.delay(50)) { - JLayerHelper.updateLoudness(); + FPSMaster.async.runnable(JLayerHelper::updateLoudness); } IngameOverlay.onRender(); } From 734b7709f010a801dd4eeae7d4886517d95899e7 Mon Sep 17 00:00:00 2001 From: SuperSkidder Date: Fri, 30 May 2025 19:08:32 +0800 Subject: [PATCH 041/193] =?UTF-8?q?fix:=20=E4=BC=98=E5=8C=96=E4=BA=86?= =?UTF-8?q?=E5=BE=AE=E8=BD=AF=E7=99=BB=E5=BD=95=EF=BC=8C=E6=98=BE=E7=A4=BA?= =?UTF-8?q?=E7=99=BB=E5=BD=95=E8=BF=9B=E5=BA=A6=EF=BC=8C=E4=BF=AE=E5=A4=8D?= =?UTF-8?q?=E9=83=A8=E5=88=86bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ui/screens/account/GuiWaiting.java | 4 +- .../ui/screens/mainmenu/MainMenu.java | 2 +- .../top/fpsmaster/utils/os/HttpRequest.java | 255 +++++++++ .../thirdparty/microsoft/MicrosoftLogin.java | 496 ++++++++++++------ .../assets/minecraft/client/lang/zh_cn.lang | 1 - 5 files changed, 591 insertions(+), 167 deletions(-) diff --git a/shared/java/top/fpsmaster/ui/screens/account/GuiWaiting.java b/shared/java/top/fpsmaster/ui/screens/account/GuiWaiting.java index 8f1e22bd..66a57ffb 100644 --- a/shared/java/top/fpsmaster/ui/screens/account/GuiWaiting.java +++ b/shared/java/top/fpsmaster/ui/screens/account/GuiWaiting.java @@ -17,7 +17,7 @@ public class GuiWaiting extends GuiScreen { @Override public void initGui() { super.initGui(); - MicrosoftLogin.login(); + FPSMaster.async.runnable(MicrosoftLogin::loginViaBrowser); } @Override @@ -35,7 +35,7 @@ public void drawScreen(int mouseX, int mouseY, float partialTicks) { // Draw text FPSMaster.fontManager.s24.drawCenteredString( - FPSMaster.i18n.get("microsoft.login.desc"), + MicrosoftLogin.loginProgressMessage, sr.getScaledWidth() / 2f, sr.getScaledHeight() / 2f - 30, FPSMaster.theme.getTextColorDescription().getRGB() diff --git a/shared/java/top/fpsmaster/ui/screens/mainmenu/MainMenu.java b/shared/java/top/fpsmaster/ui/screens/mainmenu/MainMenu.java index 197fefaf..89680d74 100644 --- a/shared/java/top/fpsmaster/ui/screens/mainmenu/MainMenu.java +++ b/shared/java/top/fpsmaster/ui/screens/mainmenu/MainMenu.java @@ -137,7 +137,7 @@ public void onClick(int mouseX, int mouseY, int mouseButton) { if (Render2DUtils.isHovered(4f, guiHeight - 40, uw, 14f, mouseX, mouseY) && needUpdate) { try { - Desktop.getDesktop().browse(new URI("https://www.fpsmaster.top/download")); + Desktop.getDesktop().browse(new URI("https://fpsmaster.top/download")); } catch (Exception e) { e.printStackTrace(); } diff --git a/shared/java/top/fpsmaster/utils/os/HttpRequest.java b/shared/java/top/fpsmaster/utils/os/HttpRequest.java index ed99a6b2..db4f5d6f 100644 --- a/shared/java/top/fpsmaster/utils/os/HttpRequest.java +++ b/shared/java/top/fpsmaster/utils/os/HttpRequest.java @@ -1,20 +1,39 @@ package top.fpsmaster.utils.os; +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.google.gson.JsonObject; +import org.apache.http.HttpEntity; +import org.apache.http.NameValuePair; +import org.apache.http.ParseException; +import org.apache.http.client.ClientProtocolException; import org.apache.http.client.HttpClient; +import org.apache.http.client.config.RequestConfig; +import org.apache.http.client.entity.UrlEncodedFormEntity; +import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.client.methods.HttpGet; import org.apache.http.client.methods.HttpPost; +import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClients; import org.apache.http.entity.StringEntity; +import org.apache.http.message.BasicNameValuePair; +import org.apache.http.util.EntityUtils; import top.fpsmaster.modules.logger.ClientLogger; import java.io.*; import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.List; import java.util.Map; public class HttpRequest { private static final HttpClient client = HttpClients.createDefault(); private static final int TIMEOUT = 15000; + public static Gson gson() { + return new GsonBuilder().setPrettyPrinting().disableHtmlEscaping().create(); + } + public static String get(String url) { return getWithCookie(url, ""); } @@ -112,4 +131,240 @@ public static void downloadAsync(String url, String filepath, Runnable callback) } }).start(); } + + /** + * 构建一个包含 Chrome 浏览器特征的 RequestConfig。 + * + * @return 配置好的 RequestConfig 实例。 + */ + private static RequestConfig buildRequestConfig() { + return RequestConfig.custom() + .setConnectTimeout(10000) // 设置连接主机服务超时时间 + .setConnectionRequestTimeout(10000) // 设置连接请求超时时间 + .setSocketTimeout(10000) // 设置读取数据连接超时时间 + .build(); + } + + /** + * 为 HTTP 请求设置 Chrome 浏览器特征头部。 + * + * @param request 可以是 HttpPost 或 HttpGet 实例。 + */ + private static void addChromeHeaders(org.apache.http.client.methods.HttpRequestBase request) { + request.setHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36"); + request.setHeader("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7"); + request.setHeader("Accept-Encoding", "gzip, deflate, br"); + request.setHeader("Accept-Language", "en-US,en;q=0.9,zh-CN;q=0.8,zh;q=0.7"); + request.setHeader("Connection", "keep-alive"); + } + + + /** + * 发送 HTTP POST 请求,请求体为原始字符串。 + * 默认 Content-Type 为 application/json,如果请求体是 JSON 格式。 + * + * @param url 请求的 URL。 + * @param body 请求体内容,通常为 JSON 字符串。 + * @return 响应体内容。 + * @throws RuntimeException 如果发生网络错误、协议错误或 HTTP 响应状态码非 2xx。 + */ + public static String post(String url, String body) { + // 使用 try-with-resources 确保 HttpClient 和 HttpResponse 自动关闭 + try (CloseableHttpClient httpClient = HttpClients.createDefault()) { + HttpPost httpPost = new HttpPost(url); + httpPost.setConfig(buildRequestConfig()); // 设置请求配置 + addChromeHeaders(httpPost); // 添加 Chrome 头部 + + // 假设 body 是 JSON 格式,设置 Content-Type 为 application/json + httpPost.setHeader("Content-Type", "application/json"); + + StringEntity stringEntity = new StringEntity(body, StandardCharsets.UTF_8); + httpPost.setEntity(stringEntity); + + try (CloseableHttpResponse httpResponse = httpClient.execute(httpPost)) { + return handleResponse(httpResponse, url); + } + } catch (ClientProtocolException e) { + throw new RuntimeException("HTTP POST 请求协议错误,URL: " + url, e); + } catch (IOException e) { + throw new RuntimeException("HTTP POST 请求 IO 错误,URL: " + url, e); + } catch (ParseException e) { + throw new RuntimeException("HTTP POST 响应解析错误,URL: " + url, e); + } + } + + /** + * 发送 HTTP POST 请求,请求体为 JsonObject。 + * 默认 Content-Type 为 application/json。 + * + * @param url 请求的 URL。 + * @param jsonObject 请求体内容,JsonObject 实例。 + * @return 响应体内容。 + * @throws RuntimeException 如果发生网络错误、协议错误或 HTTP 响应状态码非 2xx。 + */ + public static String postURL(String url, JsonObject jsonObject) { + // 使用 try-with-resources 确保 HttpClient 和 HttpResponse 自动关闭 + try (CloseableHttpClient httpClient = HttpClients.createDefault()) { + HttpPost httpPost = new HttpPost(url); + httpPost.setConfig(buildRequestConfig()); // 设置请求配置 + addChromeHeaders(httpPost); // 添加 Chrome 头部 + + // 设置 Content-Type 为 application/json,因为是发送 JsonObject + httpPost.setHeader("Content-Type", "application/json"); + + StringEntity stringEntity = new StringEntity(jsonObject.toString(), StandardCharsets.UTF_8); + httpPost.setEntity(stringEntity); + + try (CloseableHttpResponse httpResponse = httpClient.execute(httpPost)) { + return handleResponse(httpResponse, url); + } + } catch (ClientProtocolException e) { + throw new RuntimeException("HTTP POST 请求协议错误 (JsonObject),URL: " + url, e); + } catch (IOException e) { + throw new RuntimeException("HTTP POST 请求 IO 错误 (JsonObject),URL: " + url, e); + } catch (ParseException e) { + throw new RuntimeException("HTTP POST 响应解析错误 (JsonObject),URL: " + url, e); + } + } + + /** + * 发送 HTTP POST 请求,请求体为 Map 形式的表单数据。 + * Content-Type 为 application/x-www-form-urlencoded。 + * + * @param url 请求的 URL。 + * @param param 请求参数的 Map。 + * @return 响应体内容。 + * @throws RuntimeException 如果发生网络错误、协议错误或 HTTP 响应状态码非 2xx。 + */ + public static String postMAP(String url, Map param) { + // 使用 try-with-resources 确保 HttpClient 和 HttpResponse 自动关闭 + try (CloseableHttpClient httpClient = HttpClients.createDefault()) { + HttpPost httpPost = new HttpPost(url); + httpPost.setConfig(buildRequestConfig()); // 设置请求配置 + addChromeHeaders(httpPost); // 添加 Chrome 头部 + + // Content-Type 默认为 application/x-www-form-urlencoded,因为是表单数据 + // httpPost.setHeader("Content-Type", "application/x-www-form-urlencoded"); // UrlEncodedFormEntity 会自动设置 + + // 创建参数列表 + if (param != null && !param.isEmpty()) { + List paramList = new ArrayList<>(); + for (Map.Entry entry : param.entrySet()) { + paramList.add(new BasicNameValuePair(entry.getKey(), entry.getValue())); + } + UrlEncodedFormEntity entity = new UrlEncodedFormEntity(paramList, StandardCharsets.UTF_8); + httpPost.setEntity(entity); + } + + try (CloseableHttpResponse httpResponse = httpClient.execute(httpPost)) { + return handleResponse(httpResponse, url); + } + } catch (ClientProtocolException e) { + throw new RuntimeException("HTTP POST 请求协议错误 (MAP),URL: " + url, e); + } catch (IOException e) { + throw new RuntimeException("HTTP POST 请求 IO 错误 (MAP),URL: " + url, e); + } catch (ParseException e) { + throw new RuntimeException("HTTP POST 响应解析错误 (MAP),URL: " + url, e); + } + } + + /** + * 发送 HTTP POST 请求,请求体为 JsonObject。 + * Content-Type 为 application/json。 + * + * @param url 请求的 URL。 + * @param jsonObject 请求体内容,JsonObject 实例。 + * @return 响应体内容。 + * @throws RuntimeException 如果发生网络错误、协议错误或 HTTP 响应状态码非 2xx。 + */ + public static String postJSON(String url, JsonObject jsonObject) { + // 使用 try-with-resources 确保 HttpClient 和 HttpResponse 自动关闭 + try (CloseableHttpClient httpClient = HttpClients.createDefault()) { + HttpPost httpPost = new HttpPost(url); + httpPost.setConfig(buildRequestConfig()); // 设置请求配置 + addChromeHeaders(httpPost); // 添加 Chrome 头部 + + httpPost.setHeader("Content-Type", "application/json"); + httpPost.setHeader("Accept", "application/json"); // 明确接受 JSON 响应 + + StringEntity stringEntity = new StringEntity(jsonObject.toString(), StandardCharsets.UTF_8); + httpPost.setEntity(stringEntity); + + try (CloseableHttpResponse httpResponse = httpClient.execute(httpPost)) { + return handleResponse(httpResponse, url); + } + } catch (ClientProtocolException e) { + throw new RuntimeException("HTTP POST 请求协议错误 (JSON),URL: " + url, e); + } catch (IOException e) { + throw new RuntimeException("HTTP POST 请求 IO 错误 (JSON),URL: " + url, e); + } catch (ParseException e) { + throw new RuntimeException("HTTP POST 响应解析错误 (JSON),URL: " + url, e); + } + } + + /** + * 发送 HTTP GET 请求。 + * + * @param url 请求的 URL。 + * @param headers 额外的请求头部信息,可以覆盖默认的 Chrome 头部。 + * @return 响应体内容。 + * @throws RuntimeException 如果发生网络错误、协议错误或 HTTP 响应状态码非 2xx。 + */ + public static String get(String url, Map headers) { + // 使用 try-with-resources 确保 HttpClient 和 HttpResponse 自动关闭 + try (CloseableHttpClient httpClient = HttpClients.createDefault()) { + HttpGet httpGet = new HttpGet(url); + httpGet.setConfig(buildRequestConfig()); // 设置请求配置 + addChromeHeaders(httpGet); // 添加 Chrome 头部 + + // 添加或覆盖用户提供的头部 + if (headers != null && !headers.isEmpty()) { + headers.forEach(httpGet::addHeader); + } + + try (CloseableHttpResponse httpResponse = httpClient.execute(httpGet)) { + return handleResponse(httpResponse, url); + } + } catch (ClientProtocolException e) { + throw new RuntimeException("HTTP GET 请求协议错误,URL: " + url, e); + } catch (IOException e) { + throw new RuntimeException("HTTP GET 请求 IO 错误,URL: " + url, e); + } catch (ParseException e) { + throw new RuntimeException("HTTP GET 响应解析错误,URL: " + url, e); + } + } + + /** + * 处理 HTTP 响应,检查状态码并提取响应体。 + * + * @param httpResponse CloseableHttpResponse 实例。 + * @param url 请求的 URL。 + * @return 响应体内容。 + * @throws RuntimeException 如果响应状态码非 2xx 或响应实体为空。 + * @throws IOException 如果读取响应实体时发生 IO 错误。 + * @throws ParseException 如果解析响应实体时发生解析错误。 + */ + private static String handleResponse(CloseableHttpResponse httpResponse, String url) throws IOException, ParseException { + int statusCode = httpResponse.getStatusLine().getStatusCode(); + if (statusCode >= 200 && statusCode < 300) { // 2xx 表示成功 + HttpEntity responseEntity = httpResponse.getEntity(); + if (responseEntity != null) { + return EntityUtils.toString(responseEntity, StandardCharsets.UTF_8); + } else { + throw new RuntimeException("HTTP 请求成功,但响应实体为空。URL: " + url); + } + } else { + String errorResponse = ""; + if (httpResponse.getEntity() != null) { + try { + errorResponse = EntityUtils.toString(httpResponse.getEntity(), StandardCharsets.UTF_8); + } catch (IOException | ParseException e) { + // 忽略解析错误,只记录原始错误信息 + errorResponse = "无法解析错误响应体"; + } + } + throw new RuntimeException( + "HTTP 请求失败,状态码: " + statusCode + ", URL: " + url + ", 响应体: " + errorResponse); + } + } } diff --git a/shared/java/top/fpsmaster/utils/thirdparty/microsoft/MicrosoftLogin.java b/shared/java/top/fpsmaster/utils/thirdparty/microsoft/MicrosoftLogin.java index 2b6aecd1..8eac6e49 100644 --- a/shared/java/top/fpsmaster/utils/thirdparty/microsoft/MicrosoftLogin.java +++ b/shared/java/top/fpsmaster/utils/thirdparty/microsoft/MicrosoftLogin.java @@ -1,216 +1,386 @@ package top.fpsmaster.utils.thirdparty.microsoft; -import com.google.gson.GsonBuilder; import com.google.gson.JsonObject; +import com.google.gson.JsonParser; import com.sun.net.httpserver.HttpServer; +import net.minecraft.client.Minecraft; import net.minecraft.util.Session; -import org.apache.http.NameValuePair; -import org.apache.http.client.config.RequestConfig; -import org.apache.http.client.entity.UrlEncodedFormEntity; -import org.apache.http.client.methods.CloseableHttpResponse; -import org.apache.http.client.methods.HttpGet; -import org.apache.http.client.methods.HttpPost; -import org.apache.http.entity.StringEntity; -import org.apache.http.impl.client.CloseableHttpClient; -import org.apache.http.impl.client.HttpClients; -import org.apache.http.message.BasicNameValuePair; -import org.apache.http.util.EntityUtils; -import top.fpsmaster.ui.screens.account.GuiWaiting; import top.fpsmaster.interfaces.ProviderManager; +import top.fpsmaster.interfaces.game.IMinecraftProvider; +import top.fpsmaster.ui.screens.mainmenu.MainMenu; +import top.fpsmaster.utils.os.HttpRequest; -import java.awt.Desktop; +import java.awt.*; import java.io.IOException; +import java.io.OutputStream; import java.net.InetSocketAddress; import java.net.URI; +import java.net.URLEncoder; import java.nio.charset.StandardCharsets; -import java.util.ArrayList; import java.util.HashMap; -import java.util.List; +import java.util.LinkedHashMap; import java.util.Map; +import java.util.StringJoiner; +import java.util.concurrent.Executors; import java.util.concurrent.atomic.AtomicBoolean; +import static top.fpsmaster.utils.Utility.mc; + public class MicrosoftLogin { + public static String loginProgressMessage = "Waiting for login..."; + + // --- Configuration --- private static final String CLIENT_ID = "d1ed1b72-9f7c-41bc-9702-365d2cbd2e38"; + private static final int SERVER_PORT = 17342; + private static final String REDIRECT_URI = "http://127.0.0.1:" + SERVER_PORT; + private static final boolean DEBUG_MODE = false; + private static HttpServer httpServer; + private static final AtomicBoolean loginCompleted = new AtomicBoolean(false); + + /** + * Starts the local HTTP server to handle the Microsoft authentication redirect. + * This method should be called before opening the browser for login. + */ + public static void startLocalHttpServer() { + if (httpServer != null) { + logInfo("HTTP server is already running."); + return; + } - public static void start() { try { - GsonBuilder gsonBuilder = new GsonBuilder(); - httpServer = HttpServer.create(new InetSocketAddress(17342), 0); - System.out.println("Create login server"); + httpServer = HttpServer.create(new InetSocketAddress(SERVER_PORT), 0); + logInfo("Created login server on port " + SERVER_PORT); httpServer.createContext("/", exchange -> { - Map map = new HashMap<>(); - String requestURI = exchange.getRequestURI().toString(); - String result = "Login successfully! You can close this window now."; - exchange.sendResponseHeaders(200, result.length()); - exchange.getResponseBody().write(result.getBytes(StandardCharsets.UTF_8)); - httpServer.stop(3); - - String code = requestURI.substring(requestURI.indexOf("=") + 1); - map.put("client_id", CLIENT_ID); - map.put("code", code); - map.put("grant_type", "authorization_code"); - map.put("redirect_uri", "http://127.0.0.1:17342"); - - String oauthResponse = postMap(map); - String accessToken = gsonBuilder.create().fromJson(oauthResponse, JsonObject.class).get("access_token").getAsString(); - - Map map2 = new HashMap<>(); - map2.put("AuthMethod", "RPS"); - map2.put("SiteName", "user.auth.xboxlive.com"); - map2.put("RpsTicket", "d=" + accessToken); - - JsonObject jsonObject = new JsonObject(); - jsonObject.add("Properties", gsonBuilder.create().toJsonTree(map2)); - jsonObject.addProperty("RelyingParty", "http://auth.xboxlive.com"); - jsonObject.addProperty("TokenType", "JWT"); - - String xblResponse = postJson("https://user.auth.xboxlive.com/user/authenticate", jsonObject); - JsonObject xblJson = gsonBuilder.create().fromJson(xblResponse, JsonObject.class); - String xblToken = xblJson.get("Token").getAsString(); - String xstsResponse = authorizeWithXsts(gsonBuilder, xblToken); - - String xstsToken = gsonBuilder.create().fromJson(xstsResponse, JsonObject.class).get("Token").getAsString(); - String xstsUserHash = getXstsUserHash(xstsResponse); - - JsonObject properties = new JsonObject(); - properties.addProperty("identityToken", "XBL3.0 x=" + xstsUserHash + ";" + xstsToken); - String minecraftAuth = postJson("https://api.minecraftservices.com/authentication/login_with_xbox", properties); - JsonObject minecraftAuthJson = gsonBuilder.create().fromJson(minecraftAuth, JsonObject.class); - accessToken = minecraftAuthJson.get("access_token").getAsString(); - - // Get profile - Map profileMap = new HashMap<>(); - profileMap.put("Authorization", "Bearer " + accessToken); - String profile = getProfile(profileMap); - JsonObject profileJson = gsonBuilder.create().fromJson(profile, JsonObject.class); - String uuid = profileJson.get("id").getAsString(); - String name = profileJson.get("name").getAsString(); - - ProviderManager.mcProvider.setSession(new Session(name, uuid, accessToken, "mojang")); - GuiWaiting.loggedIn = true; + logInfo("New connection received on HTTP server."); + String responseMessage = "Authentication successful! You can close this tab."; + try (OutputStream responseBody = exchange.getResponseBody()) { + exchange.sendResponseHeaders(200, responseMessage.length()); + responseBody.write(responseMessage.getBytes(StandardCharsets.UTF_8)); + } catch (IOException e) { + logError("Error sending HTTP response: " + e.getMessage()); + } finally { + // Stop the server immediately after receiving the code + stopLocalHttpServer(); + } + + String requestUri = exchange.getRequestURI().toString(); + logDebug("Received request URI: " + requestUri); + + if (requestUri.contains("code=")) { + String code = requestUri.substring(requestUri.indexOf("=") + 1); + logInfo("Authorization code received. Starting token exchange..."); + try { + // Exchange authorization code for initial tokens + Map tokenRequestParams = new HashMap<>(); + tokenRequestParams.put("client_id", CLIENT_ID); + tokenRequestParams.put("code", code); + tokenRequestParams.put("grant_type", "authorization_code"); + tokenRequestParams.put("redirect_uri", REDIRECT_URI); + + String oauthResponse = HttpRequest.postMAP("https://login.live.com/oauth20_token.srf", tokenRequestParams); + logDebug("OAuth Response: " + oauthResponse); + JsonObject oauthJson = HttpRequest.gson().fromJson(oauthResponse, JsonObject.class); + String accessToken = getJsonString(oauthJson, "access_token", "OAuth access token"); + String refreshToken = getJsonString(oauthJson, "refresh_token", "OAuth refresh token"); + logInfo("OAuth Access Token obtained. (Refresh Token: " + (DEBUG_MODE ? refreshToken : "[HIDDEN]") + ")"); + + // Continue with Minecraft authentication using the obtained access token + continueMinecraftAuthentication(accessToken); + loginCompleted.set(true); + } catch (Exception e) { + logError("Error during login completion: " + e.getMessage()); + setStep("Login Failed. (error: " + e.getMessage() + ")"); + } + } else { + logError("No authorization code found in the redirect URI."); + setStep("Login failed. (no authorization code found in the redirect URI)"); + stopLocalHttpServer(); + } }); - httpServer.setExecutor(null); + // Use a single-thread executor for the HTTP server to avoid resource issues + httpServer.setExecutor(Executors.newSingleThreadExecutor()); httpServer.start(); + logInfo("HTTP server started successfully."); } catch (IOException e) { - e.printStackTrace(); + logError("Failed to start HTTP server: " + e.getMessage()); + setStep("Login failed. (error: " + e.getMessage() + ")"); + httpServer = null; // Ensure server is null if creation failed + throw new RuntimeException("Failed to start HTTP server for Microsoft login.", e); + } + } + + /** + * Stops the local HTTP server. + */ + public static void stopLocalHttpServer() { + if (httpServer != null) { + httpServer.stop(1); // Stop with a 1-second delay to allow current requests to finish + httpServer = null; + logInfo("HTTP server stopped."); } } - public static boolean login() { - AtomicBoolean flag = new AtomicBoolean(false); + /** + * Initiates the Microsoft login process by opening a browser window. + * This method will start a local HTTP server to listen for the redirect. + * + * @return true if the login process is successfully initiated (browser opened), false otherwise. + */ + public static boolean loginMicrosoft() { + startLocalHttpServer(); // Ensure the server is running before opening the browser + if (httpServer == null) { + logError("HTTP server failed to start. Cannot proceed with browser login."); + return false; + } + try { - Map map = new HashMap<>(); - map.put("client_id", CLIENT_ID); - map.put("response_type", "code"); - map.put("redirect_uri", "http://127.0.0.1:17342"); - map.put("scope", "XboxLive.signin%20XboxLive.offline_access"); - - String url = buildOAuthUrl(map); - start(); - Desktop.getDesktop().browse(URI.create(url)); + Map params = new HashMap<>(); + params.put("client_id", CLIENT_ID); + params.put("response_type", "code"); + params.put("redirect_uri", REDIRECT_URI); + params.put("scope", "XboxLive.signin offline_access"); + + String microsoftAuthUrl = buildUrl("https://login.live.com/oauth20_authorize.srf", params); + logInfo("Opening browser for Microsoft authentication: " + microsoftAuthUrl); + Desktop.getDesktop().browse(URI.create(microsoftAuthUrl)); + return true; } catch (IOException e) { - e.printStackTrace(); + logError("Failed to open browser for Microsoft login: " + e.getMessage()); + setStep("Login failed. (failed to open browser for Microsoft login)"); + stopLocalHttpServer(); // Stop server if browser can't be opened + return false; } - return flag.get(); } - private static String postMap(Map param) { - try (CloseableHttpClient httpClient = HttpClients.createDefault()) { - HttpPost httpPost = new HttpPost("https://login.live.com/oauth20_token.srf"); - if (param != null) { - List paramList = new ArrayList<>(); - for (Map.Entry entry : param.entrySet()) { - paramList.add(new BasicNameValuePair(entry.getKey(), entry.getValue())); - } - httpPost.setEntity(new UrlEncodedFormEntity(paramList)); - } + /** + * Continues the Minecraft authentication process using an Xbox Live access token. + * This method covers steps 2-5 of the original login flow: + * Xbox Live authentication, XSTS authorization, Minecraft authentication, and profile retrieval. + * + * @param xboxAccessToken The Xbox Live access token obtained from the initial OAuth flow or refresh token. + * @throws IOException If any HTTP request fails or authentication fails. + */ + private static void continueMinecraftAuthentication(String xboxAccessToken) throws IOException { + logInfo("Continuing Minecraft authentication flow..."); + + // 2. Authenticate with Xbox Live + setStep("Step 2/5: Authenticating with Xbox Live..."); + Map xboxAuthProperties = new HashMap<>(); + xboxAuthProperties.put("AuthMethod", "RPS"); + xboxAuthProperties.put("SiteName", "user.auth.xboxlive.com"); + xboxAuthProperties.put("RpsTicket", "d=" + xboxAccessToken); + + JsonObject xboxAuthPayload = new JsonObject(); + xboxAuthPayload.add("Properties", HttpRequest.gson().toJsonTree(xboxAuthProperties)); + xboxAuthPayload.addProperty("RelyingParty", "http://auth.xboxlive.com"); + xboxAuthPayload.addProperty("TokenType", "JWT"); + + String xboxAuthResponse = HttpRequest.postJSON("https://user.auth.xboxlive.com/user/authenticate", xboxAuthPayload); + logDebug("Xbox Auth Response: " + xboxAuthResponse); + JsonObject xboxAuthJson = HttpRequest.gson().fromJson(xboxAuthResponse, JsonObject.class); + String xblToken = getJsonString(xboxAuthJson, "Token", "XBL Token"); + String xblUserhash = xboxAuthJson.getAsJsonObject("DisplayClaims") + .getAsJsonArray("xui").get(0).getAsJsonObject() + .get("uhs").getAsString(); + logInfo("Xbox Live Token and Userhash obtained."); + + // 3. Authorize with XSTS + setStep("Step 3/5: Authorizing with XSTS service..."); + JsonObject xstsProperties = new JsonObject(); + xstsProperties.addProperty("SandboxId", "RETAIL"); + xstsProperties.add("UserTokens", HttpRequest.gson().toJsonTree(new String[]{xblToken})); - try (CloseableHttpResponse response = httpClient.execute(httpPost)) { - return EntityUtils.toString(response.getEntity(), "UTF-8"); + JsonObject xstsPayload = new JsonObject(); + xstsPayload.add("Properties", xstsProperties); + xstsPayload.addProperty("RelyingParty", "rp://api.minecraftservices.com/"); + xstsPayload.addProperty("TokenType", "JWT"); + + String xstsResponse = HttpRequest.postJSON("https://xsts.auth.xboxlive.com/xsts/authorize", xstsPayload); + logDebug("XSTS Response: " + xstsResponse); + JsonObject xstsJson = HttpRequest.gson().fromJson(xstsResponse, JsonObject.class); + + if (xstsJson.has("XErr")) { + long xErrCode = xstsJson.get("XErr").getAsLong(); + String message = xstsJson.has("Message") ? xstsJson.get("Message").getAsString() : "Unknown XSTS error."; + logError("XSTS Error: " + message + " (Code: " + xErrCode + ")"); + if (xErrCode == 2148916064L) { + logError("This typically means the account is a child account and requires adult verification."); + } else if (xErrCode == 2148916065L) { + logError("This usually means the account has not accepted the Xbox Live terms of service."); } - } catch (Exception e) { - e.printStackTrace(); + throw new IOException("XSTS authorization failed: " + message); } - return ""; + + String xstsToken = getJsonString(xstsJson, "Token", "XSTS Token"); + String xstsUserhash = xstsJson.getAsJsonObject("DisplayClaims") + .getAsJsonArray("xui").get(0).getAsJsonObject() + .get("uhs").getAsString(); + logInfo("XSTS Token and Userhash obtained."); + + // 4. Authenticate with Minecraft + setStep("Step 4/5: Authenticating with Minecraft services..."); + JsonObject minecraftAuthPayload = new JsonObject(); + minecraftAuthPayload.addProperty("identityToken", "XBL3.0 x=" + xstsUserhash + ";" + xstsToken); + + String minecraftAuthResponse = HttpRequest.postJSON("https://api.minecraftservices.com/authentication/login_with_xbox", minecraftAuthPayload); + logDebug("Minecraft Auth Response: " + minecraftAuthResponse); + JsonObject minecraftAuthJson = HttpRequest.gson().fromJson(minecraftAuthResponse, JsonObject.class); + String mcAccessToken = getJsonString(minecraftAuthJson, "access_token", "Minecraft access token"); + String mcUsername = getJsonString(minecraftAuthJson, "username", "Minecraft username"); // This is often the UUID, not the display name + logInfo("Minecraft Access Token obtained. Username: " + mcUsername); + + + // 5. Get Minecraft Profile + setStep("Step 5/5: Retrieving Minecraft profile..."); + Map profileHeaders = new HashMap<>(); + profileHeaders.put("Authorization", "Bearer " + mcAccessToken); + + String profileResponse = HttpRequest.get("https://api.minecraftservices.com/minecraft/profile", profileHeaders); + logDebug("Minecraft Profile Response: " + profileResponse); + JsonObject profileJson = HttpRequest.gson().fromJson(profileResponse, JsonObject.class); + + String uuid = getJsonString(profileJson, "id", "Minecraft UUID"); + String name = getJsonString(profileJson, "name", "Minecraft Username"); + boolean hasBoughtGame = profileJson.has("name") && profileJson.has("id"); // Simple check + + if (!hasBoughtGame) { + logError("Minecraft profile indicates game not owned or profile not found."); + throw new IOException("Minecraft account does not own the game or profile not found."); } - private static String getProfile(Map headers) { - try (CloseableHttpClient httpClient = HttpClients.createDefault()) { - HttpGet httpGet = new HttpGet("https://api.minecraftservices.com/minecraft/profile"); - RequestConfig requestConfig = RequestConfig.custom() - .setConnectTimeout(35000) - .setConnectionRequestTimeout(35000) - .setSocketTimeout(60000) - .build(); - httpGet.setConfig(requestConfig); - headers.forEach(httpGet::addHeader); - - try (CloseableHttpResponse response = httpClient.execute(httpGet)) { - return EntityUtils.toString(response.getEntity()); - } - } catch (Exception e) { - e.printStackTrace(); + logInfo("Successfully retrieved Minecraft profile - Name: " + name + ", UUID: " + uuid); + + // Set Minecraft Session + logInfo("Setting Minecraft session..."); + ProviderManager.mcProvider.setSession(new Session(name, uuid, mcAccessToken, "mojang")); + setStep("Minecraft session updated successfully!"); + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + mc.displayGuiScreen(new MainMenu()); + } + + /** + * Converts a map of parameters to a URL-encoded string. + * + * @param params The map of parameters. + * @return A URL-encoded string. + */ + private static String paramsToUrlEncoded(Map params) { + StringJoiner sj = new StringJoiner("&"); + for (Map.Entry entry : params.entrySet()) { + sj.add(urlEncode(entry.getKey()) + "=" + urlEncode(entry.getValue())); } - return ""; + return sj.toString(); + } + + /** + * Builds a URL with query parameters from a base URL and a map of parameters. + * + * @param baseUrl The base URL. + * @param params The map of parameters. + * @return The constructed URL. + */ + private static String buildUrl(String baseUrl, Map params) { + if (params.isEmpty()) { + return baseUrl; } + return baseUrl + "?" + paramsToUrlEncoded(params); + } - private static String postJson(String url, JsonObject jsonObject) { - try (CloseableHttpClient httpClient = HttpClients.createDefault()) { - HttpPost httpPost = new HttpPost(url); - RequestConfig requestConfig = RequestConfig.custom() - .setConnectTimeout(35000) - .setConnectionRequestTimeout(35000) - .setSocketTimeout(60000) - .build(); - httpPost.setConfig(requestConfig); - httpPost.addHeader("Content-Type", "application/json"); - httpPost.addHeader("Accept", "application/json"); - httpPost.setEntity(new StringEntity(jsonObject.toString())); - - try (CloseableHttpResponse response = httpClient.execute(httpPost)) { - return EntityUtils.toString(response.getEntity()); - } - } catch (Exception e) { - e.printStackTrace(); + /** + * URL-encodes a string. + * + * @param value The string to encode. + * @return The URL-encoded string. + */ + private static String urlEncode(String value) { + try { + return URLEncoder.encode(value, StandardCharsets.UTF_8.toString()); + } catch (Exception e) { + logError("Failed to URL encode: " + value + " - " + e.getMessage()); + return value; // Fallback to unencoded if encoding fails } - return ""; + } + + /** + * Safely retrieves a string value from a JsonObject. + * + * @param jsonObject The JsonObject. + * @param key The key to retrieve. + * @param fieldName A user-friendly name for the field (for logging). + * @return The string value. + * @throws IOException If the key is not found or is not a string. + */ + private static String getJsonString(JsonObject jsonObject, String key, String fieldName) throws IOException { + if (jsonObject == null || !jsonObject.has(key) || !jsonObject.get(key).isJsonPrimitive()) { + logError("Missing or invalid field in JSON response: " + fieldName + " (key: " + key + ")"); + throw new IOException("Missing or invalid field in JSON response: " + fieldName); } + return jsonObject.get(key).getAsString(); + } - private static String buildOAuthUrl(Map map) { - StringBuilder sb = new StringBuilder("https://login.live.com/oauth20_authorize.srf"); - if (!map.isEmpty()) { - sb.append("?"); - for (Map.Entry entry : map.entrySet()) { - sb.append(entry.getKey()).append("=").append(entry.getValue()).append("&"); - } - sb.deleteCharAt(sb.length() - 1); + // --- Logging Utilities --- + + private static void logInfo(String message) { + System.out.println("[MicrosoftLogin INFO] " + message); + } + + private static void logDebug(String message) { + if (DEBUG_MODE) { + System.out.println("[MicrosoftLogin DEBUG] " + message); } - return sb.toString(); } - private static String authorizeWithXsts(GsonBuilder gsonBuilder, String xblToken) { - JsonObject jo2 = new JsonObject(); - JsonObject jop = new JsonObject(); - jop.addProperty("SandboxId", "RETAIL"); - jop.add("UserTokens", gsonBuilder.create().toJsonTree(new String[]{xblToken})); - jo2.add("Properties", jop); - jo2.addProperty("RelyingParty", "rp://api.minecraftservices.com/"); - jo2.addProperty("TokenType", "JWT"); + private static void logError(String message) { + System.err.println("[MicrosoftLogin ERROR] " + message); + } + + - return postJson("https://xsts.auth.xboxlive.com/xsts/authorize", jo2); + public static void loginViaBrowser() { + try { + logInfo("Starting Microsoft login process..."); + setStep("Step 1/5: Retrieving accessToken from browser..."); + boolean initiated = loginMicrosoft(); + if (initiated) { + logInfo("Browser opened. Waiting for login completion..."); + long startTime = System.currentTimeMillis(); + long timeout = 120 * 1000; // 2 minutes timeout + while (!loginCompleted.get() && (System.currentTimeMillis() - startTime < timeout)) { + try { + Thread.sleep(1000); // Wait 1 second + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + logError("Login wait interrupted: " + e.getMessage()); + setStep("Login wait interrupted"); + break; + } + } + if (loginCompleted.get()) { + logInfo("Login process finished."); + } else { + logError("Login timed out or did not complete."); + } + } else { + logError("Failed to initiate browser login."); + } + } catch (Exception e) { + logError("An unexpected error occurred in main: " + e.getMessage()); + e.printStackTrace(); + } finally { + stopLocalHttpServer(); // Ensure server is stopped on exit + } } - private static String getXstsUserHash(String xstsResponse) { - JsonObject xstsJson = new GsonBuilder().create().fromJson(xstsResponse, JsonObject.class); - return xstsJson.getAsJsonObject("DisplayClaims") - .getAsJsonArray("xui") - .get(0) - .getAsJsonObject() - .get("uhs") - .getAsString(); + public static void setStep(String step) { + logInfo(step); + loginProgressMessage = step; } -} +} \ No newline at end of file diff --git a/shared/resources/assets/minecraft/client/lang/zh_cn.lang b/shared/resources/assets/minecraft/client/lang/zh_cn.lang index 8c11c66f..73874792 100644 --- a/shared/resources/assets/minecraft/client/lang/zh_cn.lang +++ b/shared/resources/assets/minecraft/client/lang/zh_cn.lang @@ -47,7 +47,6 @@ oobe.done.desc=欢迎使用 oobe.done.start=开始 microsoft.login.title=正在登录微软账号 -microsoft.login.desc=请前往浏览器继续操作 # 功能 armordisplay=护甲显示 From a4848029dd319043f3e8b208e6a27ae8300b053f Mon Sep 17 00:00:00 2001 From: SuperSkidder Date: Thu, 12 Jun 2025 13:13:54 +0800 Subject: [PATCH 042/193] feat: improve clickgui fix: bind setting wro ng position --- .../top/fpsmaster/modules/lua/LuaManager.java | 6 +++++- .../top/fpsmaster/ui/click/CategoryComponent.java | 2 +- shared/java/top/fpsmaster/ui/click/MainPanel.java | 6 +++--- .../ui/click/modules/ModuleRenderer.java | 15 ++++++++++++--- .../ui/click/modules/impl/BindSettingRender.java | 9 +++++---- .../click/modules/impl/BooleanSettingRender.java | 4 ++-- .../click/modules/impl/NumberSettingRender.java | 5 +++-- .../top/fpsmaster/utils/render/Render2DUtils.java | 4 ++++ 8 files changed, 35 insertions(+), 16 deletions(-) diff --git a/shared/java/top/fpsmaster/modules/lua/LuaManager.java b/shared/java/top/fpsmaster/modules/lua/LuaManager.java index 2d5a970d..1b159512 100644 --- a/shared/java/top/fpsmaster/modules/lua/LuaManager.java +++ b/shared/java/top/fpsmaster/modules/lua/LuaManager.java @@ -15,6 +15,7 @@ import top.fpsmaster.utils.Utility; import top.fpsmaster.utils.os.FileUtils; import top.fpsmaster.utils.render.Render2DUtils; +import top.fpsmaster.wrapper.MinecraftProvider; import top.fpsmaster.wrapper.blockpos.WrapperBlockPos; import java.awt.*; @@ -102,10 +103,13 @@ public static LuaScript loadLua(RawLua rawLua) { double posX = ProviderManager.mcProvider.getPlayer().posX; double posY = ProviderManager.mcProvider.getPlayer().posY; double posZ = ProviderManager.mcProvider.getPlayer().posZ; + boolean onGround = ProviderManager.mcProvider.getPlayer().onGround; + lua.push(posX); lua.push(posY); lua.push(posZ); - return 3; + lua.push(onGround); + return 4; }); lua.setGlobal("getPlayerPosition"); diff --git a/shared/java/top/fpsmaster/ui/click/CategoryComponent.java b/shared/java/top/fpsmaster/ui/click/CategoryComponent.java index 51a481fe..e24550f5 100644 --- a/shared/java/top/fpsmaster/ui/click/CategoryComponent.java +++ b/shared/java/top/fpsmaster/ui/click/CategoryComponent.java @@ -31,7 +31,7 @@ public void render(float x, float y, float width, float height, float mouseX, fl Render2DUtils.drawImage( new ResourceLocation("client/gui/settings/icons/" + category.name().toLowerCase() + ".png"), - x + 10, + x + 9, y, 12f, 12f, diff --git a/shared/java/top/fpsmaster/ui/click/MainPanel.java b/shared/java/top/fpsmaster/ui/click/MainPanel.java index b1981f7b..1a6694e9 100644 --- a/shared/java/top/fpsmaster/ui/click/MainPanel.java +++ b/shared/java/top/fpsmaster/ui/click/MainPanel.java @@ -117,7 +117,7 @@ public void render(int mouseX, int mouseY, float partialTicks) { GlStateManager.translate(-guiWidth / 2.0, -height / 2.0, 0.0); - backgroundColor.base(new Color(10, 10, 10, 180)); + backgroundColor.base(new Color(0, 0, 0, 150)); Render2DUtils.drawBlurArea((int) (x + leftWidth), y, (int) (width - leftWidth), (int) height, 3, backgroundColor.getColor()); Render2DUtils.drawOptimizedRoundedRect( x + leftWidth, @@ -172,7 +172,7 @@ public void render(int mouseX, int mouseY, float partialTicks) { ); } - FPSMaster.fontManager.s24.drawStringWithShadow(FPSMaster.i18n.get("category." + curType.name().toLowerCase(Locale.getDefault())), x + leftWidth + 10, y + 9, -1); + FPSMaster.fontManager.s24.drawStringWithShadow(FPSMaster.i18n.get("category." + curType.name().toLowerCase(Locale.getDefault())), x + leftWidth + 10, y + 5, -1); GL11.glEnable(GL11.GL_SCISSOR_TEST); Render2DUtils.doGlScissor( @@ -242,7 +242,7 @@ public void render(int mouseX, int mouseY, float partialTicks) { float my = y + 60; Render2DUtils.drawOptimizedRoundedRect( - x + 5 + categoryAnimation / 50f, + x + 4 + categoryAnimation / 50f, selection - 6, categoryAnimation - 8, 22f, diff --git a/shared/java/top/fpsmaster/ui/click/modules/ModuleRenderer.java b/shared/java/top/fpsmaster/ui/click/modules/ModuleRenderer.java index 4c430679..41e55834 100644 --- a/shared/java/top/fpsmaster/ui/click/modules/ModuleRenderer.java +++ b/shared/java/top/fpsmaster/ui/click/modules/ModuleRenderer.java @@ -61,10 +61,10 @@ public void render(float x, float y, float width, float height, float mouseX, fl if (mod.isEnabled()) { content.start(content.getColor(), FPSMaster.theme.getModuleTextEnabled(), 0.2f, Type.EASE_IN_OUT_QUAD); - background.start(background.getColor(), FPSMaster.theme.getModuleEnabled(), 0.2f, Type.EASE_IN_OUT_QUAD); + background.start(background.getColor(), new Color(150,150,150,60), 0.2f, Type.EASE_IN_OUT_QUAD); } else { content.start(content.getColor(), FPSMaster.theme.getModuleTextDisabled(), 0.2f, Type.EASE_IN_OUT_QUAD); - background.start(background.getColor(), FPSMaster.theme.getModuleDisabled(), 0.2f, Type.EASE_IN_OUT_QUAD); + background.start(background.getColor(), new Color(100,100,100,60), 0.2f, Type.EASE_IN_OUT_QUAD); } Render2DUtils.drawOptimizedRoundedRect( @@ -73,7 +73,16 @@ public void render(float x, float y, float width, float height, float mouseX, fl width - 10, settingHeight + 37f, 10, - new Color(100, 100, 100, 60).getRGB() + new Color(100,100,100,60).getRGB() + ); + + Render2DUtils.drawOptimizedRoundedRect( + x + 5, + y, + width - 10, + 37f, + 10, + background.getColor().getRGB() ); // Render2DUtils.drawOptimizedRoundedBorderRect( diff --git a/shared/java/top/fpsmaster/ui/click/modules/impl/BindSettingRender.java b/shared/java/top/fpsmaster/ui/click/modules/impl/BindSettingRender.java index e1c4791a..9d681650 100644 --- a/shared/java/top/fpsmaster/ui/click/modules/impl/BindSettingRender.java +++ b/shared/java/top/fpsmaster/ui/click/modules/impl/BindSettingRender.java @@ -11,6 +11,7 @@ import top.fpsmaster.utils.math.animation.ColorAnimation; import top.fpsmaster.utils.render.Render2DUtils; +import java.awt.*; import java.util.Locale; public class BindSettingRender extends SettingRender { @@ -36,15 +37,15 @@ public void render(float x, float y, float width, float height, float mouseX, fl y - 0.5f, width1 + 1, 13f, - FPSMaster.theme.getModeBoxBorder() + new Color(0,0,0,80) ); } Render2DUtils.drawOptimizedRoundedRect(x + 15 + fw, y, width1, 12f, colorAnimation.getColor()); s16b.drawString(keyName, x + 18 + fw, y + 2, FPSMaster.theme.getTextColorTitle().getRGB()); if (MainPanel.bindLock.equals(setting.name)) { - colorAnimation.base(FPSMaster.theme.getModeBoxBorder()); + colorAnimation.base(new Color(255,255,255,80)); } else { - colorAnimation.base(FPSMaster.theme.getModeBox()); + colorAnimation.base(new Color(0,0,0,80)); } this.height = 16f; } @@ -57,7 +58,7 @@ public void mouseClick(float x, float y, float width, float height, float mouseX String keyName = Keyboard.getKeyName(setting.value); UFontRenderer s16b = FPSMaster.fontManager.s16; if (Render2DUtils.isHovered( - x + 12 + fw, + x + 25 + fw, y, 10f + s16b.getStringWidth(keyName), 12f, diff --git a/shared/java/top/fpsmaster/ui/click/modules/impl/BooleanSettingRender.java b/shared/java/top/fpsmaster/ui/click/modules/impl/BooleanSettingRender.java index 2946cada..3c865a0a 100644 --- a/shared/java/top/fpsmaster/ui/click/modules/impl/BooleanSettingRender.java +++ b/shared/java/top/fpsmaster/ui/click/modules/impl/BooleanSettingRender.java @@ -25,9 +25,9 @@ public BooleanSettingRender(Module mod, BooleanSetting setting) { public void render(float x, float y, float width, float height, float mouseX, float mouseY, boolean custom) { box.update(); if (setting.getValue()) { - box.start(box.getColor(), FPSMaster.theme.getPrimary(), 0.2f, Type.EASE_IN_OUT_QUAD); + box.start(box.getColor(), new Color(255, 255, 255), 0.2f, Type.EASE_IN_OUT_QUAD); } else { - box.start(box.getColor(), FPSMaster.theme.getCheckboxBox(), 0.2f, Type.EASE_IN_OUT_QUAD); + box.start(box.getColor(), new Color(129, 129, 129), 0.2f, Type.EASE_IN_OUT_QUAD); } Render2DUtils.drawOptimizedRoundedRect(x + 14, y + 3, 6f, 6f, 3, box.getColor().getRGB()); FPSMaster.fontManager.s16.drawString( diff --git a/shared/java/top/fpsmaster/ui/click/modules/impl/NumberSettingRender.java b/shared/java/top/fpsmaster/ui/click/modules/impl/NumberSettingRender.java index def1029f..a3dffa9b 100644 --- a/shared/java/top/fpsmaster/ui/click/modules/impl/NumberSettingRender.java +++ b/shared/java/top/fpsmaster/ui/click/modules/impl/NumberSettingRender.java @@ -9,6 +9,7 @@ import top.fpsmaster.utils.math.animation.AnimationUtils; import top.fpsmaster.utils.render.Render2DUtils; +import java.awt.*; import java.util.Locale; public class NumberSettingRender extends SettingRender { @@ -27,10 +28,10 @@ public void render(float x, float y, float width, float height, float mouseX, fl FPSMaster.i18n.get((mod.name + "." + setting.name).toLowerCase(Locale.getDefault())), x + 10, y + 2, FPSMaster.theme.getTextColorDescription().getRGB() ); - Render2DUtils.drawOptimizedRoundedRect(x + 16 + fw, y + 3, 160f, 6f, FPSMaster.theme.getFrontBackground().getRGB()); + Render2DUtils.drawOptimizedRoundedRect(x + 16 + fw, y + 3, 160f, 6f, new Color(0,0,0,80)); float percent = (setting.getValue().floatValue() - setting.min.floatValue()) / (setting.max.floatValue() - setting.min.floatValue()); aWidth = (float) AnimationUtils.base(aWidth, 160 * percent, 0.2); - Render2DUtils.drawOptimizedRoundedRect(x + 16 + fw, y + 3, aWidth, 6f, FPSMaster.theme.getPrimary().getRGB()); + Render2DUtils.drawOptimizedRoundedRect(x + 16 + fw, y + 3, aWidth, 6f, -1); FPSMaster.fontManager.s16.drawString( setting.getValue().toString(), x + fw + 20 + 160, diff --git a/shared/java/top/fpsmaster/utils/render/Render2DUtils.java b/shared/java/top/fpsmaster/utils/render/Render2DUtils.java index 34e726fd..57f4db36 100644 --- a/shared/java/top/fpsmaster/utils/render/Render2DUtils.java +++ b/shared/java/top/fpsmaster/utils/render/Render2DUtils.java @@ -237,6 +237,10 @@ public static void endBlend() { } public static void drawBlurArea(int x, int y, int width, int height, int radius, Color color) { + drawBlurArea((float) x, y, width, height, radius, color); + } + + public static void drawBlurArea(float x, float y, float width, float height, int radius, Color color) { StencilUtil.initStencilToWrite(); RoundedUtil.drawRound(x, y, width, height, radius, true, color); StencilUtil.readStencilBuffer(1); From f5857ff36acb22fed02ce8d6b2a4f7dc2d447e78 Mon Sep 17 00:00:00 2001 From: vlouboos Date: Thu, 12 Jun 2025 15:39:53 +0800 Subject: [PATCH 043/193] Fix Scoreboard & Zoom --- .../forge/mixin/MixinEntityRenderer.java | 65 ++++++++++++++----- .../wrapper/mods/WrapperScoreboard.java | 46 ++++++++----- 2 files changed, 80 insertions(+), 31 deletions(-) diff --git a/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinEntityRenderer.java b/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinEntityRenderer.java index d6fadd0f..55ed8dd0 100644 --- a/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinEntityRenderer.java +++ b/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinEntityRenderer.java @@ -39,6 +39,7 @@ @Mixin(EntityRenderer.class) public abstract class MixinEntityRenderer { private float screenScale = -1; + private float screenScale2 = -1; @Inject(method = "renderWorldPass", at = @At(value = "FIELD", target = "Lnet/minecraft/client/renderer/EntityRenderer;renderHand:Z", shift = At.Shift.BEFORE)) private void renderWorldPass(int pass, float partialTicks, long finishTimeNano, CallbackInfo callbackInfo) { @@ -77,27 +78,59 @@ private void getFOVModifier(float partialTicks, boolean useFOVSetting, CallbackI f *= this.fovModifierHandPrev + (this.fovModifierHand - this.fovModifierHandPrev) * partialTicks; } + if (useFOVSetting) { + if (screenScale == -1 || Double.isNaN(screenScale)) { + screenScale = f; + } + } else { + if (screenScale2 == -1 || Double.isNaN(screenScale2)) { + screenScale2 = f; + } + } + if (SmoothZoom.zoom) { + if (useFOVSetting) { + if (SmoothZoom.smoothCamera.getValue()) { + screenScale = MathUtils.decreasedSpeed(screenScale, f, f / 4.0F, SmoothZoom.speed.getValue().floatValue() / (float) Minecraft.getDebugFPS() * 150.0f); + } else { + screenScale = f / 4.0F; + } + } else { + if (SmoothZoom.smoothCamera.getValue()) { + screenScale2 = MathUtils.decreasedSpeed(screenScale2, f, f / 4.0F, SmoothZoom.speed.getValue().floatValue() / (float) Minecraft.getDebugFPS() * 150.0f); + } else { + screenScale2 = f / 4.0F; + } + } + } + + if (!SmoothZoom.zoom) { + if (useFOVSetting) { + if (SmoothZoom.smoothCamera.getValue()) { + screenScale = MathUtils.decreasedSpeed(screenScale, f / 4.0F, f, SmoothZoom.speed.getValue().floatValue() / (float) Minecraft.getDebugFPS() * 150.0f); + } else { + screenScale = f; + } + } else { + if (SmoothZoom.smoothCamera.getValue()) { + screenScale2 = MathUtils.decreasedSpeed(screenScale2, f / 4.0F, f, SmoothZoom.speed.getValue().floatValue() / (float) Minecraft.getDebugFPS() * 150.0f); + } else { + screenScale2 = f; + } + } + } + + float screenScale = useFOVSetting ? this.screenScale : this.screenScale2; + if (entity instanceof EntityLivingBase && ((EntityLivingBase) entity).getHealth() <= 0.0F) { float f1 = (float) ((EntityLivingBase) entity).deathTime + partialTicks; - f /= (1.0F - 500.0F / (f1 + 500.0F)) * 2.0F + 1.0F; + screenScale /= (1.0F - 500.0F / (f1 + 500.0F)) * 2.0F + 1.0F; } + assert entity != null; Block block = ActiveRenderInfo.getBlockAtEntityViewpoint(mc.theWorld, entity, partialTicks); - if (block.getMaterial() == Material.water) { - f = f * 60.0F / 70.0F; - } - - if (screenScale == -1) - screenScale = f; - if (SmoothZoom.using && SmoothZoom.zoom) { - if (SmoothZoom.smoothCamera.getValue()) { - screenScale = MathUtils.decreasedSpeed(screenScale, f, f / 4.0F, SmoothZoom.speed.getValue().floatValue() / (float) Minecraft.getDebugFPS() * 150.0f); - } else { - screenScale = f / 4.0F; - } - } else { - screenScale = f; + if (block.getMaterial() == Material.water) { + screenScale = screenScale * 60.0F / 70.0F; } cir.setReturnValue(ForgeHooksClient.getFOVModifier((EntityRenderer) (Object) this, entity, block, partialTicks, screenScale)); @@ -161,7 +194,7 @@ private void orientCamera(float partialTicks) { this.partialTicks = partialTicks; float f = entity.getEyeHeight(); - if (mc.getRenderViewEntity() == mc.thePlayer && OldAnimations.using){ + if (mc.getRenderViewEntity() == mc.thePlayer && OldAnimations.using) { f = OldAnimations.getClientEyeHeight(partialTicks); } double d0 = entity.prevPosX + (entity.posX - entity.prevPosX) * (double) partialTicks; diff --git a/v1.8.9/src/main/java/top/fpsmaster/wrapper/mods/WrapperScoreboard.java b/v1.8.9/src/main/java/top/fpsmaster/wrapper/mods/WrapperScoreboard.java index 7e08bc8b..07b18e6f 100644 --- a/v1.8.9/src/main/java/top/fpsmaster/wrapper/mods/WrapperScoreboard.java +++ b/v1.8.9/src/main/java/top/fpsmaster/wrapper/mods/WrapperScoreboard.java @@ -10,10 +10,8 @@ import top.fpsmaster.features.impl.InterfaceModule; import top.fpsmaster.features.impl.interfaces.Scoreboard; import top.fpsmaster.ui.custom.impl.ScoreboardComponent; -import top.fpsmaster.utils.render.Render2DUtils; import top.fpsmaster.interfaces.ProviderManager; import top.fpsmaster.wrapper.TextFormattingProvider; -import top.fpsmaster.wrapper.WorldClientProvider; import java.util.Collection; import java.util.List; @@ -27,7 +25,6 @@ public static float[] render(ScoreboardComponent scoreboardComponent, InterfaceM UFontRenderer s16 = FPSMaster.fontManager.s16; - if (scoreplayerteam != null) { int i1 = scoreboard.getPlayersTeamColorIndex(ProviderManager.mcProvider.getPlayer().getName()); @@ -41,7 +38,7 @@ public static float[] render(ScoreboardComponent scoreboardComponent, InterfaceM if (objective != null) { Collection collection = scoreboard.getSortedScores(objective); - List list = collection.stream().filter(p_apply_1_ -> !p_apply_1_.getPlayerName().startsWith("#")).collect(Collectors.toList()); + List list = collection.stream().filter(score -> !score.getPlayerName().startsWith("#")).collect(Collectors.toList()); if (list.size() > 15) { collection = Lists.newArrayList(Iterables.skip(list, collection.size() - 15)); @@ -58,7 +55,7 @@ public static float[] render(ScoreboardComponent scoreboardComponent, InterfaceM for (Score score : collection) { ScorePlayerTeam scoreteam = scoreboard.getPlayersTeam(score.getPlayerName()); - String s = ScorePlayerTeam.formatPlayerName(scoreteam, score.getPlayerName()) + ": " + TextFormattingProvider.getRed() + score.getScorePoints(); + String s = filterHypixelIllegalCharacters(ScorePlayerTeam.formatPlayerName(scoreteam, score.getPlayerName()) + ": " + TextFormattingProvider.getRed() + score.getScorePoints()); if (mod.betterFont.getValue()) { i = Math.max(i, s16.getStringWidth(s)); } else { @@ -68,39 +65,38 @@ public static float[] render(ScoreboardComponent scoreboardComponent, InterfaceM i += 6; int height1 = 10; - float l1 = x; int j = 0; float h = collection.size() * height1 + 10; - scoreboardComponent.drawRect(l1, y, i, h, mod.backgroundColor.getColor()); + scoreboardComponent.drawRect(x, y, i, h, mod.backgroundColor.getColor()); for (Score score1 : collection) { ++j; ScorePlayerTeam scoreplayerteam1 = scoreboard.getPlayersTeam(score1.getPlayerName()); - String s1 = ScorePlayerTeam.formatPlayerName(scoreplayerteam1, score1.getPlayerName()); + String s1 = filterHypixelIllegalCharacters(ScorePlayerTeam.formatPlayerName(scoreplayerteam1, score1.getPlayerName())); float k = j * height1; // title if (j == collection.size()) { String s3 = objective.getDisplayName(); - scoreboardComponent.drawRect(l1, y, i, height1 + 1, mod.backgroundColor.getColor()); + scoreboardComponent.drawRect(x, y, i, height1 + 1, mod.backgroundColor.getColor()); if (mod.betterFont.getValue()) { - scoreboardComponent.drawString(16, s3, (int) (l1 + 2 + (float) i / 2 - s16.getStringWidth(s3) / 2f), y, -1); + scoreboardComponent.drawString(16, s3, (int) (x + 2 + (float) i / 2 - s16.getStringWidth(s3) / 2f), y, -1); } else { - ProviderManager.mcProvider.getFontRenderer().drawStringWithShadow(s3, (int) (l1 + 2 + (float) i / 2 - ProviderManager.mcProvider.getFontRenderer().getStringWidth(s3) / 2f), y, -1); + ProviderManager.mcProvider.getFontRenderer().drawStringWithShadow(s3, (int) (x + 2 + (float) i / 2 - ProviderManager.mcProvider.getFontRenderer().getStringWidth(s3) / 2f), y, -1); } } if (mod.betterFont.getValue()) { - scoreboardComponent.drawString(16, s1, ((int) l1) + 2, (int) (y + h - k), -1); + scoreboardComponent.drawString(16, s1, ((int) x) + 2, (int) (y + h - k), -1); } else { - ProviderManager.mcProvider.getFontRenderer().drawStringWithShadow(s1, ((int) l1) + 2, (int) (y + h - k), -1); + ProviderManager.mcProvider.getFontRenderer().drawStringWithShadow(s1, ((int) x) + 2, (int) (y + h - k), -1); } // 红字 if (Scoreboard.score.getValue()) { String s2 = TextFormattingProvider.getRed() + String.valueOf(score1.getScorePoints()); if (mod.betterFont.getValue()) { - scoreboardComponent.drawString(16, s2, l1 + i - 2 - s16.getStringWidth(s2), y + k, -1); + scoreboardComponent.drawString(16, s2, x + i - 2 - s16.getStringWidth(s2), y + k, -1); } else { - ProviderManager.mcProvider.getFontRenderer().drawStringWithShadow(s2, l1 + i - 2 - ProviderManager.mcProvider.getFontRenderer().getStringWidth(s2), y + k, -1); + ProviderManager.mcProvider.getFontRenderer().drawStringWithShadow(s2, x + i - 2 - ProviderManager.mcProvider.getFontRenderer().getStringWidth(s2), y + k, -1); } } } @@ -108,4 +104,24 @@ public static float[] render(ScoreboardComponent scoreboardComponent, InterfaceM } return new float[]{100, 120}; } + + + + public static String filterHypixelIllegalCharacters(String text) { + boolean dangerous = false; + StringBuilder stringBuilder = new StringBuilder(); + for (char c : text.toCharArray()) { + if (c == '\ud83c' || c == '\ud83d') { + dangerous = true; + continue; + } + if (dangerous) { + dangerous = false; + continue; + } + if (c == '⚽') continue; + stringBuilder.append(c); + } + return stringBuilder.toString(); + } } From 30723261e5d2b437fa585f6cf87a18b809888207 Mon Sep 17 00:00:00 2001 From: SuperSkidder Date: Thu, 12 Jun 2025 16:08:59 +0800 Subject: [PATCH 044/193] feat: ui improvements --- .../top/fpsmaster/ui/click/MainPanel.java | 74 +++++++++---------- .../fpsmaster/ui/click/music/MusicPanel.java | 20 ++--- .../fpsmaster/ui/click/music/SearchBox.java | 6 +- .../ui/screens/mainmenu/MainMenu.java | 2 +- .../ui/screens/oobe/impls/Login.java | 1 + 5 files changed, 52 insertions(+), 51 deletions(-) diff --git a/shared/java/top/fpsmaster/ui/click/MainPanel.java b/shared/java/top/fpsmaster/ui/click/MainPanel.java index 1a6694e9..7cec0ba8 100644 --- a/shared/java/top/fpsmaster/ui/click/MainPanel.java +++ b/shared/java/top/fpsmaster/ui/click/MainPanel.java @@ -145,34 +145,33 @@ public void render(int mouseX, int mouseY, float partialTicks) { // sizeDragBorder.update(); - if (Render2DUtils.isHoveredWithoutScale( - x + width - 10, - y + height - 10, - 10f, - 10f, - mouseX, - mouseY - )) { - Render2DUtils.drawImage( - new ResourceLocation("client/gui/settings/drag.png"), - x + width - 5, - y + height - 5, - 5f, - 5f, - new Color(255, 255, 255) - ); - } else { - Render2DUtils.drawImage( - new ResourceLocation("client/gui/settings/drag.png"), - x + width - 5, - y + height - 5, - 5f, - 5f, - new Color(200, 200, 200) - ); - } +// if (Render2DUtils.isHoveredWithoutScale( +// x + width - 10, +// y + height - 10, +// 10f, +// 10f, +// mouseX, +// mouseY +// )) { +// Render2DUtils.drawImage( +// new ResourceLocation("client/gui/settings/drag.png"), +// x + width - 5, +// y + height - 5, +// 5f, +// 5f, +// new Color(255, 255, 255) +// ); +// } else { +// Render2DUtils.drawImage( +// new ResourceLocation("client/gui/settings/drag.png"), +// x + width - 5, +// y + height - 5, +// 5f, +// 5f, +// new Color(200, 200, 200) +// ); +// } - FPSMaster.fontManager.s24.drawStringWithShadow(FPSMaster.i18n.get("category." + curType.name().toLowerCase(Locale.getDefault())), x + leftWidth + 10, y + 5, -1); GL11.glEnable(GL11.GL_SCISSOR_TEST); Render2DUtils.doGlScissor( @@ -186,12 +185,13 @@ public void render(int mouseX, int mouseY, float partialTicks) { if (curType == Category.Music) { MusicPanel.draw(x + leftWidth, y, width - leftWidth, height, mouseX, mouseY, scaleFactor); } else { + FPSMaster.fontManager.s24.drawStringWithShadow(FPSMaster.i18n.get("category." + curType.name().toLowerCase(Locale.getDefault())), x + leftWidth + 10, y + 5, -1); + modHeight = 20f; float containerWidth = width - leftWidth - 10; int finalMouseY = mouseY; modsContainer.draw(x + leftWidth, y + 25f, containerWidth, height - 20f, mouseX, mouseY, () -> { float modsY = y + 22f; - for (ModuleRenderer m : mods) { if (m.mod.category == curType) { float moduleY = modsY + modsContainer.getScroll(); @@ -352,21 +352,21 @@ public void onClick(int mouseX, int mouseY, int mouseButton) { if (!Render2DUtils.isHoveredWithoutScale(x, y, width, height, mouseX, mouseY)) return; if (mouseButton == 0 && Render2DUtils.isHoveredWithoutScale( - x, y, leftWidth, 34f, mouseX, mouseY + x + leftWidth, y, width - leftWidth, 20f, mouseX, mouseY )) { drag = true; dragX = mouseX - x; dragY = mouseY - y; } - if (mouseButton == 0 && Render2DUtils.isHoveredWithoutScale( - x + width - 20, y + height - 20, 20f, 20f, mouseX, mouseY - ) && "null".equals(dragLock)) { - sizeDrag = true; - dragLock = "sizeDrag"; - sizeDragX = x + width - mouseX; - sizeDragY = y + height - mouseY; - } +// if (mouseButton == 0 && Render2DUtils.isHoveredWithoutScale( +// x + width - 20, y + height - 20, 20f, 20f, mouseX, mouseY +// ) && "null".equals(dragLock)) { +// sizeDrag = true; +// dragLock = "sizeDrag"; +// sizeDragX = x + width - mouseX; +// sizeDragY = y + height - mouseY; +// } float my = y + 60f; for (Category c : Category.values()) { diff --git a/shared/java/top/fpsmaster/ui/click/music/MusicPanel.java b/shared/java/top/fpsmaster/ui/click/music/MusicPanel.java index 8f3fc779..dd3dee21 100644 --- a/shared/java/top/fpsmaster/ui/click/music/MusicPanel.java +++ b/shared/java/top/fpsmaster/ui/click/music/MusicPanel.java @@ -238,14 +238,14 @@ public static void draw(float x, float y, float width, float height, int mouseX, for (String page : pages) { pagesWidth += FPSMaster.fontManager.s16.getStringWidth(FPSMaster.i18n.get(page)) + 10; } - Render2DUtils.drawOptimizedRoundedRect(x + 90, y + 6, pagesWidth, 16f, FPSMaster.theme.getFrontBackground()); + Render2DUtils.drawOptimizedRoundedRect(x + 90, y + 6, pagesWidth, 16f, new Color(50, 50, 50,100).getRGB()); for (String page : pages) { int stringWidth = FPSMaster.fontManager.s16.getStringWidth(FPSMaster.i18n.get(page)); if (page.equals(pages[curSearch])) { - Render2DUtils.drawOptimizedRoundedRect(x + 90 + xOffset, y + 6, stringWidth + 10, 16f, FPSMaster.theme.getPrimary()); - FPSMaster.fontManager.s16.drawString(FPSMaster.i18n.get(page), x + 95 + xOffset, y + 10, FPSMaster.theme.getTextColorTitle().getRGB()); + Render2DUtils.drawOptimizedRoundedRect(x + 90 + xOffset, y + 6, stringWidth + 10, 16f, -1); + FPSMaster.fontManager.s16.drawString(FPSMaster.i18n.get(page), x + 95 + xOffset, y + 10, new Color(50, 50, 50).getRGB()); } else { - FPSMaster.fontManager.s16.drawString(FPSMaster.i18n.get(page), x + 95 + xOffset, y + 10, FPSMaster.theme.getTextColorDescription().getRGB()); + FPSMaster.fontManager.s16.drawString(FPSMaster.i18n.get(page), x + 95 + xOffset, y + 10, -1); } xOffset += stringWidth + 10; } @@ -268,7 +268,7 @@ public static void draw(float x, float y, float width, float height, int mouseX, } } else { int stringWidth = FPSMaster.fontManager.s16.getStringWidth(nickname); - FPSMaster.fontManager.s16.drawString(nickname, x + width - stringWidth - 5, y + 10, FPSMaster.theme.getTextColorTitle().getRGB()); + FPSMaster.fontManager.s16.drawString(nickname, x + width - stringWidth - 5, y + 10, -1); if (Render2DUtils.isHovered(x + width - stringWidth - 5, y + 10, stringWidth, 16f, mouseX, mouseY)) { if (Mouse.isButtonDown(0)) { isWaitingLogin = true; @@ -281,17 +281,17 @@ public static void draw(float x, float y, float width, float height, int mouseX, // 操作栏 AbstractMusic current = MusicPlayer.playList.current(); Render2DUtils.drawRect(x, y + height - 30, width, 2f, FPSMaster.theme.getFrontBackground().getRGB()); - Render2DUtils.drawRect(x, y + height - 30, width * MusicPlayer.getPlayProgress(), 2f, FPSMaster.theme.getPrimary().getRGB()); + Render2DUtils.drawRect(x, y + height - 30, width * MusicPlayer.getPlayProgress(), 2f, -1); if (Render2DUtils.isHovered(x, y + height - 32, width, 4f, mouseX, mouseY)) { - Render2DUtils.drawRect(x, y + height - 31f, width * MusicPlayer.getPlayProgress(), 4f, FPSMaster.theme.getPrimary().getRGB()); + Render2DUtils.drawRect(x, y + height - 31f, width * MusicPlayer.getPlayProgress(), 4f, -1); } // 音量 - Render2DUtils.drawImage(new ResourceLocation("client/textures/ui/volume.png"), x + width - 50, y + height - 16, 7f, 7f, FPSMaster.theme.getTextColorTitle()); + Render2DUtils.drawImage(new ResourceLocation("client/textures/ui/volume.png"), x + width - 50, y + height - 16, 7f, 7f, -1); Render2DUtils.drawRect(x + width - 40, y + height - 14, 30f, 2f, FPSMaster.theme.getFrontBackground().getRGB()); - Render2DUtils.drawRect(x + width - 40, y + height - 14, 30 * MusicPlayer.getVolume(), 2f, FPSMaster.theme.getPrimary().getRGB()); + Render2DUtils.drawRect(x + width - 40, y + height - 14, 30 * MusicPlayer.getVolume(), 2f, -1); if (Render2DUtils.isHovered(x + width - 40, y + height - 14, 30f, 2f, mouseX, mouseY)) { - Render2DUtils.drawRect(x + width - 40, y + height - 14.5f, 30 * MusicPlayer.getVolume(), 3f, FPSMaster.theme.getPrimary().getRGB()); + Render2DUtils.drawRect(x + width - 40, y + height - 14.5f, 30 * MusicPlayer.getVolume(), 3f, -1); if (Mouse.isButtonDown(0)) { float newVolume = (mouseX - x - width + 40) / 30f; MusicPlayer.setVolume(newVolume); diff --git a/shared/java/top/fpsmaster/ui/click/music/SearchBox.java b/shared/java/top/fpsmaster/ui/click/music/SearchBox.java index d776ff55..0eb88bd1 100644 --- a/shared/java/top/fpsmaster/ui/click/music/SearchBox.java +++ b/shared/java/top/fpsmaster/ui/click/music/SearchBox.java @@ -347,12 +347,12 @@ public void render(float x, float y, float width, float height, int mouseX, int if (this.visible) { if (Render2DUtils.isHovered(x, y, width, height, mouseX, mouseY)) { if (isFocused) { - btnColor.base(FPSMaster.theme.getTextboxFocus()); + btnColor.base(new Color(255, 255, 255, 50)); } else { - btnColor.base(FPSMaster.theme.getTextboxHover()); + btnColor.base(new Color(255, 255, 255, 20)); } } else { - btnColor.base(enabledColor); + btnColor.base(new Color(255, 255, 255, 20)); } Render2DUtils.drawOptimizedRoundedRect(xPosition, yPosition, width, height, btnColor.getColor()); diff --git a/shared/java/top/fpsmaster/ui/screens/mainmenu/MainMenu.java b/shared/java/top/fpsmaster/ui/screens/mainmenu/MainMenu.java index 197fefaf..77d448d9 100644 --- a/shared/java/top/fpsmaster/ui/screens/mainmenu/MainMenu.java +++ b/shared/java/top/fpsmaster/ui/screens/mainmenu/MainMenu.java @@ -95,7 +95,7 @@ public void render(int mouseX, int mouseY, float partialTicks) { FPSMaster.fontManager.s16.drawString("Copyright Mojang AB. Do not distribute!", guiWidth - w - 4, guiHeight - 14, Color.WHITE.getRGB()); // Display welcome message - String welcome = FPSMaster.INSTANCE.loggedIn ? TextFormattingProvider.getGreen() + String.format(FPSMaster.i18n.get("mainmenu.welcome"), FPSMaster.configManager.configure.getOrCreate("username", "")) : TextFormattingProvider.getRed().toString() + TextFormattingProvider.getBold().toString() + FPSMaster.i18n.get("mainmenu.notlogin"); + String welcome = FPSMaster.INSTANCE.loggedIn ? TextFormattingProvider.getGreen() + String.format(FPSMaster.i18n.get("mainmenu.welcome"), FPSMaster.accountManager.getUsername()) : TextFormattingProvider.getRed().toString() + TextFormattingProvider.getBold().toString() + FPSMaster.i18n.get("mainmenu.notlogin"); FPSMaster.fontManager.s16.drawString(welcome, 4, guiHeight - 52, Color.WHITE.getRGB()); // Version info diff --git a/shared/java/top/fpsmaster/ui/screens/oobe/impls/Login.java b/shared/java/top/fpsmaster/ui/screens/oobe/impls/Login.java index f6be9e5b..942821d4 100644 --- a/shared/java/top/fpsmaster/ui/screens/oobe/impls/Login.java +++ b/shared/java/top/fpsmaster/ui/screens/oobe/impls/Login.java @@ -69,6 +69,7 @@ public Login(boolean isOOBE) { } else { Minecraft.getMinecraft().displayGuiScreen(new MainMenu()); } + FPSMaster.INSTANCE.loggedIn = false; FPSMaster.configManager.configure.set("username", ""); }); } From 38edeb06bf4e33c01f3164b6b51d2ff4b7c82fe4 Mon Sep 17 00:00:00 2001 From: SuperSkidder Date: Thu, 12 Jun 2025 16:12:37 +0800 Subject: [PATCH 045/193] feat: gui multiplayer color --- shared/java/top/fpsmaster/ui/mc/GuiMultiplayer.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/shared/java/top/fpsmaster/ui/mc/GuiMultiplayer.java b/shared/java/top/fpsmaster/ui/mc/GuiMultiplayer.java index 5c9d3dce..0e65bcc6 100644 --- a/shared/java/top/fpsmaster/ui/mc/GuiMultiplayer.java +++ b/shared/java/top/fpsmaster/ui/mc/GuiMultiplayer.java @@ -174,10 +174,10 @@ public void render(int mouseX, int mouseY, float partialTicks) { UFontRenderer font = FPSMaster.fontManager.s18; title.drawCenteredString("多人游戏", width / 2f, 16, -1); - Render2DUtils.drawOptimizedRoundedRect((width - 180) / 2f, 30, 180, 24, 3, new Color(255, 255, 255, 80).getRGB()); - Render2DUtils.drawOptimizedRoundedRect((width - 176) / 2f + 90 * tab, 32, 86, 20, 3, new Color(113, 127, 254).getRGB()); - FPSMaster.fontManager.s16.drawCenteredString("服务器列表", (width - 90) / 2f, 36, -1); - FPSMaster.fontManager.s16.drawCenteredString("推荐服务器", (width + 90) / 2f, 36, -1); + Render2DUtils.drawOptimizedRoundedRect((width - 180) / 2f, 30, 180, 24, 3, new Color(0, 0, 0, 80).getRGB()); + Render2DUtils.drawOptimizedRoundedRect((width - 176) / 2f + 90 * tab, 32, 86, 20, 3, -1); + FPSMaster.fontManager.s16.drawCenteredString("服务器列表", (width - 90) / 2f, 36, tab == 0 ? new Color(50, 50, 50).getRGB() : -1); + FPSMaster.fontManager.s16.drawCenteredString("推荐服务器", (width + 90) / 2f, 36, tab == 1 ? new Color(50, 50, 50).getRGB() : -1); GL11.glPushMatrix(); GL11.glEnable(GL11.GL_SCISSOR_TEST); @@ -274,7 +274,7 @@ public void onClick(int mouseX, int mouseY, int mouseButton) { } else { if (timer.delay(200)) { selectedServer = null; - }else{ + } else { FMLClientHandler.instance().connectToServer(this, selectedServer); } } From 2259d7412665bb22c149494ed80edbe32c557101 Mon Sep 17 00:00:00 2001 From: vlouboos Date: Thu, 12 Jun 2025 18:04:16 +0800 Subject: [PATCH 046/193] Fixed some bugs --- .../fpsmaster/features/command/impl/Dev.java | 3 +-- .../fpsmaster/forge/mixin/MixinMinecraft.java | 24 ++++++++++++++++++- 2 files changed, 24 insertions(+), 3 deletions(-) diff --git a/shared/java/top/fpsmaster/features/command/impl/Dev.java b/shared/java/top/fpsmaster/features/command/impl/Dev.java index b76925de..52cd5945 100644 --- a/shared/java/top/fpsmaster/features/command/impl/Dev.java +++ b/shared/java/top/fpsmaster/features/command/impl/Dev.java @@ -35,8 +35,7 @@ public void execute(String[] args) { LuaManager.scripts.forEach(script -> Utility.sendClientNotify(script.rawLua.filename)); break; case "ide": - Minecraft.getMinecraft().displayGuiScreen(null); - Minecraft.getMinecraft().displayGuiScreen(new DevSpace()); + Minecraft.getMinecraft().addScheduledTask(() -> Minecraft.getMinecraft().displayGuiScreen(new DevSpace())); break; default: Utility.sendClientNotify("Unknown command: " + args[0]); diff --git a/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinMinecraft.java b/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinMinecraft.java index 7972f9e0..b308f58f 100644 --- a/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinMinecraft.java +++ b/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinMinecraft.java @@ -34,7 +34,6 @@ import javax.annotation.Nullable; import java.awt.*; -import java.util.Iterator; import static top.fpsmaster.FPSMaster.getClientTitle; @@ -160,6 +159,29 @@ public void onTick(CallbackInfo ci) { EventDispatcher.dispatchEvent(new EventTick()); } + // Ugly code + @Inject(method = "runTick", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/settings/KeyBinding;isPressed()Z", ordinal = 3)) + public void chatVis(CallbackInfo ci) { + if (this.gameSettings.keyBindTogglePerspective.isPressed()) { + ++this.gameSettings.thirdPersonView; + if (this.gameSettings.thirdPersonView > 2) { + this.gameSettings.thirdPersonView = 0; + } + + if (this.gameSettings.thirdPersonView == 0) { + this.entityRenderer.loadEntityShader(this.getRenderViewEntity()); + } else if (this.gameSettings.thirdPersonView == 1) { + this.entityRenderer.loadEntityShader((Entity)null); + } + + this.renderGlobal.setDisplayListEntitiesDirty(); + } + + if (this.gameSettings.keyBindSmoothCamera.isPressed()) { + this.gameSettings.smoothCamera = !this.gameSettings.smoothCamera; + } + } + @Shadow protected abstract void sendClickBlockToController(boolean leftClick); From bcc9ef2be114323d19aca0d157623eb84f1564b1 Mon Sep 17 00:00:00 2001 From: SuperSkidder Date: Thu, 12 Jun 2025 20:47:07 +0800 Subject: [PATCH 047/193] fix: clickgui size bug --- .../top/fpsmaster/ui/click/MainPanel.java | 28 +++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/shared/java/top/fpsmaster/ui/click/MainPanel.java b/shared/java/top/fpsmaster/ui/click/MainPanel.java index 7cec0ba8..4956ef14 100644 --- a/shared/java/top/fpsmaster/ui/click/MainPanel.java +++ b/shared/java/top/fpsmaster/ui/click/MainPanel.java @@ -60,8 +60,8 @@ public class MainPanel extends ScaledGuiScreen { static int x = -1; static int y = -1; - static float width = 0f; - static float height = 0f; + static float width = 400f; + static float height = 240f; public static String bindLock = ""; public static Module curModule = null; public static String dragLock = "null"; @@ -89,15 +89,15 @@ public void render(int mouseX, int mouseY, float partialTicks) { } - if (sizeDrag) { - float w = mouseX + sizeDragX - x; - float h = mouseY + sizeDragY - y; - width = w; - height = h; - } +// if (sizeDrag) { +// float w = mouseX + sizeDragX - x; +// float h = mouseY + sizeDragY - y; +// width = w; +// height = h; +// } - width = Math.min(Math.max(400f, width), guiWidth); - height = Math.min(Math.max(240f, height), guiHeight); +// width = Math.min(Math.max(400f, width), guiWidth); +// height = Math.min(Math.max(240f, height), guiHeight); x = (int) Math.max(0, Math.min(guiWidth - (int) width, x)); y = (int) Math.max(0, Math.min(guiHeight - (int) height, y)); @@ -300,10 +300,10 @@ public void initGui() { scaleAnimation.fstart(0.8, 1.0, 0.2f, Type.EASE_OUT_BACK); close = false; - if (width == 0f || height == 0f) { - width = scaledWidth / 2f; - height = scaledHeight / 2f; - } +// if (width == 0f || height == 0f) { +// width = scaledWidth / 2f; +// height = scaledHeight / 2f; +// } if (x == -1 || y == -1) { x = (int) ((scaledWidth - width) / 2); From c6fe9c0a14f3dc835c79dabd3f8def67e1e17718 Mon Sep 17 00:00:00 2001 From: vlouboos Date: Tue, 24 Jun 2025 20:45:46 +0800 Subject: [PATCH 048/193] Add Client Brand Tag --- shared/java/top/fpsmaster/FPSMaster.java | 2 +- .../forge/mixin/MixinClientBrandRetriever.java | 18 ++++++++++++++++++ .../src/main/resources/mixins.fpsmaster.json | 1 + 3 files changed, 20 insertions(+), 1 deletion(-) create mode 100644 v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinClientBrandRetriever.java diff --git a/shared/java/top/fpsmaster/FPSMaster.java b/shared/java/top/fpsmaster/FPSMaster.java index fea993c2..0b0304f9 100644 --- a/shared/java/top/fpsmaster/FPSMaster.java +++ b/shared/java/top/fpsmaster/FPSMaster.java @@ -68,7 +68,7 @@ private static void checkDevelopment() { try { Class.forName("net.fabricmc.devlaunchinjector.Main"); development = true; - } catch (Throwable e) { + } catch (Throwable ignored) { } } diff --git a/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinClientBrandRetriever.java b/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinClientBrandRetriever.java new file mode 100644 index 00000000..366d679d --- /dev/null +++ b/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinClientBrandRetriever.java @@ -0,0 +1,18 @@ +package top.fpsmaster.forge.mixin; + +import net.minecraft.client.ClientBrandRetriever; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Overwrite; +import top.fpsmaster.utils.GitInfo; + +@Mixin(ClientBrandRetriever.class) +public class MixinClientBrandRetriever { + /** + * @author vlouboos + * @reason Overwrite Tag + */ + @Overwrite + public static String getClientModName() { + return "fpsmaster:" + GitInfo.getBranch() + ":" + GitInfo.getCommitIdAbbrev(); + } +} diff --git a/v1.8.9/src/main/resources/mixins.fpsmaster.json b/v1.8.9/src/main/resources/mixins.fpsmaster.json index b033ef42..5b0dd946 100644 --- a/v1.8.9/src/main/resources/mixins.fpsmaster.json +++ b/v1.8.9/src/main/resources/mixins.fpsmaster.json @@ -19,6 +19,7 @@ "EntityFXMixin_StaticParticleColor", "MixinAbstractClientPlayer", "MixinChatLine", + "MixinClientBrandRetriever", "MixinEntityPlayerSP", "MixinEntityRenderer", "MixinFontRender", From 742adbd32e2af1389671d5a3a4ad381ff3861a70 Mon Sep 17 00:00:00 2001 From: SuperSkidder Date: Sun, 29 Jun 2025 22:38:38 +0800 Subject: [PATCH 049/193] fix #91 --- .../fpsmaster/features/impl/interfaces/TargetDisplay.java | 5 +++-- .../top/fpsmaster/ui/custom/impl/TargetHUDComponent.java | 3 ++- shared/resources/assets/minecraft/client/lang/zh_cn.lang | 1 + 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/shared/java/top/fpsmaster/features/impl/interfaces/TargetDisplay.java b/shared/java/top/fpsmaster/features/impl/interfaces/TargetDisplay.java index f3c1b829..11544245 100644 --- a/shared/java/top/fpsmaster/features/impl/interfaces/TargetDisplay.java +++ b/shared/java/top/fpsmaster/features/impl/interfaces/TargetDisplay.java @@ -9,6 +9,7 @@ import top.fpsmaster.event.events.EventRender3D; import top.fpsmaster.features.impl.InterfaceModule; import top.fpsmaster.features.manager.Category; +import top.fpsmaster.features.settings.impl.BooleanSetting; import top.fpsmaster.features.settings.impl.ColorSetting; import top.fpsmaster.features.settings.impl.ModeSetting; import top.fpsmaster.interfaces.ProviderManager; @@ -19,14 +20,14 @@ public class TargetDisplay extends InterfaceModule { private ModeSetting targetESP = new ModeSetting("TargetESP", 0, "glow", "none"); private ColorSetting espColor = new ColorSetting("EspColor", new Color(255, 255, 255, 255), () -> !targetESP.isMode("none")); - public static ModeSetting targetHUD = new ModeSetting("TargetHUD", 0, "simple", "none"); + public static BooleanSetting omit = new BooleanSetting("OmitName", true); public static EntityPlayer target; public static long lastHit; public TargetDisplay() { super("TargetDisplay", Category.Interface); - addSettings(targetESP, targetHUD, espColor); + addSettings(targetESP, targetHUD, espColor, omit); } @Subscribe diff --git a/shared/java/top/fpsmaster/ui/custom/impl/TargetHUDComponent.java b/shared/java/top/fpsmaster/ui/custom/impl/TargetHUDComponent.java index 7896c8d4..e385fe03 100644 --- a/shared/java/top/fpsmaster/ui/custom/impl/TargetHUDComponent.java +++ b/shared/java/top/fpsmaster/ui/custom/impl/TargetHUDComponent.java @@ -40,7 +40,8 @@ public void draw(float x, float y) { // Set width and height String name = ((Entity) target1).getDisplayName().getFormattedText(); - if (name.length() > 12) { + + if (name.length() > 12 && TargetDisplay.omit.getValue()) { name = name.substring(0, 10) + ".."; } width = (30 + FPSMaster.fontManager.s16.getStringWidth(name)); diff --git a/shared/resources/assets/minecraft/client/lang/zh_cn.lang b/shared/resources/assets/minecraft/client/lang/zh_cn.lang index 73874792..b1dc6ca1 100644 --- a/shared/resources/assets/minecraft/client/lang/zh_cn.lang +++ b/shared/resources/assets/minecraft/client/lang/zh_cn.lang @@ -380,6 +380,7 @@ targetdisplay.targethud.simple=简单 targetdisplay.espcolor=ESP颜色 targetdisplay.roundradius=圆角半径 targetdisplay.background=背景 +targetdisplay.omitname=省略过长的名字 minimizedbobbing=最小摇晃 minimizedbobbing.desc=停止全局的摇晃 From fa94aa41ed6f6f4f37e31597510338a3cde5bd80 Mon Sep 17 00:00:00 2001 From: SuperSkidder Date: Sun, 29 Jun 2025 22:55:51 +0800 Subject: [PATCH 050/193] fix #74 --- .../features/command/CommandManager.java | 4 +-- .../impl/interfaces/ClientSettings.java | 4 ++- .../features/impl/utility/ClientCommand.java | 28 ------------------- .../fpsmaster/features/impl/utility/IRC.java | 2 ++ .../features/manager/ModuleManager.java | 1 - .../modules/config/ConfigManager.java | 3 -- .../fpsmaster/websocket/client/WsClient.java | 3 +- .../assets/minecraft/client/lang/zh_cn.lang | 5 ++-- 8 files changed, 12 insertions(+), 38 deletions(-) delete mode 100644 shared/java/top/fpsmaster/features/impl/utility/ClientCommand.java diff --git a/shared/java/top/fpsmaster/features/command/CommandManager.java b/shared/java/top/fpsmaster/features/command/CommandManager.java index 3b79f91e..4007af69 100644 --- a/shared/java/top/fpsmaster/features/command/CommandManager.java +++ b/shared/java/top/fpsmaster/features/command/CommandManager.java @@ -7,7 +7,7 @@ import top.fpsmaster.features.command.impl.AI; import top.fpsmaster.features.command.impl.Dev; import top.fpsmaster.features.command.impl.IRCChat; -import top.fpsmaster.features.impl.utility.ClientCommand; +import top.fpsmaster.features.impl.interfaces.ClientSettings; import top.fpsmaster.utils.Utility; import java.util.ArrayList; @@ -27,7 +27,7 @@ public void init() { @Subscribe public void onChat(EventSendChatMessage e) { - if (ClientCommand.using && e.msg.startsWith(ClientCommand.prefix.getValue())) { + if (e.msg.startsWith(ClientSettings.prefix.getValue())) { e.cancel(); try { runCommand(e.msg.substring(1)); diff --git a/shared/java/top/fpsmaster/features/impl/interfaces/ClientSettings.java b/shared/java/top/fpsmaster/features/impl/interfaces/ClientSettings.java index 6639028f..8ae17e75 100644 --- a/shared/java/top/fpsmaster/features/impl/interfaces/ClientSettings.java +++ b/shared/java/top/fpsmaster/features/impl/interfaces/ClientSettings.java @@ -5,15 +5,17 @@ import top.fpsmaster.features.manager.Category; import top.fpsmaster.features.settings.impl.BindSetting; import top.fpsmaster.features.settings.impl.BooleanSetting; +import top.fpsmaster.features.settings.impl.TextSetting; public class ClientSettings extends InterfaceModule { public static BooleanSetting blur = new BooleanSetting("blur", false); public static BindSetting keyBind = new BindSetting("ClickGuiKey", Keyboard.KEY_RSHIFT); public static BooleanSetting fixedScale = new BooleanSetting("FixedScale", true); + public static final TextSetting prefix = new TextSetting("prefix", "#"); public ClientSettings() { super("ClientSettings", Category.Interface); - addSettings(keyBind, fixedScale, blur); + addSettings(prefix, keyBind, fixedScale, blur); } @Override diff --git a/shared/java/top/fpsmaster/features/impl/utility/ClientCommand.java b/shared/java/top/fpsmaster/features/impl/utility/ClientCommand.java deleted file mode 100644 index 9a1dc63f..00000000 --- a/shared/java/top/fpsmaster/features/impl/utility/ClientCommand.java +++ /dev/null @@ -1,28 +0,0 @@ -package top.fpsmaster.features.impl.utility; - -import top.fpsmaster.features.manager.Category; -import top.fpsmaster.features.manager.Module; -import top.fpsmaster.features.settings.impl.TextSetting; - -public class ClientCommand extends Module { - - public static boolean using = false; - public static final TextSetting prefix = new TextSetting("prefix", "#"); - - public ClientCommand() { - super("ClientCommand", Category.Utility); - addSettings(prefix); - } - - @Override - public void onEnable() { - using = true; - super.onEnable(); - } - - @Override - public void onDisable() { - using = false; - super.onDisable(); - } -} diff --git a/shared/java/top/fpsmaster/features/impl/utility/IRC.java b/shared/java/top/fpsmaster/features/impl/utility/IRC.java index 58332c10..caa19c31 100644 --- a/shared/java/top/fpsmaster/features/impl/utility/IRC.java +++ b/shared/java/top/fpsmaster/features/impl/utility/IRC.java @@ -3,6 +3,7 @@ import top.fpsmaster.FPSMaster; import top.fpsmaster.event.Subscribe; import top.fpsmaster.event.events.EventTick; +import top.fpsmaster.features.impl.interfaces.ClientSettings; import top.fpsmaster.features.manager.Category; import top.fpsmaster.features.manager.Module; import top.fpsmaster.features.settings.impl.BooleanSetting; @@ -42,6 +43,7 @@ public void onTick(EventTick e) throws URISyntaxException { FPSMaster.INSTANCE.wsClient = WsClient.start("wss://service.fpsmaster.top/"); Utility.sendClientDebug("尝试连接"); } else if (FPSMaster.INSTANCE.wsClient != null && FPSMaster.INSTANCE.wsClient.isClosed() && !FPSMaster.INSTANCE.wsClient.isOpen()) { + FPSMaster.INSTANCE.wsClient.close(); FPSMaster.INSTANCE.wsClient.connect(); Utility.sendClientDebug("尝试连接"); } diff --git a/shared/java/top/fpsmaster/features/manager/ModuleManager.java b/shared/java/top/fpsmaster/features/manager/ModuleManager.java index d9691b95..5ae2a148 100644 --- a/shared/java/top/fpsmaster/features/manager/ModuleManager.java +++ b/shared/java/top/fpsmaster/features/manager/ModuleManager.java @@ -112,7 +112,6 @@ public void init() { modules.add(new PingDisplay()); modules.add(new CoordsDisplay()); modules.add(new ModsList()); - modules.add(new ClientCommand()); modules.add(new MiniMap()); modules.add(new DirectionDisplay()); modules.add(new DamageIndicator()); diff --git a/shared/java/top/fpsmaster/modules/config/ConfigManager.java b/shared/java/top/fpsmaster/modules/config/ConfigManager.java index 15750ccb..71d49e1b 100644 --- a/shared/java/top/fpsmaster/modules/config/ConfigManager.java +++ b/shared/java/top/fpsmaster/modules/config/ConfigManager.java @@ -2,11 +2,9 @@ import com.google.gson.*; import top.fpsmaster.FPSMaster; -import top.fpsmaster.features.impl.InterfaceModule; import top.fpsmaster.features.impl.optimizes.OldAnimations; import top.fpsmaster.features.impl.optimizes.Performance; import top.fpsmaster.features.impl.render.ItemPhysics; -import top.fpsmaster.features.impl.utility.ClientCommand; import top.fpsmaster.features.impl.utility.IRC; import top.fpsmaster.features.manager.Module; import top.fpsmaster.features.settings.Setting; @@ -157,7 +155,6 @@ private void openDefaultModules() { FPSMaster.moduleManager.getModule(Performance.class).set(true); FPSMaster.moduleManager.getModule(OldAnimations.class).set(true); FPSMaster.moduleManager.getModule(ItemPhysics.class).set(true); - FPSMaster.moduleManager.getModule(ClientCommand.class).set(true); FPSMaster.moduleManager.getModule(IRC.class).set(true); } } diff --git a/shared/java/top/fpsmaster/websocket/client/WsClient.java b/shared/java/top/fpsmaster/websocket/client/WsClient.java index 4fade73d..42616d3d 100644 --- a/shared/java/top/fpsmaster/websocket/client/WsClient.java +++ b/shared/java/top/fpsmaster/websocket/client/WsClient.java @@ -5,6 +5,7 @@ import org.java_websocket.client.WebSocketClient; import org.java_websocket.handshake.ServerHandshake; import top.fpsmaster.FPSMaster; +import top.fpsmaster.features.impl.interfaces.ClientSettings; import top.fpsmaster.interfaces.ProviderManager; import top.fpsmaster.modules.dev.DevMode; import top.fpsmaster.utils.Utility; @@ -26,7 +27,7 @@ public WsClient(URI serverURI) { public void onOpen(ServerHandshake handshakedata) { Utility.sendClientDebug("成功连接到irc服务器"); if (ProviderManager.mcProvider.getPlayer() != null) { - Utility.sendClientMessage(FPSMaster.i18n.get("irc.enable")); + Utility.sendClientMessage(FPSMaster.i18n.get("irc.enable").replace("%s",ClientSettings.prefix.getValue())); } assert FPSMaster.accountManager != null; send(new LoginPacket(FPSMaster.accountManager.getUsername(), FPSMaster.accountManager.getToken()).toJson()); diff --git a/shared/resources/assets/minecraft/client/lang/zh_cn.lang b/shared/resources/assets/minecraft/client/lang/zh_cn.lang index b1dc6ca1..7eb3492e 100644 --- a/shared/resources/assets/minecraft/client/lang/zh_cn.lang +++ b/shared/resources/assets/minecraft/client/lang/zh_cn.lang @@ -259,7 +259,7 @@ oldanimations.animationmode.push=Push irc=客户端聊天 irc.desc=与相同客户端的用户聊天 -irc.enable=IRC功能已启用,输入#irc <消息>发送消息 +irc.enable=IRC功能已启用,输入%sirc <消息>发送消息 irc.showmates=显示同客户端用户 hitcolor=击中颜色 @@ -468,7 +468,7 @@ betterscreen.noflickering=防止闪烁 clientcommand=客户端命令 clientcommand.desc=使用命令执行客户端功能 -clientcommand.prefix=命令前缀 + cheatersdetector=作弊者检测 cheatersdetector.desc=检测作弊者并特殊标记 @@ -481,6 +481,7 @@ clientsettings.desc=调整客户端各类设置 clientsettings.clickguikey=设置界面快捷键 clientsettings.fixedscale=固定界面缩放比例 clientsettings.blur=界面组件模糊 +clientsettings.prefix=命令前缀 dragonwings=龙翅膀 dragonwings.desc=在自己身上龙翅膀 From cb46566618c0f118d244574fbde1339e30896465 Mon Sep 17 00:00:00 2001 From: SuperSkidder Date: Sun, 29 Jun 2025 22:59:32 +0800 Subject: [PATCH 051/193] fix #89 --- .../fpsmaster/ui/click/music/MusicPanel.java | 24 ++++++++++++------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/shared/java/top/fpsmaster/ui/click/music/MusicPanel.java b/shared/java/top/fpsmaster/ui/click/music/MusicPanel.java index dd3dee21..129bd691 100644 --- a/shared/java/top/fpsmaster/ui/click/music/MusicPanel.java +++ b/shared/java/top/fpsmaster/ui/click/music/MusicPanel.java @@ -50,6 +50,7 @@ public class MusicPanel { public static float y = 0f; public static float width = 0f; public static float height = 0f; + private static Thread playThread; public static void mouseClicked(int mouseX, int mouseY, int btn) { inputBox.mouseClicked(mouseX, mouseY, btn); @@ -91,15 +92,20 @@ public static void mouseClicked(int mouseX, int mouseY, int btn) { if (Render2DUtils.isHovered(x, y + height - 30, width, 4f, mouseX, mouseY)) { if (Mouse.isButtonDown(0) && current != null) { if (!MusicPlayer.isPlaying) { - FPSMaster.async.runnable(() -> { - MusicPlayer.playList.play(); - try { - Thread.sleep(50); - } catch (InterruptedException e) { - throw new RuntimeException(e); - } - current.seek((mouseX - x) / width); - }); + if (playThread != null && playThread.isAlive()) { + playThread.interrupt(); + } + playThread = new Thread( + () -> { + MusicPlayer.playList.play(); + try { + Thread.sleep(50); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + current.seek((mouseX - x) / width); + } + ); MusicPlayer.isPlaying = true; } else { current.seek((mouseX - x) / width); From 18ccfd07f0642ce51e10c402267975ffb30b5bca Mon Sep 17 00:00:00 2001 From: SuperSkidder Date: Sun, 29 Jun 2025 23:03:52 +0800 Subject: [PATCH 052/193] fix #90 --- .../mixin/MixinAbstractClientPlayer.java | 22 +++---------------- 1 file changed, 3 insertions(+), 19 deletions(-) diff --git a/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinAbstractClientPlayer.java b/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinAbstractClientPlayer.java index 488723b6..c2bcb548 100644 --- a/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinAbstractClientPlayer.java +++ b/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinAbstractClientPlayer.java @@ -1,6 +1,5 @@ package top.fpsmaster.forge.mixin; -import net.minecraft.client.Minecraft; import net.minecraft.client.entity.AbstractClientPlayer; import net.minecraft.client.network.NetworkPlayerInfo; import net.minecraft.entity.SharedMonsterAttributes; @@ -8,16 +7,13 @@ import net.minecraft.init.Items; import net.minecraft.util.ResourceLocation; import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Overwrite; 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.callback.CallbackInfoReturnable; import top.fpsmaster.event.EventDispatcher; import top.fpsmaster.event.events.EventCapeLoading; -import top.fpsmaster.features.impl.optimizes.SmoothZoom; import top.fpsmaster.features.impl.utility.CustomFOV; -import top.fpsmaster.utils.math.MathUtils; @Mixin(AbstractClientPlayer.class) public abstract class MixinAbstractClientPlayer extends MixinEntityPlayer { @@ -65,23 +61,11 @@ public void customFov(CallbackInfoReturnable cir) { private NetworkPlayerInfo playerInfo; - /** - * @author SuperSkidder - * @reason CapeLoading - */ - @Overwrite - public ResourceLocation getLocationCape() { + @Inject(method = "getLocationCape", at = @At("HEAD"), cancellable = true) + public void getLocationCape(CallbackInfoReturnable cir) { EventCapeLoading event = new EventCapeLoading(playerInfo.getGameProfile().getName(), (AbstractClientPlayer) (Object) this); EventDispatcher.dispatchEvent(event); fpsmasterCape = event.cape; - - if (fpsmasterCape != null) { - return fpsmasterCape; - } - - - NetworkPlayerInfo networkplayerinfo = this.getPlayerInfo(); - return networkplayerinfo == null ? null : networkplayerinfo.getLocationCape(); - + cir.setReturnValue(fpsmasterCape); } } From be58aa465e20fceff7b607d0de9a54e50723b90a Mon Sep 17 00:00:00 2001 From: SuperSkidder Date: Sun, 29 Jun 2025 23:11:36 +0800 Subject: [PATCH 053/193] fix #68 --- shared/java/top/fpsmaster/ui/mc/ServerListEntry.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/shared/java/top/fpsmaster/ui/mc/ServerListEntry.java b/shared/java/top/fpsmaster/ui/mc/ServerListEntry.java index 111b93bc..daa507a9 100644 --- a/shared/java/top/fpsmaster/ui/mc/ServerListEntry.java +++ b/shared/java/top/fpsmaster/ui/mc/ServerListEntry.java @@ -171,6 +171,10 @@ public void drawEntry(int slotIndex, int x, int y, int listWidth, int slotHeight // this.owner.setHoveringText(s); // } + if (Render2DUtils.isHovered(x + listWidth - text.getStringWidth(s1), y + 4,10,10,mouseX,mouseY)) { + text.drawString(s1, x + listWidth - text.getStringWidth(s1) + 12, y + 4, -1); + } + if (this.mc.gameSettings.touchscreen || isSelected) { this.mc.getTextureManager().bindTexture(SERVER_SELECTION_BUTTONS); Gui.drawRect(x, y, x + 32, y + 32, -1601138544); From 6e6d195e3b5ebb3c431e9435d9e71a1de7cb5d2f Mon Sep 17 00:00:00 2001 From: SuperSkidder Date: Mon, 30 Jun 2025 00:48:33 +0800 Subject: [PATCH 054/193] fix keyevent trigger problem move ClientSettings from interface to utility add togglesprint and sprint component --- .../impl/interfaces/ClientSettings.java | 2 +- .../features/impl/utility/Sprint.java | 37 ++++++++++++++++-- .../features/manager/ModuleManager.java | 1 + .../ui/custom/ComponentsManager.java | 1 + .../ui/custom/impl/SprintComponent.java | 33 ++++++++++++++++ .../assets/minecraft/client/lang/zh_cn.lang | 2 + .../textures/modules/clientsettings.png | Bin 0 -> 440 bytes .../fpsmaster/forge/mixin/MixinMinecraft.java | 8 ++-- 8 files changed, 77 insertions(+), 7 deletions(-) create mode 100644 shared/java/top/fpsmaster/ui/custom/impl/SprintComponent.java create mode 100644 shared/resources/assets/minecraft/client/textures/modules/clientsettings.png diff --git a/shared/java/top/fpsmaster/features/impl/interfaces/ClientSettings.java b/shared/java/top/fpsmaster/features/impl/interfaces/ClientSettings.java index 8ae17e75..0c10ce5f 100644 --- a/shared/java/top/fpsmaster/features/impl/interfaces/ClientSettings.java +++ b/shared/java/top/fpsmaster/features/impl/interfaces/ClientSettings.java @@ -14,7 +14,7 @@ public class ClientSettings extends InterfaceModule { public static final TextSetting prefix = new TextSetting("prefix", "#"); public ClientSettings() { - super("ClientSettings", Category.Interface); + super("ClientSettings", Category.Utility); addSettings(prefix, keyBind, fixedScale, blur); } diff --git a/shared/java/top/fpsmaster/features/impl/utility/Sprint.java b/shared/java/top/fpsmaster/features/impl/utility/Sprint.java index 4a9261f5..c60e0e62 100644 --- a/shared/java/top/fpsmaster/features/impl/utility/Sprint.java +++ b/shared/java/top/fpsmaster/features/impl/utility/Sprint.java @@ -1,26 +1,57 @@ package top.fpsmaster.features.impl.utility; +import net.minecraft.potion.Potion; import top.fpsmaster.event.Subscribe; +import top.fpsmaster.event.events.EventKey; import top.fpsmaster.event.events.EventUpdate; +import top.fpsmaster.features.impl.InterfaceModule; import top.fpsmaster.features.manager.Category; import top.fpsmaster.features.manager.Module; +import top.fpsmaster.features.settings.impl.BooleanSetting; import top.fpsmaster.interfaces.ProviderManager; import top.fpsmaster.utils.Utility; +import top.fpsmaster.wrapper.MinecraftProvider; -public class Sprint extends Module { +import static top.fpsmaster.utils.Utility.mc; + +public class Sprint extends InterfaceModule { + + BooleanSetting toggleSprint = new BooleanSetting("ToggleSprint", true); public Sprint() { super("Sprint", Category.Utility); + addSettings(toggleSprint, betterFont); } + public static boolean sprint = true; + @Subscribe public void onUpdate(EventUpdate e) { - ProviderManager.gameSettings.setKeyPress(Utility.mc.gameSettings.keyBindSprint, true); + if (sprint || !toggleSprint.getValue()) { + if (mc.thePlayer.moveForward <= 0) + return; + if (mc.thePlayer.isCollidedHorizontally) + return; + if (mc.thePlayer.isPotionActive(Potion.blindness)) + return; + if (mc.thePlayer.getFoodStats().getFoodLevel() < 6f) + return; + if (mc.thePlayer.isUsingItem()) + return; + mc.thePlayer.setSprinting(true); + } + } + + @Subscribe + public void onKey(EventKey e){ + if (e.key == mc.gameSettings.keyBindSprint.getKeyCode()) { + sprint = !sprint; + } } @Override public void onDisable() { super.onDisable(); - ProviderManager.gameSettings.setKeyPress(Utility.mc.gameSettings.keyBindSprint, false); + ProviderManager.gameSettings.setKeyPress(mc.gameSettings.keyBindSprint, false); } } \ No newline at end of file diff --git a/shared/java/top/fpsmaster/features/manager/ModuleManager.java b/shared/java/top/fpsmaster/features/manager/ModuleManager.java index 5ae2a148..d5fdec70 100644 --- a/shared/java/top/fpsmaster/features/manager/ModuleManager.java +++ b/shared/java/top/fpsmaster/features/manager/ModuleManager.java @@ -15,6 +15,7 @@ import top.fpsmaster.ui.click.MainPanel; import top.fpsmaster.ui.click.modules.ModuleRenderer; import top.fpsmaster.ui.devspace.DevSpace; +import top.fpsmaster.utils.Utility; import java.util.ArrayList; import java.util.List; diff --git a/shared/java/top/fpsmaster/ui/custom/ComponentsManager.java b/shared/java/top/fpsmaster/ui/custom/ComponentsManager.java index e5f3a013..600d2d61 100644 --- a/shared/java/top/fpsmaster/ui/custom/ComponentsManager.java +++ b/shared/java/top/fpsmaster/ui/custom/ComponentsManager.java @@ -37,6 +37,7 @@ public void init() { components.add(new CoordsDisplayComponent()); components.add(new ModsListComponent()); components.add(new MiniMapComponent()); + components.add(new SprintComponent()); } // Get a component by its class type diff --git a/shared/java/top/fpsmaster/ui/custom/impl/SprintComponent.java b/shared/java/top/fpsmaster/ui/custom/impl/SprintComponent.java new file mode 100644 index 00000000..b9098366 --- /dev/null +++ b/shared/java/top/fpsmaster/ui/custom/impl/SprintComponent.java @@ -0,0 +1,33 @@ +package top.fpsmaster.ui.custom.impl; + +import top.fpsmaster.FPSMaster; +import top.fpsmaster.features.impl.utility.Sprint; +import top.fpsmaster.ui.custom.Component; + +import static top.fpsmaster.utils.Utility.mc; + +public class SprintComponent extends Component{ + public SprintComponent() { + super(Sprint.class); + } + + @Override + public void draw(float x, float y) { + super.draw(x, y); + String text; + if (Sprint.sprint) { + text = "[Sprinting (Toggled)]"; + }else{ + text = ""; + if (mc.thePlayer.isSprinting()){ + text = "[Sprinting (Vanilla)]"; + } + } + if (mc.thePlayer.capabilities.isFlying){ + text = "[Flying]"; + } + drawString(16, text, x, y,-1); + this.width = getStringWidth(16, text); + this.height = 12; + } +} diff --git a/shared/resources/assets/minecraft/client/lang/zh_cn.lang b/shared/resources/assets/minecraft/client/lang/zh_cn.lang index 7eb3492e..a20bfce3 100644 --- a/shared/resources/assets/minecraft/client/lang/zh_cn.lang +++ b/shared/resources/assets/minecraft/client/lang/zh_cn.lang @@ -213,6 +213,8 @@ motionblur.fastrender=注意!动态模糊功能与快速渲染并不兼容, sprint=强制疾跑 sprint.desc=保持疾跑 +sprint.togglesprint=保持疾跑 +sprint.betterfont=更好的字体 musicdisplay=音乐显示 musicdisplay.desc=显示你正在播放的音乐 diff --git a/shared/resources/assets/minecraft/client/textures/modules/clientsettings.png b/shared/resources/assets/minecraft/client/textures/modules/clientsettings.png new file mode 100644 index 0000000000000000000000000000000000000000..bf3c05472da8117cb1f91b89136ac27c947aaa01 GIT binary patch literal 440 zcmV;p0Z0CcP)Px$a!Eu%R7gwRR_$#H76y=Io72pB_Sc%A&h!BwRsj46LPyqb>9{*!P z+;eULHvzMQ?DMRG2mXX)p2Bxlm&dl%jVfTQ?9^+Ix2~ZTwRNvT0Rg0+PF0 zyG9b&sp@tX@SX|}s=65lbObX}UD{I>PQhXH6x-PfO8*#@`Wh`$Ew%Hs z3R(jk5zRVRU3`;XMI@)3%*PoqfL|f2{SE_Ce?{13*CP0;fe>1$B z0((@2)5DvBx$6ZSgjFb-y!Wmc9L~8~snT@4;9B}v9nH6tPe+e&FhBkhWz${knmFLK i=`BMS;ptPI2YvxmR Date: Mon, 30 Jun 2025 14:12:07 +0800 Subject: [PATCH 055/193] update readme --- README.md | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 434ca639..46e068e7 100644 --- a/README.md +++ b/README.md @@ -13,10 +13,9 @@ FPSMaster 是一个免费、强大的 Minecraft PvP 客户端。 本分支是FPSMaster v4的开发分支,目前处于开发阶段,请勿在生产环境中使用。 如果你想参与到开发中,请查看以下注意事项: -1. SDK将逐渐迁移到java,尽量不要增加新的kotlin代码 -2. 如果您要添加新的功能,请先在issue中提出,并进行讨论,避免您开发的功能与项目目标不一致 -3. 请不要在生产环境中使用,除非你非常熟悉代码,并且知道自己在做什么。 -4. 本分支的1.12.2版本代码暂时不会更新,因此使用1.12.2版本会报错是正常现象。 +1. 如果您要添加新的功能,请先在issue中提出,并进行讨论,避免您开发的功能与项目目标不一致 +2. 请不要在生产环境中使用,除非你非常熟悉代码,并且知道自己在做什么。 +3. 本分支的1.12.2版本代码暂时不会更新,因此使用1.12.2版本会报错是正常现象。 ### todo: @@ -36,15 +35,13 @@ FPSMaster 是一个免费、强大的 Minecraft PvP 客户端。 - [ ] 重写IRC模块 - [ ] 优化配置文件模块 - [ ] FPSMaster Intelligence -- [ ] HitMarker +- [x] HitMarker - [ ] Waypoint ## 开源许可证 本项目采用 GPL-3.0 许可证。详情请参阅 [LICENSE](LICENSE) 文件。 -特别声明:由于疏忽,自`c6a5edaac43fdcca8ce487eee430e9fb059a2db1`前所有版本的代码均错误地使用了MIT协议开源,现已更正为GPL-3.0。 - ## 开发环境配置 1. clone项目 2. Link Gradle Script From 3f37d9d87cf3985a6c9572173667ec422de652fa Mon Sep 17 00:00:00 2001 From: SuperSkidder Date: Mon, 30 Jun 2025 19:38:29 +0800 Subject: [PATCH 056/193] improve clickgui --- .../java/top/fpsmaster/ui/click/MainPanel.java | 12 +++++------- .../client/gui/settings/window/left.png | Bin 0 -> 5077 bytes .../client/gui/settings/window/panel.png | Bin 0 -> 134728 bytes .../client/gui/settings/window/selection.png | Bin 0 -> 571 bytes 4 files changed, 5 insertions(+), 7 deletions(-) create mode 100644 shared/resources/assets/minecraft/client/gui/settings/window/left.png create mode 100644 shared/resources/assets/minecraft/client/gui/settings/window/panel.png create mode 100644 shared/resources/assets/minecraft/client/gui/settings/window/selection.png diff --git a/shared/java/top/fpsmaster/ui/click/MainPanel.java b/shared/java/top/fpsmaster/ui/click/MainPanel.java index 4956ef14..49ed594f 100644 --- a/shared/java/top/fpsmaster/ui/click/MainPanel.java +++ b/shared/java/top/fpsmaster/ui/click/MainPanel.java @@ -32,7 +32,6 @@ public class MainPanel extends ScaledGuiScreen { float dragY = 0f; Category curType = Category.OPTIMIZE; LinkedList categories = new LinkedList<>(); - final float leftWidth = 50f; float modsWheel = 0f; float wheelTemp = 0f; boolean sizeDrag = false; @@ -60,8 +59,9 @@ public class MainPanel extends ScaledGuiScreen { static int x = -1; static int y = -1; - static float width = 400f; - static float height = 240f; + static float width = 430f; + static float height = 245.5f; + final float leftWidth = 50f; public static String bindLock = ""; public static Module curModule = null; public static String dragLock = "null"; @@ -118,13 +118,12 @@ public void render(int mouseX, int mouseY, float partialTicks) { backgroundColor.base(new Color(0, 0, 0, 150)); - Render2DUtils.drawBlurArea((int) (x + leftWidth), y, (int) (width - leftWidth), (int) height, 3, backgroundColor.getColor()); - Render2DUtils.drawOptimizedRoundedRect( + Render2DUtils.drawImage(new ResourceLocation("client/gui/settings/window/panel.png"), x + leftWidth, y, width - leftWidth, height, - backgroundColor.getColor() + -1 ); // logoColor.base(new Color(255, 255, 255)); @@ -230,7 +229,6 @@ public void render(int mouseX, int mouseY, float partialTicks) { categoryAnimation = (float) AnimationUtils.base(categoryAnimation, 30f, 0.15f); } - Render2DUtils.drawBlurArea(x, (int) (y + height / 2 - 70), (int) categoryAnimation, 140, 10, backgroundColor.getColor()); Render2DUtils.drawOptimizedRoundedRect( x + categoryAnimation / 50f, y + height / 2 - 70, diff --git a/shared/resources/assets/minecraft/client/gui/settings/window/left.png b/shared/resources/assets/minecraft/client/gui/settings/window/left.png new file mode 100644 index 0000000000000000000000000000000000000000..960611d9cbe345a61367cf997df2644e88d863f4 GIT binary patch literal 5077 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 XaJ(xPT>SvJngeO7>Z(*htRwyh24B8x literal 0 HcmV?d00001 diff --git a/shared/resources/assets/minecraft/client/gui/settings/window/panel.png b/shared/resources/assets/minecraft/client/gui/settings/window/panel.png new file mode 100644 index 0000000000000000000000000000000000000000..385ee5aac59d6d5390c2036f51c2f805de430923 GIT binary patch literal 134728 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 z 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 literal 0 HcmV?d00001 From 84b043847031c2fed63e7685e0db1761c827bfab Mon Sep 17 00:00:00 2001 From: SuperSkidder Date: Mon, 30 Jun 2025 21:36:40 +0800 Subject: [PATCH 057/193] feat: New Music UI optimize clickgui --- .../top/fpsmaster/ui/click/MainPanel.java | 97 +++--------------- .../ui/click/modules/ModuleRenderer.java | 48 +++++++-- .../fpsmaster/ui/click/music/MusicPanel.java | 2 +- .../ui/click/music/NewMusicPanel.java | 43 ++++++++ .../music/components/PLayListComponent.java | 7 ++ .../fpsmaster/utils/render/Render2DUtils.java | 1 - .../assets/minecraft/client/gui/music.png | Bin 0 -> 2930 bytes .../client/gui/settings/window/module.png | Bin 0 -> 1173 bytes .../client/gui/settings/window/option.png | Bin 0 -> 592 bytes .../gui/settings/window/option_circle.png | Bin 0 -> 283 bytes 10 files changed, 105 insertions(+), 93 deletions(-) create mode 100644 shared/java/top/fpsmaster/ui/click/music/NewMusicPanel.java create mode 100644 shared/java/top/fpsmaster/ui/click/music/components/PLayListComponent.java create mode 100644 shared/resources/assets/minecraft/client/gui/music.png create mode 100644 shared/resources/assets/minecraft/client/gui/settings/window/module.png create mode 100644 shared/resources/assets/minecraft/client/gui/settings/window/option.png create mode 100644 shared/resources/assets/minecraft/client/gui/settings/window/option_circle.png diff --git a/shared/java/top/fpsmaster/ui/click/MainPanel.java b/shared/java/top/fpsmaster/ui/click/MainPanel.java index 49ed594f..aaba41ea 100644 --- a/shared/java/top/fpsmaster/ui/click/MainPanel.java +++ b/shared/java/top/fpsmaster/ui/click/MainPanel.java @@ -12,6 +12,7 @@ import top.fpsmaster.ui.click.component.ScrollContainer; import top.fpsmaster.ui.click.music.MusicPanel; import top.fpsmaster.ui.click.modules.ModuleRenderer; +import top.fpsmaster.ui.click.music.NewMusicPanel; import top.fpsmaster.ui.click.themes.DarkTheme; import top.fpsmaster.ui.click.themes.LightTheme; import top.fpsmaster.utils.math.animation.Animation; @@ -34,18 +35,11 @@ public class MainPanel extends ScaledGuiScreen { LinkedList categories = new LinkedList<>(); float modsWheel = 0f; float wheelTemp = 0f; - boolean sizeDrag = false; - float sizeDragX = 0f; - float sizeDragY = 0f; Animation scaleAnimation = new Animation(); float selection = 0f; - ColorAnimation sizeDragBorder = new ColorAnimation(255, 255, 255, 0); - ColorAnimation backgroundColor = new ColorAnimation(39, 39, 39, 120); - ColorAnimation modeColor = new ColorAnimation(70, 70, 70, 200); - ColorAnimation logoColor = new ColorAnimation(255, 255, 255, 255); float categoryAnimation = 30; @@ -79,7 +73,6 @@ public void render(int mouseX, int mouseY, float partialTicks) { if (!Mouse.isButtonDown(0)) { dragLock = "null"; drag = false; - sizeDrag = false; } if (drag) { @@ -88,22 +81,11 @@ public void render(int mouseX, int mouseY, float partialTicks) { y = mouseY; } - -// if (sizeDrag) { -// float w = mouseX + sizeDragX - x; -// float h = mouseY + sizeDragY - y; -// width = w; -// height = h; -// } - -// width = Math.min(Math.max(400f, width), guiWidth); -// height = Math.min(Math.max(240f, height), guiHeight); - x = (int) Math.max(0, Math.min(guiWidth - (int) width, x)); y = (int) Math.max(0, Math.min(guiHeight - (int) height, y)); if (close) { - if (scaleAnimation.value >= 1.1) { + if (scaleAnimation.value <= 0.7) { mc.displayGuiScreen(null); if (mc.currentScreen == null) { mc.setIngameFocus(); @@ -117,65 +99,18 @@ public void render(int mouseX, int mouseY, float partialTicks) { GlStateManager.translate(-guiWidth / 2.0, -height / 2.0, 0.0); - backgroundColor.base(new Color(0, 0, 0, 150)); Render2DUtils.drawImage(new ResourceLocation("client/gui/settings/window/panel.png"), - x + leftWidth, - y, - width - leftWidth, - height, + x + leftWidth - 8, + y - 2, + width - leftWidth + 16, + height + 12, -1 ); -// logoColor.base(new Color(255, 255, 255)); -// Render2DUtils.drawImage( -// new ResourceLocation("client/gui/settings/logo.png"), -// x + leftWidth / 2 - 40 - 5, -// y + 15f, -// 81.5f, -// 64 / 2f, -// logoColor.getColor() -// ); - -// if (drag || sizeDrag) { -// sizeDragBorder.start(sizeDragBorder.getColor(), new Color(255, 255, 255), 0.15f, Type.EASE_IN_OUT_QUAD); -// } else { -// sizeDragBorder.start(sizeDragBorder.getColor(), new Color(255, 255, 255, 0), 0.2f, Type.EASE_IN_OUT_QUAD); -// } - -// sizeDragBorder.update(); - -// if (Render2DUtils.isHoveredWithoutScale( -// x + width - 10, -// y + height - 10, -// 10f, -// 10f, -// mouseX, -// mouseY -// )) { -// Render2DUtils.drawImage( -// new ResourceLocation("client/gui/settings/drag.png"), -// x + width - 5, -// y + height - 5, -// 5f, -// 5f, -// new Color(255, 255, 255) -// ); -// } else { -// Render2DUtils.drawImage( -// new ResourceLocation("client/gui/settings/drag.png"), -// x + width - 5, -// y + height - 5, -// 5f, -// 5f, -// new Color(200, 200, 200) -// ); -// } - - GL11.glEnable(GL11.GL_SCISSOR_TEST); Render2DUtils.doGlScissor( - x, y + 22, width, - (height - 30), + x, y+10, width, + (height - 18), scaleFactor ); @@ -184,8 +119,6 @@ public void render(int mouseX, int mouseY, float partialTicks) { if (curType == Category.Music) { MusicPanel.draw(x + leftWidth, y, width - leftWidth, height, mouseX, mouseY, scaleFactor); } else { - FPSMaster.fontManager.s24.drawStringWithShadow(FPSMaster.i18n.get("category." + curType.name().toLowerCase(Locale.getDefault())), x + leftWidth + 10, y + 5, -1); - modHeight = 20f; float containerWidth = width - leftWidth - 10; int finalMouseY = mouseY; @@ -231,11 +164,11 @@ public void render(int mouseX, int mouseY, float partialTicks) { Render2DUtils.drawOptimizedRoundedRect( x + categoryAnimation / 50f, - y + height / 2 - 70, + y + height / 2 - 74, categoryAnimation, 140, - 10, - backgroundColor.getColor().getRGB() + 14, + new Color(0,0,0,200).getRGB() ); float my = y + 60; @@ -244,7 +177,7 @@ public void render(int mouseX, int mouseY, float partialTicks) { selection - 6, categoryAnimation - 8, 22f, - 11, + 10, new Color(255, 255, 255).getRGB() ); @@ -264,7 +197,7 @@ public void render(int mouseX, int mouseY, float partialTicks) { } if (m.category == curType) { - selection = (sizeDrag || drag) + selection = drag ? my : (float) AnimationUtils.base(selection, my, 0.2); } @@ -295,7 +228,7 @@ public void initGui() { ScaledResolution sr = new ScaledResolution(mc); int scaledWidth = sr.getScaledWidth(); int scaledHeight = sr.getScaledHeight(); - scaleAnimation.fstart(0.8, 1.0, 0.2f, Type.EASE_OUT_BACK); + scaleAnimation.fstart(0.8, 1.0, 0.2f, Type.EASE_IN_OUT_QUAD); close = false; // if (width == 0f || height == 0f) { @@ -329,7 +262,7 @@ public void keyTyped(char typedChar, int keyCode) throws IOException { if (keyCode == 1) { if (scaleAnimation.end != 0.1) { close = true; - scaleAnimation.fstart(scaleAnimation.value, 1.1, 0.2f, Type.EASE_IN_BACK); + scaleAnimation.fstart(scaleAnimation.value, 0.7, 0.1f, Type.EASE_IN_OUT_QUAD); } return; } diff --git a/shared/java/top/fpsmaster/ui/click/modules/ModuleRenderer.java b/shared/java/top/fpsmaster/ui/click/modules/ModuleRenderer.java index 41e55834..86d9c7fc 100644 --- a/shared/java/top/fpsmaster/ui/click/modules/ModuleRenderer.java +++ b/shared/java/top/fpsmaster/ui/click/modules/ModuleRenderer.java @@ -1,5 +1,6 @@ package top.fpsmaster.ui.click.modules; +import net.minecraft.client.renderer.GlStateManager; import net.minecraft.util.ResourceLocation; import top.fpsmaster.FPSMaster; import top.fpsmaster.features.manager.Category; @@ -20,6 +21,10 @@ import java.util.Locale; import java.util.function.Consumer; +import static org.lwjgl.opengl.GL11.*; +import static org.lwjgl.opengl.GL11.GL_DEPTH_TEST; +import static org.lwjgl.opengl.GL11.glEnable; + public class ModuleRenderer extends ValueRender { ArrayList> settingsRenderers = new ArrayList<>(); private float settingHeight = 0f; @@ -27,6 +32,8 @@ public class ModuleRenderer extends ValueRender { private boolean expand = false; public ColorAnimation content; ColorAnimation background = new ColorAnimation(); + ColorAnimation option = new ColorAnimation(); + float optionX = 0; public ModuleRenderer(Module mod) { this.mod = mod; @@ -58,31 +65,35 @@ public void render(float x, float y, float width, float height, float mouseX, fl border = Render2DUtils.isHovered(x + 5, y, width - 10, height, (int) mouseX, (int) mouseY) ? (float) AnimationUtils.base(border, 200.0, 0.3) : (float) AnimationUtils.base(border, 30.0, 0.3); + option.update(); if (mod.isEnabled()) { content.start(content.getColor(), FPSMaster.theme.getModuleTextEnabled(), 0.2f, Type.EASE_IN_OUT_QUAD); - background.start(background.getColor(), new Color(150,150,150,60), 0.2f, Type.EASE_IN_OUT_QUAD); + option.start(option.getColor(), new Color(89, 101, 241), 0.2f, Type.EASE_IN_OUT_QUAD); + optionX = (float) AnimationUtils.base(optionX, 10, 0.2f); } else { content.start(content.getColor(), FPSMaster.theme.getModuleTextDisabled(), 0.2f, Type.EASE_IN_OUT_QUAD); - background.start(background.getColor(), new Color(100,100,100,60), 0.2f, Type.EASE_IN_OUT_QUAD); + option.start(option.getColor(), new Color(255, 255, 255), 0.2f, Type.EASE_IN_OUT_QUAD); + optionX = (float) AnimationUtils.base(optionX, 0, 0.2f); } - Render2DUtils.drawOptimizedRoundedRect( + Render2DUtils.drawImage( + new ResourceLocation("client/gui/settings/window/module.png"), x + 5, y, width - 10, - settingHeight + 37f, - 10, - new Color(100,100,100,60).getRGB() + 40, + -1 ); + GlStateManager.disableBlend(); Render2DUtils.drawOptimizedRoundedRect( x + 5, - y, + y + 40, width - 10, - 37f, + settingHeight, 10, - background.getColor().getRGB() + new Color(100, 100, 100, 60).getRGB() ); // Render2DUtils.drawOptimizedRoundedBorderRect( @@ -90,6 +101,25 @@ public void render(float x, float y, float width, float height, float mouseX, fl // FPSMaster.theme.getModuleBorder(), (int) border) // ); + Render2DUtils.drawImage( + new ResourceLocation("client/gui/settings/window/option.png"), + x + width - 40, + y + 16, + 21, + 10, + option.getColor() + ); + + Render2DUtils.drawImage( + new ResourceLocation("client/gui/settings/window/option_circle.png"), + x + width - 38 + optionX, + y + 17.5f, + 7, + 7, + -1 + ); + + if (mod.category == Category.Interface) { Render2DUtils.drawImage( new ResourceLocation("client/textures/modules/interface.png"), diff --git a/shared/java/top/fpsmaster/ui/click/music/MusicPanel.java b/shared/java/top/fpsmaster/ui/click/music/MusicPanel.java index 129bd691..855be3e1 100644 --- a/shared/java/top/fpsmaster/ui/click/music/MusicPanel.java +++ b/shared/java/top/fpsmaster/ui/click/music/MusicPanel.java @@ -193,7 +193,7 @@ public static void draw(float x, float y, float width, float height, int mouseX, } GL11.glEnable(GL11.GL_SCISSOR_TEST); - Render2DUtils.doGlScissor(x, y + 30, width, height - 60, scaleFactor); + Render2DUtils.doGlScissor(x, y, width, height - 30, scaleFactor); if (searchThread == null || !searchThread.isAlive()) { AtomicReference dY = new AtomicReference<>(y + 50 + container.getScroll()); AtomicReference musicHeight = new AtomicReference<>(0f); diff --git a/shared/java/top/fpsmaster/ui/click/music/NewMusicPanel.java b/shared/java/top/fpsmaster/ui/click/music/NewMusicPanel.java new file mode 100644 index 00000000..943720e2 --- /dev/null +++ b/shared/java/top/fpsmaster/ui/click/music/NewMusicPanel.java @@ -0,0 +1,43 @@ +package top.fpsmaster.ui.click.music; + +import net.minecraft.util.ResourceLocation; +import top.fpsmaster.FPSMaster; +import top.fpsmaster.modules.music.PlayList; +import top.fpsmaster.utils.render.Render2DUtils; + +import java.awt.*; + +public class NewMusicPanel { + + private static Thread playThread; + private static PlayList playList = new PlayList(); + private static PlayList displayList = new PlayList(); + + + public static void draw(float x, int y, float width, float height, int mouseX, int mouseY, int scaleFactor) { + Render2DUtils.drawImage(new ResourceLocation("client/gui/music.png"), x + 12, y + 14, 75, 16, -1); + FPSMaster.fontManager.s18.drawString("SuperSkidder", x + width - 80, y + 15, -1); + + + Render2DUtils.drawOptimizedRoundedRect(x + 20, y + 50, 100, 60, new Color(225,70,70)); + Render2DUtils.drawOptimizedRoundedRect(x + 20, y + 90, 100, 20, new Color(0,0,0,100)); + FPSMaster.fontManager.s24.drawString("每日推荐", x + 25, y + 55, -1); + FPSMaster.fontManager.s14.drawString("每日推荐,从『花日』听起", x + 25, y + 95, -1); + + Render2DUtils.drawOptimizedRoundedRect(x + 140, y + 50, 100, 60, new Color(113, 113, 113)); + Render2DUtils.drawOptimizedRoundedRect(x + 140, y + 90, 100, 20, new Color(0,0,0,100)); + FPSMaster.fontManager.s24.drawString("本地音乐", x + 145, y + 55, -1); + FPSMaster.fontManager.s14.drawString("共检测到22首本地音乐", x + 145, y + 95, -1); + + FPSMaster.fontManager.s22.drawString("收藏歌单", x + 20, y + 125, -1); + + } + + public static void keyTyped(char typedChar, int keyCode) { + + } + + public static void mouseClicked(int mouseX, int mouseY, int mouseButton) { + + } +} diff --git a/shared/java/top/fpsmaster/ui/click/music/components/PLayListComponent.java b/shared/java/top/fpsmaster/ui/click/music/components/PLayListComponent.java new file mode 100644 index 00000000..1d8a22ba --- /dev/null +++ b/shared/java/top/fpsmaster/ui/click/music/components/PLayListComponent.java @@ -0,0 +1,7 @@ +package top.fpsmaster.ui.click.music.components; + +public class PLayListComponent { + int playListId; + + +} diff --git a/shared/java/top/fpsmaster/utils/render/Render2DUtils.java b/shared/java/top/fpsmaster/utils/render/Render2DUtils.java index 57f4db36..949ac08e 100644 --- a/shared/java/top/fpsmaster/utils/render/Render2DUtils.java +++ b/shared/java/top/fpsmaster/utils/render/Render2DUtils.java @@ -72,7 +72,6 @@ public static void drawOptimizedRoundedRect(float x, float y, float width, float drawImage(resourceLocations[1], x + width - radius, y, radius, radius, color, rawImage); drawImage(resourceLocations[2], x, y + height - radius, radius, radius, color, rawImage); drawImage(resourceLocations[3], x + width - radius, y + height - radius, radius, radius, color, rawImage); - } public static void drawImage(ResourceLocation res, float x, float y, float width, float height, Color color) { diff --git a/shared/resources/assets/minecraft/client/gui/music.png b/shared/resources/assets/minecraft/client/gui/music.png new file mode 100644 index 0000000000000000000000000000000000000000..e5e86faad7c6cff6582c72b5b7ad3ac919e9173e GIT binary patch literal 2930 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 literal 0 HcmV?d00001 diff --git a/shared/resources/assets/minecraft/client/gui/settings/window/module.png b/shared/resources/assets/minecraft/client/gui/settings/window/module.png new file mode 100644 index 0000000000000000000000000000000000000000..018921f2b447dc2253b7faf011a512afd18fd30c GIT binary patch literal 1173 zcmeAS@N?(olHy`uVBq!ia0y~yV0r>%2XL?f$-smJeIUhH9OUlAuYjqdHMIm+s`G; z?+TXr_t$xj({B9)H|%^20>5m^jo~yAd z50_zJu-ojn{Bu=q?pw$G_x~H}pDxax4rCt5bli6QB2-*{l=&{hS2@!<==C7cVxCoVND) zMP~+vgsGfG3=AA9Cm0zNCMd8oG&nQ?ZDtx3Bql(f=H8a$V{7hxp~%3n!3&h4Zf|R^ zylfH*Ojv@p91IL$o}eUV;yd+v>E7$Wl;+CM#Ly6W3COxyx_5eb=+)6Ub}W}eeUgN+1c6r zKwnK4*N@XVH`n_6_1oL?|MNrxE&Lzcd@vyy2wuOsy83?Hj)I4;Cr_U2uCA`mZ+E1^ sOEY!;uR`?fy4+kE=+ZXK?E2Z<@D}eU|NP2lz@ml0)78&qol`;+0Gu4%;Q#;t literal 0 HcmV?d00001 diff --git a/shared/resources/assets/minecraft/client/gui/settings/window/option.png b/shared/resources/assets/minecraft/client/gui/settings/window/option.png new file mode 100644 index 0000000000000000000000000000000000000000..1cc0e52a7a3fcd37c07bfb22904ae4acfe37953c GIT binary patch literal 592 zcmV-W0Px#1am@3R0s$N2z&@+hyVZq`bk7VR7i={*D-6`Kor37)02Dx3v&n}&|nZ6jOSp~ z*|SFz`~}j0S8s)8Od&(SYoYxFCTMI{&jyj%WDo)mf(wWv$U-OSu0!$AV6}x3&iTVF zZ#aI#8}1M~5~Z}qIlru`>Y-_xR7zP(Da9L|x@nrUs;URh`6Z>acg&={9&pY-8iw(O zbH2;6Y@Md*mN7=FsuIU8_}@C64iG{d*L8=sZI3a={kpC{V~oEag|1dBeL9_fl~PWU zBw5CB{PY&EzvcV>!1KI?rfEOIFr3e3v*tHwUDw~5ruh&>(QTgRdlkq-mSuHEqtPc_ z*Efb?Tp@%IAcRm+6jxHp$tfTaLMYGkeH2BvQp!nD6u+R9(w=FWH%XE#PXT!-&+~nf zBumpYZz!cbAcV{~=Q~w9`KRJIe&U?(2q7~7fQu~4)~Zo$Wm&ccfD6zx?L1A>t!hwP zX_{^|O*;nwIAe@a)u6T*V-x_+KsDrF10lpSA;eJ)X^Rlz2qB(9O8Mxz?oc(TE!TC2 zQp!gVLfqT7Jys2B%eL*Y5aJ#fV=Iht-}n82YSim|-ydL%`;4&_IF9pDmgTkQc?-+3 zx~g%9EX(S8p0_B=^4f8nm-qE3K?tER4ClJ8Z-OAWQ@IAd?+=0?xYKog6NcgZFn>1> e=cAqCSL7!#XYOgyXXa zrGAstjA#Ep;(LqP|G!6X=%tLb%|+*|J?EQG(wn6GNH@2BS9sEHSz&_`k6y>6Q`UD> zyxXW!yPW+JgGaP~?3Jkg&ih5xmNs$iyY(ljCG2&MQuTeePldsFwrcNzmtjHCymN9z df4Ti*cGM4C=5lS@QJ{wyJYD@<);T3K0RZMwYuW$+ literal 0 HcmV?d00001 From 604e208cc80e188e90d2db555591f60ef7cd7ac6 Mon Sep 17 00:00:00 2001 From: SuperSkidder Date: Tue, 1 Jul 2025 00:30:45 +0800 Subject: [PATCH 058/193] remove client brand --- .../forge/mixin/MixinClientBrandRetriever.java | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinClientBrandRetriever.java b/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinClientBrandRetriever.java index 366d679d..04155ad8 100644 --- a/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinClientBrandRetriever.java +++ b/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinClientBrandRetriever.java @@ -7,12 +7,14 @@ @Mixin(ClientBrandRetriever.class) public class MixinClientBrandRetriever { + + //Some servers abandon any client they don't know, so we need to remove it temporarily until we can detect these servers and switch to vanilla brand automatically. /** * @author vlouboos * @reason Overwrite Tag */ - @Overwrite - public static String getClientModName() { - return "fpsmaster:" + GitInfo.getBranch() + ":" + GitInfo.getCommitIdAbbrev(); - } +// @Overwrite +// public static String getClientModName() { +// return "fpsmaster:" + GitInfo.getBranch() + ":" + GitInfo.getCommitIdAbbrev(); +// } } From 8fdf97ef23bc16f732d975dd08d28c3210b2bc24 Mon Sep 17 00:00:00 2001 From: SuperSkidder Date: Tue, 1 Jul 2025 01:00:31 +0800 Subject: [PATCH 059/193] feat&optimize optimize http request utility client commands will add to history now --- .../features/command/CommandManager.java | 3 + .../top/fpsmaster/utils/os/HttpRequest.java | 395 +++++------------- .../thirdparty/microsoft/MicrosoftLogin.java | 8 +- .../utils/thirdparty/openai/OpenAI.java | 38 +- 4 files changed, 117 insertions(+), 327 deletions(-) diff --git a/shared/java/top/fpsmaster/features/command/CommandManager.java b/shared/java/top/fpsmaster/features/command/CommandManager.java index 4007af69..5afaccd4 100644 --- a/shared/java/top/fpsmaster/features/command/CommandManager.java +++ b/shared/java/top/fpsmaster/features/command/CommandManager.java @@ -13,6 +13,8 @@ import java.util.ArrayList; import java.util.List; +import static top.fpsmaster.utils.Utility.mc; + public class CommandManager { private final List commands = new ArrayList<>(); @@ -30,6 +32,7 @@ public void onChat(EventSendChatMessage e) { if (e.msg.startsWith(ClientSettings.prefix.getValue())) { e.cancel(); try { + mc.ingameGUI.getChatGUI().addToSentMessages(e.msg); runCommand(e.msg.substring(1)); } catch (Exception ex) { ex.printStackTrace(); diff --git a/shared/java/top/fpsmaster/utils/os/HttpRequest.java b/shared/java/top/fpsmaster/utils/os/HttpRequest.java index db4f5d6f..bd14dc96 100644 --- a/shared/java/top/fpsmaster/utils/os/HttpRequest.java +++ b/shared/java/top/fpsmaster/utils/os/HttpRequest.java @@ -4,18 +4,18 @@ import com.google.gson.GsonBuilder; import com.google.gson.JsonObject; import org.apache.http.HttpEntity; +import org.apache.http.HttpResponse; import org.apache.http.NameValuePair; -import org.apache.http.ParseException; -import org.apache.http.client.ClientProtocolException; import org.apache.http.client.HttpClient; import org.apache.http.client.config.RequestConfig; import org.apache.http.client.entity.UrlEncodedFormEntity; import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.client.methods.HttpGet; import org.apache.http.client.methods.HttpPost; +import org.apache.http.client.methods.HttpRequestBase; +import org.apache.http.entity.StringEntity; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClients; -import org.apache.http.entity.StringEntity; import org.apache.http.message.BasicNameValuePair; import org.apache.http.util.EntityUtils; import top.fpsmaster.modules.logger.ClientLogger; @@ -23,348 +23,143 @@ import java.io.*; import java.nio.charset.StandardCharsets; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; import java.util.Map; -public class HttpRequest { - private static final HttpClient client = HttpClients.createDefault(); - private static final int TIMEOUT = 15000; +public final class HttpRequest { + // 共享线程安全的HTTP客户端 + private static final CloseableHttpClient HTTP_CLIENT = HttpClients.createDefault(); + // 默认超时设置(15秒) + private static final int DEFAULT_TIMEOUT = 15000; + + private HttpRequest() {} // 防止实例化 public static Gson gson() { return new GsonBuilder().setPrettyPrinting().disableHtmlEscaping().create(); } + // ================== GET 请求 ================== // public static String get(String url) { - return getWithCookie(url, ""); + return executeRequest(new HttpGet(url), null); } public static String getWithCookie(String url, String cookie) { - if (url == null || url.isEmpty()) { - throw new IllegalArgumentException("URL cannot be null or empty"); - } - HttpGet request = new HttpGet(url); - request.setHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36"); - - if (!cookie.isEmpty()) { - request.setHeader("Cookie", cookie.replace("\n", "")); - } - - try (AutoCloseableHttpResponse response = new AutoCloseableHttpResponse(client.execute(request)); - BufferedReader reader = new BufferedReader(new InputStreamReader(response.getHttpResponse().getEntity().getContent(), StandardCharsets.UTF_8))) { - StringBuilder builder = new StringBuilder(); - String line; - while ((line = reader.readLine()) != null) { - builder.append(line); - } - return builder.toString(); - } catch (IOException e) { - ClientLogger.error("Error during HTTP GET request to " + url + ": " + e.getMessage()); - } - return ""; + request.setHeader("Cookie", cookie.replace("\n", "")); + return executeRequest(request, null); } - public static void downloadFile(String url, String filepath) { - try { - HttpGet request = new HttpGet(url); - try (AutoCloseableHttpResponse response = new AutoCloseableHttpResponse(client.execute(request)); - InputStream is = response.getHttpResponse().getEntity().getContent(); - FileOutputStream fileout = new FileOutputStream(filepath)) { - - long totalLen = response.getHttpResponse().getEntity().getContentLength(); - long unit = totalLen / 100; - byte[] buffer = new byte[10 * 1024]; - long progress = 0; - int ch; - while ((ch = is.read(buffer)) != -1) { - fileout.write(buffer, 0, ch); - progress += ch; - if (progress % 10 == 0) { - ClientLogger.info("Downloaded " + progress / unit + "%"); - } - } - fileout.flush(); - } - } catch (Exception e) { - ClientLogger.error("Failed to download file from " + url + ": " + e.getMessage()); - e.printStackTrace(); - } + public static String get(String url, Map headers) { + return executeRequest(new HttpGet(url), headers); } - public static String[] sendPostRequest(String targetUrl, String body, Map headers) throws IOException { - String[] response = new String[2]; - HttpPost request = new HttpPost(targetUrl); - - // Add headers - for (Map.Entry entry : headers.entrySet()) { - request.setHeader(entry.getKey(), entry.getValue().trim()); - } - - // Add body - StringEntity entity = new StringEntity(body, StandardCharsets.UTF_8); - request.setEntity(entity); - - try (AutoCloseableHttpResponse httpResponse = new AutoCloseableHttpResponse(client.execute(request)); - BufferedReader reader = new BufferedReader(new InputStreamReader( - httpResponse.getHttpResponse().getEntity().getContent(), StandardCharsets.UTF_8))) { - - // Get the response code - response[0] = String.valueOf(httpResponse.getHttpResponse().getStatusLine().getStatusCode()); - - StringBuilder content = new StringBuilder(); - String inputLine; - while ((inputLine = reader.readLine()) != null) { - content.append(inputLine); - } - response[1] = content.toString(); - } - return response; + // ================== POST 请求 ================== // + public static String post(String url, String body) { + return post(url, body, "application/json"); } - public static void downloadAsync(String url, String filepath, Runnable callback) { - new Thread(() -> { - try { - downloadFile(url, filepath); - callback.run(); - } catch (Exception e) { - e.printStackTrace(); - } - }).start(); + public static String postJson(String url, JsonObject json) { + return post(url, json.toString(), "application/json"); } - /** - * 构建一个包含 Chrome 浏览器特征的 RequestConfig。 - * - * @return 配置好的 RequestConfig 实例。 - */ - private static RequestConfig buildRequestConfig() { - return RequestConfig.custom() - .setConnectTimeout(10000) // 设置连接主机服务超时时间 - .setConnectionRequestTimeout(10000) // 设置连接请求超时时间 - .setSocketTimeout(10000) // 设置读取数据连接超时时间 - .build(); + public static String postJson(String url, JsonObject json, Map headers) { + return post(url, json.toString(), "application/json", headers); } - /** - * 为 HTTP 请求设置 Chrome 浏览器特征头部。 - * - * @param request 可以是 HttpPost 或 HttpGet 实例。 - */ - private static void addChromeHeaders(org.apache.http.client.methods.HttpRequestBase request) { - request.setHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36"); - request.setHeader("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7"); - request.setHeader("Accept-Encoding", "gzip, deflate, br"); - request.setHeader("Accept-Language", "en-US,en;q=0.9,zh-CN;q=0.8,zh;q=0.7"); - request.setHeader("Connection", "keep-alive"); + public static String postForm(String url, Map params) { + HttpPost request = new HttpPost(url); + if (params != null && !params.isEmpty()) { + List formData = new ArrayList<>(); + params.forEach((k, v) -> formData.add(new BasicNameValuePair(k, v))); + request.setEntity(new UrlEncodedFormEntity(formData, StandardCharsets.UTF_8)); + } + return executeRequest(request, null); } - - /** - * 发送 HTTP POST 请求,请求体为原始字符串。 - * 默认 Content-Type 为 application/json,如果请求体是 JSON 格式。 - * - * @param url 请求的 URL。 - * @param body 请求体内容,通常为 JSON 字符串。 - * @return 响应体内容。 - * @throws RuntimeException 如果发生网络错误、协议错误或 HTTP 响应状态码非 2xx。 - */ - public static String post(String url, String body) { - // 使用 try-with-resources 确保 HttpClient 和 HttpResponse 自动关闭 - try (CloseableHttpClient httpClient = HttpClients.createDefault()) { - HttpPost httpPost = new HttpPost(url); - httpPost.setConfig(buildRequestConfig()); // 设置请求配置 - addChromeHeaders(httpPost); // 添加 Chrome 头部 - - // 假设 body 是 JSON 格式,设置 Content-Type 为 application/json - httpPost.setHeader("Content-Type", "application/json"); - - StringEntity stringEntity = new StringEntity(body, StandardCharsets.UTF_8); - httpPost.setEntity(stringEntity); - - try (CloseableHttpResponse httpResponse = httpClient.execute(httpPost)) { - return handleResponse(httpResponse, url); - } - } catch (ClientProtocolException e) { - throw new RuntimeException("HTTP POST 请求协议错误,URL: " + url, e); - } catch (IOException e) { - throw new RuntimeException("HTTP POST 请求 IO 错误,URL: " + url, e); - } catch (ParseException e) { - throw new RuntimeException("HTTP POST 响应解析错误,URL: " + url, e); + private static String post(String url, String body, String contentType) { + return post(url, body, contentType, null); + } + private static String post(String url, String body, String contentType, Map headers) { + HttpPost request = new HttpPost(url); + if (headers != null) { + headers.forEach(request::setHeader); } + if (body != null) { + StringEntity entity = new StringEntity(body, StandardCharsets.UTF_8); + entity.setContentType(contentType); + request.setEntity(entity); + } + return executeRequest(request, null); } - /** - * 发送 HTTP POST 请求,请求体为 JsonObject。 - * 默认 Content-Type 为 application/json。 - * - * @param url 请求的 URL。 - * @param jsonObject 请求体内容,JsonObject 实例。 - * @return 响应体内容。 - * @throws RuntimeException 如果发生网络错误、协议错误或 HTTP 响应状态码非 2xx。 - */ - public static String postURL(String url, JsonObject jsonObject) { - // 使用 try-with-resources 确保 HttpClient 和 HttpResponse 自动关闭 - try (CloseableHttpClient httpClient = HttpClients.createDefault()) { - HttpPost httpPost = new HttpPost(url); - httpPost.setConfig(buildRequestConfig()); // 设置请求配置 - addChromeHeaders(httpPost); // 添加 Chrome 头部 - - // 设置 Content-Type 为 application/json,因为是发送 JsonObject - httpPost.setHeader("Content-Type", "application/json"); - - StringEntity stringEntity = new StringEntity(jsonObject.toString(), StandardCharsets.UTF_8); - httpPost.setEntity(stringEntity); + // ================== 文件下载 ================== // + public static void downloadFile(String url, String filepath) { + try (InputStream is = HTTP_CLIENT.execute(new HttpGet(url)).getEntity().getContent(); + FileOutputStream fos = new FileOutputStream(filepath)) { - try (CloseableHttpResponse httpResponse = httpClient.execute(httpPost)) { - return handleResponse(httpResponse, url); + byte[] buffer = new byte[8192]; + int bytesRead; + while ((bytesRead = is.read(buffer)) != -1) { + fos.write(buffer, 0, bytesRead); } - } catch (ClientProtocolException e) { - throw new RuntimeException("HTTP POST 请求协议错误 (JsonObject),URL: " + url, e); - } catch (IOException e) { - throw new RuntimeException("HTTP POST 请求 IO 错误 (JsonObject),URL: " + url, e); - } catch (ParseException e) { - throw new RuntimeException("HTTP POST 响应解析错误 (JsonObject),URL: " + url, e); + } catch (Exception e) { + ClientLogger.error("Download failed: " + e.getMessage()); } } - /** - * 发送 HTTP POST 请求,请求体为 Map 形式的表单数据。 - * Content-Type 为 application/x-www-form-urlencoded。 - * - * @param url 请求的 URL。 - * @param param 请求参数的 Map。 - * @return 响应体内容。 - * @throws RuntimeException 如果发生网络错误、协议错误或 HTTP 响应状态码非 2xx。 - */ - public static String postMAP(String url, Map param) { - // 使用 try-with-resources 确保 HttpClient 和 HttpResponse 自动关闭 - try (CloseableHttpClient httpClient = HttpClients.createDefault()) { - HttpPost httpPost = new HttpPost(url); - httpPost.setConfig(buildRequestConfig()); // 设置请求配置 - addChromeHeaders(httpPost); // 添加 Chrome 头部 + public static void downloadAsync(String url, String filepath, Runnable callback) { + new Thread(() -> { + downloadFile(url, filepath); + callback.run(); + }).start(); + } - // Content-Type 默认为 application/x-www-form-urlencoded,因为是表单数据 - // httpPost.setHeader("Content-Type", "application/x-www-form-urlencoded"); // UrlEncodedFormEntity 会自动设置 + // ================== 核心执行方法 ================== // + private static String executeRequest(HttpRequestBase request, Map headers) { + try { + // 设置请求配置和默认头 + request.setConfig(buildRequestConfig()); + addDefaultHeaders(request); - // 创建参数列表 - if (param != null && !param.isEmpty()) { - List paramList = new ArrayList<>(); - for (Map.Entry entry : param.entrySet()) { - paramList.add(new BasicNameValuePair(entry.getKey(), entry.getValue())); - } - UrlEncodedFormEntity entity = new UrlEncodedFormEntity(paramList, StandardCharsets.UTF_8); - httpPost.setEntity(entity); + // 添加自定义头部 + if (headers != null) { + headers.forEach(request::addHeader); } - try (CloseableHttpResponse httpResponse = httpClient.execute(httpPost)) { - return handleResponse(httpResponse, url); + // 执行请求并处理响应 + try (CloseableHttpResponse response = HTTP_CLIENT.execute(request)) { + return handleResponse(response, request.getURI().toString()); } - } catch (ClientProtocolException e) { - throw new RuntimeException("HTTP POST 请求协议错误 (MAP),URL: " + url, e); - } catch (IOException e) { - throw new RuntimeException("HTTP POST 请求 IO 错误 (MAP),URL: " + url, e); - } catch (ParseException e) { - throw new RuntimeException("HTTP POST 响应解析错误 (MAP),URL: " + url, e); + } catch (Exception e) { + ClientLogger.error("Request failed: " + e.getMessage()); + return ""; } } - /** - * 发送 HTTP POST 请求,请求体为 JsonObject。 - * Content-Type 为 application/json。 - * - * @param url 请求的 URL。 - * @param jsonObject 请求体内容,JsonObject 实例。 - * @return 响应体内容。 - * @throws RuntimeException 如果发生网络错误、协议错误或 HTTP 响应状态码非 2xx。 - */ - public static String postJSON(String url, JsonObject jsonObject) { - // 使用 try-with-resources 确保 HttpClient 和 HttpResponse 自动关闭 - try (CloseableHttpClient httpClient = HttpClients.createDefault()) { - HttpPost httpPost = new HttpPost(url); - httpPost.setConfig(buildRequestConfig()); // 设置请求配置 - addChromeHeaders(httpPost); // 添加 Chrome 头部 - - httpPost.setHeader("Content-Type", "application/json"); - httpPost.setHeader("Accept", "application/json"); // 明确接受 JSON 响应 - - StringEntity stringEntity = new StringEntity(jsonObject.toString(), StandardCharsets.UTF_8); - httpPost.setEntity(stringEntity); - - try (CloseableHttpResponse httpResponse = httpClient.execute(httpPost)) { - return handleResponse(httpResponse, url); - } - } catch (ClientProtocolException e) { - throw new RuntimeException("HTTP POST 请求协议错误 (JSON),URL: " + url, e); - } catch (IOException e) { - throw new RuntimeException("HTTP POST 请求 IO 错误 (JSON),URL: " + url, e); - } catch (ParseException e) { - throw new RuntimeException("HTTP POST 响应解析错误 (JSON),URL: " + url, e); - } + // ================== 工具方法 ================== // + private static RequestConfig buildRequestConfig() { + return RequestConfig.custom() + .setConnectTimeout(DEFAULT_TIMEOUT) + .setConnectionRequestTimeout(DEFAULT_TIMEOUT) + .setSocketTimeout(DEFAULT_TIMEOUT) + .build(); } - /** - * 发送 HTTP GET 请求。 - * - * @param url 请求的 URL。 - * @param headers 额外的请求头部信息,可以覆盖默认的 Chrome 头部。 - * @return 响应体内容。 - * @throws RuntimeException 如果发生网络错误、协议错误或 HTTP 响应状态码非 2xx。 - */ - public static String get(String url, Map headers) { - // 使用 try-with-resources 确保 HttpClient 和 HttpResponse 自动关闭 - try (CloseableHttpClient httpClient = HttpClients.createDefault()) { - HttpGet httpGet = new HttpGet(url); - httpGet.setConfig(buildRequestConfig()); // 设置请求配置 - addChromeHeaders(httpGet); // 添加 Chrome 头部 + private static void addDefaultHeaders(HttpRequestBase request) { + request.setHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36"); + request.setHeader("Accept", "application/json, text/html, */*"); + request.setHeader("Accept-Language", "en-US,en;q=0.9"); + } - // 添加或覆盖用户提供的头部 - if (headers != null && !headers.isEmpty()) { - headers.forEach(httpGet::addHeader); - } + private static String handleResponse(HttpResponse response, String url) throws IOException { + int statusCode = response.getStatusLine().getStatusCode(); + HttpEntity entity = response.getEntity(); - try (CloseableHttpResponse httpResponse = httpClient.execute(httpGet)) { - return handleResponse(httpResponse, url); - } - } catch (ClientProtocolException e) { - throw new RuntimeException("HTTP GET 请求协议错误,URL: " + url, e); - } catch (IOException e) { - throw new RuntimeException("HTTP GET 请求 IO 错误,URL: " + url, e); - } catch (ParseException e) { - throw new RuntimeException("HTTP GET 响应解析错误,URL: " + url, e); + if (statusCode < 200 || statusCode >= 300) { + throw new IOException("HTTP Error: " + statusCode + " for URL: " + url); } - } - /** - * 处理 HTTP 响应,检查状态码并提取响应体。 - * - * @param httpResponse CloseableHttpResponse 实例。 - * @param url 请求的 URL。 - * @return 响应体内容。 - * @throws RuntimeException 如果响应状态码非 2xx 或响应实体为空。 - * @throws IOException 如果读取响应实体时发生 IO 错误。 - * @throws ParseException 如果解析响应实体时发生解析错误。 - */ - private static String handleResponse(CloseableHttpResponse httpResponse, String url) throws IOException, ParseException { - int statusCode = httpResponse.getStatusLine().getStatusCode(); - if (statusCode >= 200 && statusCode < 300) { // 2xx 表示成功 - HttpEntity responseEntity = httpResponse.getEntity(); - if (responseEntity != null) { - return EntityUtils.toString(responseEntity, StandardCharsets.UTF_8); - } else { - throw new RuntimeException("HTTP 请求成功,但响应实体为空。URL: " + url); - } - } else { - String errorResponse = ""; - if (httpResponse.getEntity() != null) { - try { - errorResponse = EntityUtils.toString(httpResponse.getEntity(), StandardCharsets.UTF_8); - } catch (IOException | ParseException e) { - // 忽略解析错误,只记录原始错误信息 - errorResponse = "无法解析错误响应体"; - } - } - throw new RuntimeException( - "HTTP 请求失败,状态码: " + statusCode + ", URL: " + url + ", 响应体: " + errorResponse); - } + return entity != null ? EntityUtils.toString(entity, StandardCharsets.UTF_8) : ""; } -} +} \ No newline at end of file diff --git a/shared/java/top/fpsmaster/utils/thirdparty/microsoft/MicrosoftLogin.java b/shared/java/top/fpsmaster/utils/thirdparty/microsoft/MicrosoftLogin.java index 8eac6e49..40b876d3 100644 --- a/shared/java/top/fpsmaster/utils/thirdparty/microsoft/MicrosoftLogin.java +++ b/shared/java/top/fpsmaster/utils/thirdparty/microsoft/MicrosoftLogin.java @@ -80,7 +80,7 @@ public static void startLocalHttpServer() { tokenRequestParams.put("grant_type", "authorization_code"); tokenRequestParams.put("redirect_uri", REDIRECT_URI); - String oauthResponse = HttpRequest.postMAP("https://login.live.com/oauth20_token.srf", tokenRequestParams); + String oauthResponse = HttpRequest.postForm("https://login.live.com/oauth20_token.srf", tokenRequestParams); logDebug("OAuth Response: " + oauthResponse); JsonObject oauthJson = HttpRequest.gson().fromJson(oauthResponse, JsonObject.class); String accessToken = getJsonString(oauthJson, "access_token", "OAuth access token"); @@ -179,7 +179,7 @@ private static void continueMinecraftAuthentication(String xboxAccessToken) thro xboxAuthPayload.addProperty("RelyingParty", "http://auth.xboxlive.com"); xboxAuthPayload.addProperty("TokenType", "JWT"); - String xboxAuthResponse = HttpRequest.postJSON("https://user.auth.xboxlive.com/user/authenticate", xboxAuthPayload); + String xboxAuthResponse = HttpRequest.postJson("https://user.auth.xboxlive.com/user/authenticate", xboxAuthPayload); logDebug("Xbox Auth Response: " + xboxAuthResponse); JsonObject xboxAuthJson = HttpRequest.gson().fromJson(xboxAuthResponse, JsonObject.class); String xblToken = getJsonString(xboxAuthJson, "Token", "XBL Token"); @@ -199,7 +199,7 @@ private static void continueMinecraftAuthentication(String xboxAccessToken) thro xstsPayload.addProperty("RelyingParty", "rp://api.minecraftservices.com/"); xstsPayload.addProperty("TokenType", "JWT"); - String xstsResponse = HttpRequest.postJSON("https://xsts.auth.xboxlive.com/xsts/authorize", xstsPayload); + String xstsResponse = HttpRequest.postJson("https://xsts.auth.xboxlive.com/xsts/authorize", xstsPayload); logDebug("XSTS Response: " + xstsResponse); JsonObject xstsJson = HttpRequest.gson().fromJson(xstsResponse, JsonObject.class); @@ -226,7 +226,7 @@ private static void continueMinecraftAuthentication(String xboxAccessToken) thro JsonObject minecraftAuthPayload = new JsonObject(); minecraftAuthPayload.addProperty("identityToken", "XBL3.0 x=" + xstsUserhash + ";" + xstsToken); - String minecraftAuthResponse = HttpRequest.postJSON("https://api.minecraftservices.com/authentication/login_with_xbox", minecraftAuthPayload); + String minecraftAuthResponse = HttpRequest.postJson("https://api.minecraftservices.com/authentication/login_with_xbox", minecraftAuthPayload); logDebug("Minecraft Auth Response: " + minecraftAuthResponse); JsonObject minecraftAuthJson = HttpRequest.gson().fromJson(minecraftAuthResponse, JsonObject.class); String mcAccessToken = getJsonString(minecraftAuthJson, "access_token", "Minecraft access token"); diff --git a/shared/java/top/fpsmaster/utils/thirdparty/openai/OpenAI.java b/shared/java/top/fpsmaster/utils/thirdparty/openai/OpenAI.java index 8c6e269a..72ffd8e0 100644 --- a/shared/java/top/fpsmaster/utils/thirdparty/openai/OpenAI.java +++ b/shared/java/top/fpsmaster/utils/thirdparty/openai/OpenAI.java @@ -37,15 +37,14 @@ public String requestNewAnswer(String question, JsonArray msgs) { JsonObject body = new JsonObject(); body.addProperty("model", model); body.add("messages", messages); - String json = body.toString(); Map hashMap = new HashMap<>(); hashMap.put("Content-Type", "application/json"); hashMap.put("Authorization", "Bearer " + openAiKey); - String[] text; + String text; try { - text = HttpRequest.sendPostRequest(baseUrl + "/chat/completions", json, hashMap); + text = HttpRequest.postJson(baseUrl + "/chat/completions", body, hashMap); } catch (Exception e) { throw new RuntimeException(e); } @@ -69,15 +68,14 @@ public String requestNewAnswer(String question) { JsonObject body = new JsonObject(); body.addProperty("model", model); body.add("messages", messages); - String json = body.toString(); Map hashMap = new HashMap<>(); hashMap.put("Content-Type", "application/json"); hashMap.put("Authorization", "Bearer " + openAiKey); - String[] text; + String text; try { - text = HttpRequest.sendPostRequest(baseUrl + "/chat/completions", json, hashMap); + text = HttpRequest.postJson(baseUrl + "/chat/completions", body, hashMap); } catch (Exception e) { ClientLogger.error("Translator", e.toString()); return ""; @@ -86,27 +84,21 @@ public String requestNewAnswer(String question) { return getString(text); } - private String getString(String[] response) { - if (response.length != 2) return "failed"; - - JsonObject responseJson = new JsonParser().parse(response[1]).getAsJsonObject(); - if ("200".equals(response[0])) { - return responseJson.getAsJsonArray("choices") - .get(0).getAsJsonObject() - .getAsJsonObject("message") - .getAsJsonObject("content") - .getAsString(); - } else { - JsonObject errorJson = responseJson.getAsJsonObject("error"); - throw new RuntimeException("OpenAI returned an error: " + errorJson.getAsJsonPrimitive("message").getAsString()); - } + private String getString(String response) { + JsonObject responseJson = new JsonParser().parse(response).getAsJsonObject(); + return responseJson.getAsJsonArray("choices") + .get(0).getAsJsonObject() + .getAsJsonObject("message") + .getAsJsonObject("content") + .getAsString(); + } public static String[] requestClientAI(String prompt, String model, JsonArray messages) { try { - String sendPostRequest = HttpRequest.sendPostRequest( + String sendPostRequest = HttpRequest.postJson( FPSMaster.SERVICE_API + "/chat?timestamp=" + System.currentTimeMillis(), - new Gson().toJson(messages), + messages.getAsJsonObject(), new HashMap() {{ put("Content-Type", "application/json"); put("username", FPSMaster.accountManager.getUsername()); @@ -114,7 +106,7 @@ public static String[] requestClientAI(String prompt, String model, JsonArray me put("model", model); put("prompt", prompt); }} - )[1]; + ); if (!sendPostRequest.isEmpty()) { JsonObject json = new JsonParser().parse(sendPostRequest).getAsJsonObject(); From 444b2bb459c61dff4e3c91a278bd88bb6ff79034 Mon Sep 17 00:00:00 2001 From: SuperSkidder Date: Wed, 2 Jul 2025 00:10:47 +0800 Subject: [PATCH 060/193] feat: lunar block animation --- .../impl/optimizes/OldAnimations.java | 2 +- .../assets/minecraft/client/lang/zh_cn.lang | 1 + .../forge/mixin/MixinItemRenderer.java | 20 +++++++++++++++++-- 3 files changed, 20 insertions(+), 3 deletions(-) diff --git a/shared/java/top/fpsmaster/features/impl/optimizes/OldAnimations.java b/shared/java/top/fpsmaster/features/impl/optimizes/OldAnimations.java index eb11e6a4..3468837b 100644 --- a/shared/java/top/fpsmaster/features/impl/optimizes/OldAnimations.java +++ b/shared/java/top/fpsmaster/features/impl/optimizes/OldAnimations.java @@ -17,7 +17,7 @@ public class OldAnimations extends Module { public static BooleanSetting noShield = new BooleanSetting("NoShield", true); public static BooleanSetting animationSneak = new BooleanSetting("AnimationSneak", true); public static BooleanSetting oldBlock = new BooleanSetting("OldBlock", true); - public static ModeSetting animationMode = new ModeSetting("AnimationMode", 0, () -> oldBlock.getValue(), "1.7", "Swang", "Sigma", "Swank", "Swong", "Debug", "Luna", "Jigsaw", "Jello", "Push"); + public static ModeSetting animationMode = new ModeSetting("AnimationMode", 0, () -> oldBlock.getValue(), "Lunar", "1.7", "Swang", "Sigma", "Swank", "Swong", "Debug", "Luna", "Jigsaw", "Jello", "Push"); public static BooleanSetting oldRod = new BooleanSetting("OldRod", true); public static BooleanSetting oldBow = new BooleanSetting("OldBow", true); public static BooleanSetting oldSwing = new BooleanSetting("OldSwing", true); diff --git a/shared/resources/assets/minecraft/client/lang/zh_cn.lang b/shared/resources/assets/minecraft/client/lang/zh_cn.lang index a20bfce3..8fc591a9 100644 --- a/shared/resources/assets/minecraft/client/lang/zh_cn.lang +++ b/shared/resources/assets/minecraft/client/lang/zh_cn.lang @@ -248,6 +248,7 @@ oldanimations.blockz=格挡Z oldanimations.animationmode=格挡动画 oldanimations.animationsneak=潜行动画 oldanimations.animationmode.1.7=1.7 +oldanimations.animationmode.lunar=Lunar oldanimations.animationmode.swang=Swang oldanimations.animationmode.sigma=Sigma oldanimations.animationmode.swank=Swank diff --git a/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinItemRenderer.java b/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinItemRenderer.java index f7cda7e2..e9df6860 100644 --- a/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinItemRenderer.java +++ b/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinItemRenderer.java @@ -114,11 +114,27 @@ public void renderFireInFirstPerson(CallbackInfo ci) { } + private void transformFirstPersonItemLunar(float equipProgress, float swingProgress) { + GlStateManager.translate(0.07F, -0.14F, -0.11F); + GlStateManager.translate(0.56F, -0.52F, -0.71999997F); + GlStateManager.rotate(45.0F, 0.0F, 1.0F, 0.0F); + float f = MathHelper.sin(swingProgress * swingProgress * (float)Math.PI); + float f1 = MathHelper.sin(MathHelper.sqrt_float(swingProgress) * (float)Math.PI); + GlStateManager.rotate(f * -20.0F, 0.0F, 1.0F, 0.0F); + GlStateManager.rotate(f1 * -20.0F, 0.0F, 0.0F, 1.0F); + GlStateManager.rotate(f1 * -80.0F, 1.0F, 0.0F, 0.0F); + GlStateManager.scale(0.4F, 0.4F, 0.4F); + } + private void drawBlocking(float equippedProgress, float swingProgress) { GL11.glTranslated(OldAnimations.x.getValue().floatValue(), OldAnimations.y.getValue().floatValue(), OldAnimations.z.getValue().floatValue()); // GL11.glScaled(OldAnimations.scale.getValue().floatValue(), OldAnimations.scale.getValue().floatValue(), 0); - if (OldAnimations.animationMode.isMode("Sigma")) { - this.transformFirstPersonItem(swingProgress, 0.0f); + if(OldAnimations.animationMode.isMode("Lunar")){ + this.transformFirstPersonItemLunar(0.2f, swingProgress); + this.doBlockTransformations(); + GlStateManager.translate(-0.5, 0.2, 0.0); + } else if (OldAnimations.animationMode.isMode("Sigma")) { + this.transformFirstPersonItem(equippedProgress, swingProgress); float swong = MathHelper.sin((float) (MathHelper.sqrt_float(equippedProgress) * Math.PI)); GlStateManager.rotate(-swong * 55 / 2.0F, -8.0F, -0.0F, 9.0F); GlStateManager.rotate(-swong * 45, 1.0F, swong / 2, -0.0F); From 29ed02063b960a78e4e2b525d7655b9b9d2fc989 Mon Sep 17 00:00:00 2001 From: SuperSkidder Date: Wed, 2 Jul 2025 00:12:03 +0800 Subject: [PATCH 061/193] change: made account autologin async --- .../modules/account/AccountManager.java | 32 ++++++++++--------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/shared/java/top/fpsmaster/modules/account/AccountManager.java b/shared/java/top/fpsmaster/modules/account/AccountManager.java index af9af4f7..c0a0d403 100644 --- a/shared/java/top/fpsmaster/modules/account/AccountManager.java +++ b/shared/java/top/fpsmaster/modules/account/AccountManager.java @@ -13,23 +13,25 @@ public class AccountManager { private String[] itemsHeld = new String[0]; public void autoLogin() { - try { - token = FileUtils.readTempValue("token").trim(); - username = FPSMaster.configManager.configure.getOrCreate("username", "").trim(); // Since we do the empty check, we should make it empty. - if (!token.isEmpty() && !username.isEmpty()) { - if (attemptLogin(username, token)) { - ClientLogger.info("自动登录成功! " + username); - FPSMaster.INSTANCE.loggedIn = true; - getItems(username, token); - } else { - ClientLogger.info(username); - ClientLogger.error("自动登录失败!"); + FPSMaster.async.runnable(()->{ + try { + token = FileUtils.readTempValue("token").trim(); + username = FPSMaster.configManager.configure.getOrCreate("username", "").trim(); // Since we do the empty check, we should make it empty. + if (!token.isEmpty() && !username.isEmpty()) { + if (attemptLogin(username, token)) { + ClientLogger.info("自动登录成功! " + username); + FPSMaster.INSTANCE.loggedIn = true; + getItems(username, token); + } else { + ClientLogger.info(username); + ClientLogger.error("自动登录失败!"); + } } + } catch (Exception e) { + e.printStackTrace(); + ClientLogger.error("尝试自动登录失败!" + e.getMessage()); } - } catch (Exception e) { - e.printStackTrace(); - ClientLogger.error("尝试自动登录失败!" + e.getMessage()); - } + }); } private boolean attemptLogin(String username, String token) { From f475e279494071609bd1419350d902870e55197e Mon Sep 17 00:00:00 2001 From: SuperSkidder Date: Wed, 2 Jul 2025 01:01:43 +0800 Subject: [PATCH 062/193] feat: better ExceptionHandler --- .../top/fpsmaster/event/EventDispatcher.java | 9 +- .../fpsmaster/exception/AccountException.java | 26 +++++ .../fpsmaster/exception/ExceptionHandler.java | 104 ++++++++++++++++++ .../fpsmaster/exception/FileException.java | 26 +++++ .../fpsmaster/exception/ModuleException.java | 26 +++++ .../fpsmaster/exception/NetworkException.java | 26 +++++ .../modules/account/AccountManager.java | 100 +++++++++++------ .../fpsmaster/ui/click/music/MusicPanel.java | 30 +++-- .../ui/screens/oobe/impls/Login.java | 21 +++- .../top/fpsmaster/utils/os/FileUtils.java | 57 ++++++---- 10 files changed, 358 insertions(+), 67 deletions(-) create mode 100644 shared/java/top/fpsmaster/exception/AccountException.java create mode 100644 shared/java/top/fpsmaster/exception/ExceptionHandler.java create mode 100644 shared/java/top/fpsmaster/exception/FileException.java create mode 100644 shared/java/top/fpsmaster/exception/ModuleException.java create mode 100644 shared/java/top/fpsmaster/exception/NetworkException.java diff --git a/shared/java/top/fpsmaster/event/EventDispatcher.java b/shared/java/top/fpsmaster/event/EventDispatcher.java index 5e1b8a0c..1da5a746 100644 --- a/shared/java/top/fpsmaster/event/EventDispatcher.java +++ b/shared/java/top/fpsmaster/event/EventDispatcher.java @@ -1,5 +1,6 @@ package top.fpsmaster.event; +import top.fpsmaster.exception.ExceptionHandler; import top.fpsmaster.modules.logger.ClientLogger; import java.lang.reflect.Method; import java.util.HashMap; @@ -38,7 +39,13 @@ public static void dispatchEvent(Event event) { listener.invoke(event); } catch (Throwable e) { ClientLogger.warn("Failed to dispatch event " + event.getClass().getSimpleName() + " to listener " + listener.getLog()); - e.printStackTrace(); + if (e instanceof Exception) { + ExceptionHandler.handleModuleException((Exception) e, "Failed to dispatch event " + event.getClass().getSimpleName()); + } else { + // For non-Exception Throwables, we still need to log them + top.fpsmaster.modules.logger.ClientLogger.error("Non-Exception Throwable: " + e.getMessage()); + e.printStackTrace(); + } } } } diff --git a/shared/java/top/fpsmaster/exception/AccountException.java b/shared/java/top/fpsmaster/exception/AccountException.java new file mode 100644 index 00000000..71b650fa --- /dev/null +++ b/shared/java/top/fpsmaster/exception/AccountException.java @@ -0,0 +1,26 @@ +package top.fpsmaster.exception; + +/** + * Exception thrown when there is an error related to account operations. + */ +public class AccountException extends Exception { + + /** + * Constructs a new AccountException with the specified detail message. + * + * @param message the detail message + */ + public AccountException(String message) { + super(message); + } + + /** + * Constructs a new AccountException with the specified detail message and cause. + * + * @param message the detail message + * @param cause the cause + */ + public AccountException(String message, Throwable cause) { + super(message, cause); + } +} \ No newline at end of file diff --git a/shared/java/top/fpsmaster/exception/ExceptionHandler.java b/shared/java/top/fpsmaster/exception/ExceptionHandler.java new file mode 100644 index 00000000..a5739a93 --- /dev/null +++ b/shared/java/top/fpsmaster/exception/ExceptionHandler.java @@ -0,0 +1,104 @@ +package top.fpsmaster.exception; + +import top.fpsmaster.modules.logger.ClientLogger; + +import java.io.PrintWriter; +import java.io.StringWriter; + +/** + * Centralized exception handler for the FPSMaster application. + * This class provides methods to handle different types of exceptions in a consistent way. + */ +public class ExceptionHandler { + + /** + * Handles any exception by logging it and optionally taking additional actions. + * + * @param e The exception to handle + * @param message Additional context message + */ + public static void handle(Exception e, String message) { + ClientLogger.error(message + ": " + e.getMessage()); + logExceptionDetails(e, "General"); + } + + /** + * Handles any exception by logging it. + * + * @param e The exception to handle + */ + public static void handle(Exception e) { + handle(e, "An error occurred"); + } + + /** + * Handles a specific type of exception related to account operations. + * + * @param e The exception to handle + * @param message Additional context message + */ + public static void handleAccountException(Exception e, String message) { + ClientLogger.error("Account error: " + message + ": " + e.getMessage()); + logExceptionDetails(e, "Account"); + } + + /** + * Handles a specific type of exception related to file operations. + * + * @param e The exception to handle + * @param message Additional context message + */ + public static void handleFileException(Exception e, String message) { + ClientLogger.error("File operation error: " + message + ": " + e.getMessage()); + logExceptionDetails(e, "File"); + } + + /** + * Handles a specific type of exception related to network operations. + * + * @param e The exception to handle + * @param message Additional context message + */ + public static void handleNetworkException(Exception e, String message) { + ClientLogger.error("Network error: " + message + ": " + e.getMessage()); + logExceptionDetails(e, "Network"); + } + + /** + * Handles a specific type of exception related to module operations. + * + * @param e The exception to handle + * @param message Additional context message + */ + public static void handleModuleException(Exception e, String message) { + ClientLogger.error("Module error: " + message + ": " + e.getMessage()); + logExceptionDetails(e, "Module"); + } + + /** + * Logs detailed information about an exception in a structured way. + * + * @param e The exception to log + * @param category The category of the exception for better organization + */ + private static void logExceptionDetails(Exception e, String category) { + ClientLogger.error(category + " Exception", "Type: " + e.getClass().getName()); + + // Get the cause if available + Throwable cause = e.getCause(); + if (cause != null) { + ClientLogger.error(category + " Exception", "Caused by: " + cause.getClass().getName() + ": " + cause.getMessage()); + } + + // Log stack trace in a structured way + StringWriter sw = new StringWriter(); + PrintWriter pw = new PrintWriter(sw); + e.printStackTrace(pw); + + // Split the stack trace into lines and log each line + String[] stackTraceLines = sw.toString().split("\\r?\\n"); + for (String line : stackTraceLines) { + ClientLogger.debug(line); + } + } +} diff --git a/shared/java/top/fpsmaster/exception/FileException.java b/shared/java/top/fpsmaster/exception/FileException.java new file mode 100644 index 00000000..33846d09 --- /dev/null +++ b/shared/java/top/fpsmaster/exception/FileException.java @@ -0,0 +1,26 @@ +package top.fpsmaster.exception; + +/** + * Exception thrown when there is an error related to file operations. + */ +public class FileException extends Exception { + + /** + * Constructs a new FileException with the specified detail message. + * + * @param message the detail message + */ + public FileException(String message) { + super(message); + } + + /** + * Constructs a new FileException with the specified detail message and cause. + * + * @param message the detail message + * @param cause the cause + */ + public FileException(String message, Throwable cause) { + super(message, cause); + } +} \ No newline at end of file diff --git a/shared/java/top/fpsmaster/exception/ModuleException.java b/shared/java/top/fpsmaster/exception/ModuleException.java new file mode 100644 index 00000000..7e13b878 --- /dev/null +++ b/shared/java/top/fpsmaster/exception/ModuleException.java @@ -0,0 +1,26 @@ +package top.fpsmaster.exception; + +/** + * Exception thrown when there is an error related to module operations. + */ +public class ModuleException extends Exception { + + /** + * Constructs a new ModuleException with the specified detail message. + * + * @param message the detail message + */ + public ModuleException(String message) { + super(message); + } + + /** + * Constructs a new ModuleException with the specified detail message and cause. + * + * @param message the detail message + * @param cause the cause + */ + public ModuleException(String message, Throwable cause) { + super(message, cause); + } +} \ No newline at end of file diff --git a/shared/java/top/fpsmaster/exception/NetworkException.java b/shared/java/top/fpsmaster/exception/NetworkException.java new file mode 100644 index 00000000..6460414c --- /dev/null +++ b/shared/java/top/fpsmaster/exception/NetworkException.java @@ -0,0 +1,26 @@ +package top.fpsmaster.exception; + +/** + * Exception thrown when there is an error related to network operations. + */ +public class NetworkException extends Exception { + + /** + * Constructs a new NetworkException with the specified detail message. + * + * @param message the detail message + */ + public NetworkException(String message) { + super(message); + } + + /** + * Constructs a new NetworkException with the specified detail message and cause. + * + * @param message the detail message + * @param cause the cause + */ + public NetworkException(String message, Throwable cause) { + super(message, cause); + } +} \ No newline at end of file diff --git a/shared/java/top/fpsmaster/modules/account/AccountManager.java b/shared/java/top/fpsmaster/modules/account/AccountManager.java index c0a0d403..5b8ba597 100644 --- a/shared/java/top/fpsmaster/modules/account/AccountManager.java +++ b/shared/java/top/fpsmaster/modules/account/AccountManager.java @@ -3,6 +3,10 @@ import com.google.gson.JsonObject; import com.google.gson.JsonParser; import top.fpsmaster.FPSMaster; +import top.fpsmaster.exception.AccountException; +import top.fpsmaster.exception.ExceptionHandler; +import top.fpsmaster.exception.FileException; +import top.fpsmaster.exception.NetworkException; import top.fpsmaster.modules.logger.ClientLogger; import top.fpsmaster.utils.os.FileUtils; import top.fpsmaster.utils.os.HttpRequest; @@ -13,45 +17,68 @@ public class AccountManager { private String[] itemsHeld = new String[0]; public void autoLogin() { - FPSMaster.async.runnable(()->{ + FPSMaster.async.runnable(() -> { try { - token = FileUtils.readTempValue("token").trim(); - username = FPSMaster.configManager.configure.getOrCreate("username", "").trim(); // Since we do the empty check, we should make it empty. - if (!token.isEmpty() && !username.isEmpty()) { - if (attemptLogin(username, token)) { - ClientLogger.info("自动登录成功! " + username); - FPSMaster.INSTANCE.loggedIn = true; - getItems(username, token); - } else { - ClientLogger.info(username); - ClientLogger.error("自动登录失败!"); - } - } + doAutoLogin(); + } catch (FileException e) { + ExceptionHandler.handleFileException(e, "尝试自动登录失败"); + } catch (AccountException e) { + ExceptionHandler.handleAccountException(e, "尝试自动登录失败"); + } catch (NetworkException e) { + ExceptionHandler.handleNetworkException(e, "尝试自动登录失败"); } catch (Exception e) { - e.printStackTrace(); - ClientLogger.error("尝试自动登录失败!" + e.getMessage()); + ExceptionHandler.handle(e, "尝试自动登录失败"); } }); } - private boolean attemptLogin(String username, String token) { + private void doAutoLogin() throws FileException, AccountException, NetworkException { + token = FileUtils.readTempValue("token").trim(); + username = FPSMaster.configManager.configure.getOrCreate("username", "").trim(); // Since we do the empty check, we should make it empty. + if (!token.isEmpty() && !username.isEmpty()) { + if (attemptLogin(username, token)) { + ClientLogger.info("自动登录成功! " + username); + FPSMaster.INSTANCE.loggedIn = true; + getItems(username, token); + } else { + ClientLogger.info(username); + ClientLogger.error("自动登录失败!"); + throw new AccountException("自动登录失败"); + } + } + } + + private boolean attemptLogin(String username, String token) throws NetworkException { if (username.isEmpty() || token.isEmpty()) { return false; } - String s = HttpRequest.get(FPSMaster.SERVICE_API + "/checkToken?username=" + username + "&token=" + token + "×tamp=" + System.currentTimeMillis()); - JsonObject json = parser.parse(s).getAsJsonObject(); - this.username = username; - this.token = token; - return json.get("code").getAsInt() == 200; + try { + String s = HttpRequest.get(FPSMaster.SERVICE_API + "/checkToken?username=" + username + "&token=" + token + "×tamp=" + System.currentTimeMillis()); + JsonObject json = parser.parse(s).getAsJsonObject(); + this.username = username; + this.token = token; + return json.get("code").getAsInt() == 200; + } catch (Exception e) { + throw new NetworkException("Failed to check token", e); + } } - public void getItems(String username, String token) { - String s = HttpRequest.get(FPSMaster.SERVICE_API + "/getWebUser?username=" + username + "&token=" + token + "×tamp=" + System.currentTimeMillis()); - JsonObject json = parser.parse(s).getAsJsonObject(); - if (json.get("code").getAsInt() == 200) { - String items = json.getAsJsonObject("data").getAsJsonObject("items").getAsString(); - itemsHeld = items.split(","); - itemsHeld = itemsHeld.length > 0 ? itemsHeld : new String[0]; // Ensuring it's not empty + public void getItems(String username, String token) throws NetworkException { + try { + String s = HttpRequest.get(FPSMaster.SERVICE_API + "/getWebUser?username=" + username + "&token=" + token + "×tamp=" + System.currentTimeMillis()); + JsonObject json = parser.parse(s).getAsJsonObject(); + if (json.get("code").getAsInt() == 200) { + String items = json.getAsJsonObject("data").getAsJsonObject("items").getAsString(); + itemsHeld = items.split(","); + itemsHeld = itemsHeld.length > 0 ? itemsHeld : new String[0]; // Ensuring it's not empty + } else { + throw new NetworkException("Failed to get items: " + json.get("message").getAsString()); + } + } catch (Exception e) { + if (e instanceof NetworkException) { + throw (NetworkException) e; + } + throw new NetworkException("Failed to get items", e); } } @@ -59,9 +86,20 @@ public void getItems(String username, String token) { public static String cape = ""; public static String skin = ""; - public static JsonObject login(String username, String password) { - String s = HttpRequest.get(FPSMaster.SERVICE_API + "/login?username=" + username + "&password=" + password + "×tamp=" + System.currentTimeMillis()); - return parser.parse(s).getAsJsonObject(); + public static JsonObject login(String username, String password) throws NetworkException { + try { + String s = HttpRequest.get(FPSMaster.SERVICE_API + "/login?username=" + username + "&password=" + password + "×tamp=" + System.currentTimeMillis()); + JsonObject jsonObject = parser.parse(s).getAsJsonObject(); + if (jsonObject.get("code").getAsInt() != 200) { + throw new NetworkException("Login failed: " + jsonObject.get("message").getAsString()); + } + return jsonObject; + } catch (Exception e) { + if (e instanceof NetworkException) { + throw (NetworkException) e; + } + throw new NetworkException("Login failed", e); + } } // Getter and Setter methods diff --git a/shared/java/top/fpsmaster/ui/click/music/MusicPanel.java b/shared/java/top/fpsmaster/ui/click/music/MusicPanel.java index 855be3e1..f2be6a39 100644 --- a/shared/java/top/fpsmaster/ui/click/music/MusicPanel.java +++ b/shared/java/top/fpsmaster/ui/click/music/MusicPanel.java @@ -7,6 +7,8 @@ import org.lwjgl.input.Mouse; import org.lwjgl.opengl.GL11; import top.fpsmaster.FPSMaster; +import top.fpsmaster.exception.ExceptionHandler; +import top.fpsmaster.exception.FileException; import top.fpsmaster.modules.music.AbstractMusic; import top.fpsmaster.modules.music.JLayerHelper; import top.fpsmaster.modules.music.MusicPlayer; @@ -360,7 +362,11 @@ private static void reloadImg() { String element = loginStatus.get("nickname").getAsString(); if (element != null) { nickname = element; - FileUtils.saveTempValue("nickname", nickname); + try { + FileUtils.saveTempValue("nickname", nickname); + } catch (FileException e) { + ExceptionHandler.handleFileException(e, "无法保存昵称"); + } } } if (code == 803) { @@ -369,8 +375,12 @@ private static void reloadImg() { String result = "MUSIC_U=" + extractMiddleContent(asString, "MUSIC_U=", ";") + "; " + "NMTID=" + extractMiddleContent(asString, "NMTID=", ";"); NeteaseApi.cookies = result; - FileUtils.saveTempValue("cookies", NeteaseApi.cookies); - System.out.println("cookies: " + NeteaseApi.cookies); + try { + FileUtils.saveTempValue("cookies", NeteaseApi.cookies); + System.out.println("cookies: " + NeteaseApi.cookies); + } catch (FileException e) { + ExceptionHandler.handleFileException(e, "无法保存cookies"); + } } Thread.sleep(1000); } catch (InterruptedException e) { @@ -391,10 +401,14 @@ private static void reloadImg() { File qr = new File(FileUtils.dir, "/music/qr.png"); File qrf = new File(FileUtils.dir, "/music"); qrf.mkdirs(); - FileUtils.saveFileBytes("/music/qr.png", bytes); - ThreadDownloadImageData textureArt = new ThreadDownloadImageData(qr, null, null, null); - textureManager.loadTexture(resourceLocation, textureArt); - loginThread.start(); + try { + FileUtils.saveFileBytes("/music/qr.png", bytes); + ThreadDownloadImageData textureArt = new ThreadDownloadImageData(qr, null, null, null); + textureManager.loadTexture(resourceLocation, textureArt); + loginThread.start(); + } catch (FileException e) { + ExceptionHandler.handleFileException(e, "无法保存二维码图片"); + } }); } @@ -411,4 +425,4 @@ private static void run() { searchThread = null; } } -} \ No newline at end of file +} diff --git a/shared/java/top/fpsmaster/ui/screens/oobe/impls/Login.java b/shared/java/top/fpsmaster/ui/screens/oobe/impls/Login.java index 942821d4..50cdfe61 100644 --- a/shared/java/top/fpsmaster/ui/screens/oobe/impls/Login.java +++ b/shared/java/top/fpsmaster/ui/screens/oobe/impls/Login.java @@ -4,6 +4,9 @@ import net.minecraft.client.Minecraft; import net.minecraft.client.gui.ScaledResolution; import top.fpsmaster.FPSMaster; +import top.fpsmaster.exception.ExceptionHandler; +import top.fpsmaster.exception.FileException; +import top.fpsmaster.exception.NetworkException; import top.fpsmaster.modules.account.AccountManager; import top.fpsmaster.ui.common.TextField; import top.fpsmaster.ui.screens.oobe.Scene; @@ -36,7 +39,7 @@ public Login(boolean isOOBE) { if (!defaultText.isEmpty()) { // If there's a value "offline", strange bug happens. username.setText(defaultText); } - + btn = new GuiButton(FPSMaster.i18n.get("oobe.login.login"), () -> { try { JsonObject login = AccountManager.login(username.getText(), password.getText()); @@ -45,7 +48,11 @@ public Login(boolean isOOBE) { FPSMaster.accountManager.setUsername(username.getText()); FPSMaster.accountManager.setToken(login.get("msg").getAsString()); } - FileUtils.saveTempValue("token", FPSMaster.accountManager.getToken()); + try { + FileUtils.saveTempValue("token", FPSMaster.accountManager.getToken()); + } catch (FileException e) { + ExceptionHandler.handleFileException(e, "无法保存登录令牌"); + } FPSMaster.INSTANCE.loggedIn = true; if (isOOBE) { FPSMaster.oobeScreen.nextScene(); @@ -56,8 +63,12 @@ public Login(boolean isOOBE) { msg = login.get("msg").getAsString(); msgbox = true; } + } catch (NetworkException e) { + ExceptionHandler.handleNetworkException(e, "登录失败"); + msg = "网络错误: " + e.getMessage(); + msgbox = true; } catch (Exception e) { - e.printStackTrace(); + ExceptionHandler.handle(e, "登录失败"); msg = "未知错误: " + e.getMessage(); msgbox = true; } @@ -78,7 +89,7 @@ public Login(boolean isOOBE) { public void drawScreen(int mouseX, int mouseY, float partialTicks) { super.drawScreen(mouseX, mouseY, partialTicks); ScaledResolution sr = new ScaledResolution(Minecraft.getMinecraft()); - + Render2DUtils.drawRect(0f, 0f, sr.getScaledWidth(), sr.getScaledHeight(), new Color(235, 242, 255).getRGB()); FPSMaster.fontManager.s24.drawCenteredString(FPSMaster.i18n.get("oobe.login.desc"), sr.getScaledWidth() / 2f, sr.getScaledHeight() / 2f - 90, FPSMaster.theme.getTextColorDescription().getRGB()); @@ -121,7 +132,7 @@ public void mouseClick(int mouseX, int mouseY, int mouseButton) { try { desktop.browse(new URI(url)); } catch (Exception e) { - e.printStackTrace(); + ExceptionHandler.handle(e, "无法打开网页"); } } } diff --git a/shared/java/top/fpsmaster/utils/os/FileUtils.java b/shared/java/top/fpsmaster/utils/os/FileUtils.java index 5cd7a797..c325bca2 100644 --- a/shared/java/top/fpsmaster/utils/os/FileUtils.java +++ b/shared/java/top/fpsmaster/utils/os/FileUtils.java @@ -1,5 +1,6 @@ package top.fpsmaster.utils.os; +import top.fpsmaster.exception.FileException; import top.fpsmaster.interfaces.ProviderManager; import top.fpsmaster.modules.logger.ClientLogger; import top.fpsmaster.wrapper.Constants; @@ -53,55 +54,60 @@ public static File file(File parent, String child) { return file; } - public static void saveFileBytes(String s, byte[] bytes) { + public static void saveFileBytes(String s, byte[] bytes) throws FileException { File file = new File(dir, s); try { if (!file.exists()) { - file.createNewFile(); + if (!file.createNewFile()) { + throw new FileException("Failed to create file: " + s); + } } try (FileOutputStream fOut = new FileOutputStream(file)) { fOut.write(bytes); fOut.flush(); } - } catch (IOException e) { - e.printStackTrace(); + } catch (IOException e) { + throw new FileException("Failed to save file bytes: " + s, e); } } - public static void saveFile(String name, String content) { + public static void saveFile(String name, String content) throws FileException { File file = new File(dir, name); saveAbsoluteFile(file.getAbsolutePath(), content); } - private static void saveAbsoluteFile(String name, String content) { + private static void saveAbsoluteFile(String name, String content) throws FileException { File file = new File(name); try { if (!file.exists()) { if (!file.createNewFile()) { ClientLogger.error("FileUtils", "failed to create " + name); + throw new FileException("Failed to create file: " + name); } } try (BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(Files.newOutputStream(file.toPath()), StandardCharsets.UTF_8))) { bw.write(content); bw.flush(); } - } catch (IOException e) { - e.printStackTrace(); + } catch (IOException e) { + throw new FileException("Failed to save file: " + name, e); } } - public static void saveTempValue(String name, String value) { + public static void saveTempValue(String name, String value) throws FileException { File dir = new File(fpsmasterCache, name + ".tmp"); saveAbsoluteFile(dir.getAbsolutePath(), value); } - public static String readTempValue(String name) { + public static String readTempValue(String name) throws FileException { + File dir = new File(fpsmasterCache, name + ".tmp"); + if (!dir.exists()) { + return ""; + } try { - File dir = new File(fpsmasterCache, name + ".tmp"); - return !dir.exists() ? "" : readAbsoluteFile(dir.getAbsolutePath()); + return readAbsoluteFile(dir.getAbsolutePath()); } catch (Exception e) { - e.printStackTrace(); - return ""; + throw new FileException("Failed to read temp value: " + name, e); } } @@ -121,10 +127,15 @@ public static void release(String file) { while ((line = reader.readLine()) != null) { sb.append(line).append("\n"); } - saveFile(file + ".lang", sb.toString()); - } + try { + saveFile(file + ".lang", sb.toString()); + } catch (FileException e) { + ClientLogger.error("Failed to save language file: " + file + ".lang"); + throw new IOException("Failed to save language file", e); + } } - } catch (IOException e) { + } + } catch (IOException e) { e.printStackTrace(); } } @@ -139,17 +150,19 @@ public static int getDirSize(File folder) { return (int) (size / 1024 / 1024); } - public static String readFile(String name) { + public static String readFile(String name) throws FileException { File file = new File(dir, name); return readAbsoluteFile(file.getAbsolutePath()); } - public static String readAbsoluteFile(String name) { + public static String readAbsoluteFile(String name) throws FileException { File file = new File(name); StringBuilder result = new StringBuilder(); try { if (!file.exists()) { - file.createNewFile(); + if (!file.createNewFile()) { + throw new FileException("Failed to create file: " + name); + } } try (FileInputStream fIn = new FileInputStream(file); BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(fIn, StandardCharsets.UTF_8))) { @@ -158,8 +171,8 @@ public static String readAbsoluteFile(String name) { result.append(str).append(System.lineSeparator()); } } - } catch (IOException e) { - e.printStackTrace(); + } catch (IOException e) { + throw new FileException("Failed to read file: " + name, e); } return result.toString(); } From 7dae348209eb1618cd7736bc82d6f20c7837ffad Mon Sep 17 00:00:00 2001 From: SuperSkidder Date: Wed, 2 Jul 2025 01:28:25 +0800 Subject: [PATCH 063/193] docs: add code_standards.md and development_tutorial.md --- docs/code_standards.md | 139 ++++++++++++++ docs/development_tutorial.md | 353 +++++++++++++++++++++++++++++++++++ 2 files changed, 492 insertions(+) create mode 100644 docs/code_standards.md create mode 100644 docs/development_tutorial.md diff --git a/docs/code_standards.md b/docs/code_standards.md new file mode 100644 index 00000000..60edb6ae --- /dev/null +++ b/docs/code_standards.md @@ -0,0 +1,139 @@ +# FPSMaster 代码规范 + +本文档概述了FPSMaster项目的代码标准和贡献指南。所有贡献者在提交代码时都应遵循这些标准,以确保代码库的一致性和质量。 + +## 代码风格指南 + +### 命名规范 + +1. 方法名、变量名和包名使用**驼峰式命名法(camelCase)** + ```java + public void initializeModules() { ... } + private String clientVersion; + ``` + +2. 类名和接口名使用**帕斯卡命名法(PascalCase)** + ```java + public class ModuleManager { ... } + public interface EventListener { ... } + ``` + +3. 常量使用**全大写蛇形命名法(UPPER_SNAKE_CASE)** + ```java + public static final String CLIENT_VERSION = "v4"; + ``` + +### 代码组织 + +1. 按字母顺序组织导入并删除未使用的导入 +2. 将相关方法分组放置 +3. 保持方法专注于单一职责 +4. 限制方法长度以提高可读性(建议控制在50行以内) +5. 使用适当的访问修饰符(private, protected, public)来加强封装性 +6. 字段应放在类顶部,其次是构造函数,然后是方法 + +### 格式化 + +1. 使用4个空格缩进(不要用制表符) +2. 左大括号与声明放在同一行 + ```java + public void method() { + // 代码 + } + ``` +3. 在`if`、`for`、`while`等关键字后使用空格 + ```java + if (condition) { + // 代码 + } + ``` +4. 在运算符周围使用空格 + ```java + int a = b + c; + ``` + +### 文档 + +1. 为所有公共类和方法添加JavaDoc注释 + ```java + /** + * 初始化模块系统。 + * 此方法注册所有模块并设置事件监听器。 + */ + public void initializeModules() { + // 实现 + } + ``` +2. 为复杂代码段添加行内注释 +3. 保持注释与代码变更同步更新 + +### 错误处理 + +1. 使用适当的异常处理 +2. 避免空的catch块;至少应记录异常 + ```java + try { + // 可能抛出异常的代码 + } catch (Exception e) { + ClientLogger.error("处理失败: " + e.getMessage()); + } + ``` +3. 提供有意义的错误信息 + +### 最佳实践 + +1. 避免使用魔法数字;改用命名常量 +2. 尽量减少静态字段和方法的使用 +3. 遵循最小权限原则(使用尽可能严格的访问修饰符) +4. 避免代码重复;将通用代码提取为可重用方法 +5. 根据任务选择合适的数据结构 +6. 实现适当的空值检查以避免NullPointerException + +## 测试要求 + +在提交pull request前,贡献者必须: + +1. **测试所有受影响的功能**:确保变更不会破坏现有功能 +2. **跨不同Minecraft版本测试**:如适用,验证变更在所有支持的Minecraft版本(1.8.9, 1.12.2等)上都能正常工作 +3. **测试边界情况**:考虑并测试边界条件和异常输入 +4. **性能测试**:对于性能关键代码,验证变更不会对性能产生负面影响 + +### 测试清单 + +- [ ] 测试变更的主要功能 +- [ ] 验证变更不会破坏现有功能 +- [ ] 在所有适用的Minecraft版本上测试 +- [ ] 考虑并测试边界情况 +- [ ] 验证性能影响(如适用) +- [ ] 检查测试过程中是否有控制台错误 + +## Pull Request指南 + +提交pull request时: + +1. **描述你的变更**:清晰说明PR做了什么 +2. **引用相关问题**:链接到PR解决的所有相关问题 +3. **保持变更专注**:每个PR应只解决一个关注点 +4. **遵循代码风格**:确保代码遵循项目的代码风格指南 +5. **更新文档**:更新变更影响的所有相关文档 + +### PR清单 + +- [ ] 代码遵循项目的代码风格指南 +- [ ] 测试所有相关模块 +- [ ] 文档已更新(如适用) +- [ ] PR只解决一个关注点 +- [ ] PR引用了相关问题 + +## 贡献流程 + +1. **Fork仓库**:创建项目的个人fork +2. **创建分支**:在新分支中进行变更 +3. **实现变更**:开发功能或修复 +4. **测试变更**:确保所有测试通过且变更按预期工作 +5. **提交pull request**:从你的分支向主仓库创建PR +6. **处理评审反馈**:根据代码评审要求进行修改 + +## 结语 + +遵循这些指南有助于保持FPSMaster项目的代码质量和一致性。感谢您的贡献,感谢您帮助FPSMaster变得更好! \ No newline at end of file diff --git a/docs/development_tutorial.md b/docs/development_tutorial.md new file mode 100644 index 00000000..0e09c0c3 --- /dev/null +++ b/docs/development_tutorial.md @@ -0,0 +1,353 @@ +# FPSMaster 开发教程 + +本教程将介绍如何为 FPSMaster 客户端添加新功能,包括基本功能、带界面组件的功能,以及如何使用 mixin 系统。此外,还将简要介绍客户端的命令系统和配置系统。 + +## 目录 + +1. [添加基本功能](#添加基本功能) +2. [添加带界面组件的功能](#添加带界面组件的功能) +3. [使用 Mixin 系统](#使用-mixin-系统) +4. [命令系统介绍](#命令系统介绍) +5. [配置系统介绍](#配置系统介绍) + +## 添加基本功能 + +在 FPSMaster 中,所有功能都是通过继承 `Module` 类来实现的。下面是添加一个基本功能的步骤: + +### 步骤 1:创建新的功能类 + +首先,在 `top.fpsmaster.features.impl` 包下创建一个新的类,根据功能类型选择合适的类型(如 `optimizes`、`render`、`utility` 等)。 + +```java +package top.fpsmaster.features.impl.utility; + +import top.fpsmaster.features.manager.Category; +import top.fpsmaster.features.manager.Module; + +public class MyFeature extends Module { + + public MyFeature() { + super("MyFeature", "这是我的第一个功能", Category.Utility); + } + + @Override + public void onEnable() { + super.onEnable(); + // 功能启用时的代码 + } + + @Override + public void onDisable() { + super.onDisable(); + // 功能禁用时的代码 + } +} +``` + +### 步骤 2:添加设置 + +大多数功能都需要一些设置来让用户自定义其行为。FPSMaster 提供了多种设置类型: + +```java +import top.fpsmaster.features.settings.impl.BooleanSetting; +import top.fpsmaster.features.settings.impl.NumberSetting; +import top.fpsmaster.features.settings.impl.ModeSetting; +import top.fpsmaster.features.settings.impl.ColorSetting; + +public class MyFeature extends Module { + + // 布尔设置(开关) + public BooleanSetting enableEffect = new BooleanSetting("EnableEffect", true); + + // 数值设置(带范围和步长) + public NumberSetting speed = new NumberSetting("Speed", 1.0, 0.1, 5.0, 0.1); + + // 模式设置(多选一) + public ModeSetting mode = new ModeSetting("Mode", 0, "Mode1", "Mode2", "Mode3"); + + // 颜色设置 + public ColorSetting color = new ColorSetting("Color", new Color(255, 0, 0)); + + public MyFeature() { + super("MyFeature", "这是我的第一个功能", Category.Utility); + + // 添加设置到功能 + addSettings(enableEffect, speed, mode, color); + } +} +``` + +### 步骤 3:注册功能 + +在 `ModuleManager` 类的 `init()` 方法中注册你的功能: + +```java +// 在 ModuleManager.java 的 init() 方法中添加 +modules.add(new MyFeature()); +``` + +### 步骤 4:实现功能逻辑 + +根据功能的需求,你可能需要订阅事件来实现功能逻辑。FPSMaster 使用注解来订阅事件: + +```java +import top.fpsmaster.event.Subscribe; +import top.fpsmaster.event.events.EventTick; + +public class MyFeature extends Module { + + // ... 其他代码 ... + + @Subscribe + public void onTick(EventTick event) { + // 每个游戏刻执行的代码 + if (isEnabled() && enableEffect.getValue()) { + // 根据设置执行不同的逻辑 + if (mode.getMode().equals("Mode1")) { + // Mode1 的逻辑 + } else if (mode.getMode().equals("Mode2")) { + // Mode2 的逻辑 + } + } + } +} +``` + +## 添加带界面组件的功能 + +如果你想创建一个在游戏界面上显示信息的功能(如坐标显示、FPS显示等),你需要创建一个 `InterfaceModule` 和对应的 `Component`。 + +### 步骤 1:创建 InterfaceModule + +在 `top.fpsmaster.features.impl.interfaces` 包下创建一个新的类: + +```java +package top.fpsmaster.features.impl.interfaces; + +import top.fpsmaster.features.impl.InterfaceModule; +import top.fpsmaster.features.manager.Category; +import top.fpsmaster.features.settings.impl.BooleanSetting; + +public class MyDisplay extends InterfaceModule { + + // 特定于此显示的设置 + public BooleanSetting showExtra = new BooleanSetting("ShowExtra", false); + + public MyDisplay() { + super("MyDisplay", Category.Interface); + + // 添加通用界面设置和特定设置 + addSettings(rounded, backgroundColor, fontShadow, betterFont, bg, rounded, roundRadius); + addSettings(showExtra); + } +} +``` + +### 步骤 2:创建 Component + +在 `top.fpsmaster.ui.custom.impl` 包下创建一个对应的组件类: + +```java +package top.fpsmaster.ui.custom.impl; + +import top.fpsmaster.features.impl.interfaces.MyDisplay; +import top.fpsmaster.ui.custom.Component; + +public class MyDisplayComponent extends Component { + + public MyDisplayComponent() { + super(MyDisplay.class); + allowScale = true; // 允许用户调整大小 + } + + @Override + public void draw(float x, float y) { + super.draw(x, y); + + // 获取要显示的信息 + String displayText = "Hello, World!"; + + // 如果启用了额外显示 + if (((MyDisplay) mod).showExtra.getValue()) { + displayText += " Extra Info"; + } + + // 设置组件大小 + width = getStringWidth(18, displayText) + 4; + height = 14f; + + // 绘制背景和文本 + drawRect(x, y, width, height, mod.backgroundColor.getColor()); + drawString(18, displayText, x + 2, y + 2, -1); // -1 表示白色 + } +} +``` + +### 步骤 3:注册组件 + +在 `ComponentsManager` 类的 `init()` 方法中注册你的组件: + +```java +// 在 ComponentsManager.java 的 init() 方法中添加 +components.add(new MyDisplayComponent()); +``` + +### 步骤 4:注册模块 + +在 `ModuleManager` 类的 `init()` 方法中注册你的模块: + +```java +// 在 ModuleManager.java 的 init() 方法中添加 +modules.add(new MyDisplay()); +``` + +## 使用 Mixin 系统 + +Mixin 是一种在运行时修改 Minecraft 代码的技术,无需直接修改原始代码。FPSMaster 使用 SpongePowered Mixin 框架来实现这一点。 + +### 步骤 1:创建 Mixin 类 + +在 `top.fpsmaster.forge.mixin` 包下创建一个新的 Mixin 类: + +```java +package top.fpsmaster.forge.mixin; + +import net.minecraft.client.renderer.EntityRenderer; +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; +import top.fpsmaster.features.impl.optimizes.MyFeature; + +@Mixin(EntityRenderer.class) +public class MixinEntityRenderer { + + // 在方法开始处注入代码 + @Inject(method = "renderWorldPass", at = @At("HEAD"), cancellable = true) + private void onRenderWorldPass(int pass, float partialTicks, long finishTimeNano, CallbackInfo ci) { + // 如果我的功能启用,则取消原方法执行 + if (MyFeature.using) { + ci.cancel(); + } + } + + // 重定向字段访问 + @Redirect(method = "setupCameraTransform", at = @At(value = "FIELD", target = "Lnet/minecraft/client/settings/GameSettings;viewBobbing:Z")) + public boolean redirectViewBobbing(GameSettings instance) { + // 修改视角摇晃设置 + return instance.viewBobbing && !MyFeature.disableBobbing; + } + + // 完全覆盖方法 + @Overwrite + public void someMethod() { + // 完全替换原方法的实现 + } +} +``` + +### 步骤 2:注册 Mixin + +在 `mixins.fpsmaster.json` 文件中注册你的 Mixin: + +```json +{ + "required": true, + "minVersion": "0.7.11", + "package": "top.fpsmaster.forge.mixin", + "refmap": "mixins.fpsmaster.refmap.json", + "compatibilityLevel": "JAVA_8", + "mixins": [ + "MixinEntityRenderer" + ] +} +``` + +### Mixin 常用注解 + +- `@Mixin`: 指定要修改的目标类 +- `@Inject`: 在方法的特定点注入代码 +- `@Redirect`: 重定向字段访问或方法调用 +- `@Overwrite`: 完全覆盖原方法 +- `@Shadow`: 声明目标类中存在的字段或方法 +- `@Unique`: 声明 Mixin 类中的唯一方法或字段 + +## 命令系统介绍 + +FPSMaster 的命令系统允许用户通过聊天框输入命令来执行特定操作。 + +### 创建新命令 + +要创建新命令,需要继承 `Command` 类并实现 `execute` 方法: + +```java +package top.fpsmaster.features.command.impl; + +import top.fpsmaster.features.command.Command; +import top.fpsmaster.utils.Utility; + +public class MyCommand extends Command { + + public MyCommand() { + super("mycommand"); // 命令名称 + } + + @Override + public void execute(String[] args) { + if (args.length == 0) { + // 无参数时的行为 + Utility.sendClientMessage("使用方法: .mycommand <参数>"); + } else { + // 有参数时的行为 + Utility.sendClientMessage("执行命令: " + args[0]); + } + } +} +``` + +### 注册命令 + +在 `CommandManager` 类的 `init()` 方法中注册你的命令: + +```java +// 在 CommandManager.java 的 init() 方法中添加 +commands.add(new MyCommand()); +``` + +### 使用命令 + +用户可以在游戏中通过聊天框输入命令前缀(默认为 `.`)加命令名称来使用命令: + +``` +.mycommand 参数 +``` + +## 配置系统介绍 + +FPSMaster 的配置系统用于保存和加载用户设置,包括模块状态、设置值和组件位置等。 + +### 模块配置 + +模块的配置(启用状态、设置值等)会自动保存和加载,无需额外代码。 + +### 客户端配置 + +对于不属于特定模块的设置,可以使用 `Configure` 类: + +```java +// 获取配置值,如果不存在则创建默认值 +String value = FPSMaster.configManager.configure.getOrCreate("myKey", "defaultValue"); + +// 设置配置值 +FPSMaster.configManager.configure.set("myKey", "newValue"); +``` + +### 保存和加载配置 + +配置会在客户端关闭时自动保存,在启动时自动加载。 + +## 总结 + +通过本教程,你应该已经了解了如何为 FPSMaster 客户端添加新功能,包括基本功能、带界面组件的功能,以及如何使用 mixin 系统。此外,你还了解了客户端的命令系统和配置系统的基本使用方法。 + +开发 FPSMaster 功能时,建议参考现有的功能实现,以确保代码风格和结构的一致性。祝你开发愉快! \ No newline at end of file From 609481cd75451929e6c86a48e2a10d7763fde30d Mon Sep 17 00:00:00 2001 From: SuperSkidder Date: Wed, 2 Jul 2025 01:46:51 +0800 Subject: [PATCH 064/193] docs: add tasks.md --- README.md | 21 +------- docs/tasks.md | 140 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 142 insertions(+), 19 deletions(-) create mode 100644 docs/tasks.md diff --git a/README.md b/README.md index 46e068e7..f54ee222 100644 --- a/README.md +++ b/README.md @@ -18,25 +18,8 @@ FPSMaster 是一个免费、强大的 Minecraft PvP 客户端。 3. 本分支的1.12.2版本代码暂时不会更新,因此使用1.12.2版本会报错是正常现象。 -### todo: -- [x] 完全迁移到Java -- [ ] 优化代码结构 -- [x] 添加固定界面尺寸选项 -- [x] 组件尺寸自定义 -- [ ] 重构MusicPlayer界面 -- [ ] 支持播放无损/VIP音乐 -- [x] 修复音乐可视化 -- [x] 添加脚本插件系统 -- [ ] 添加界面自动对齐 -- [ ] 添加翻译功能 -- [x] 迁移优化代码 -- [ ] 自动更新 -- [ ] 多语言界面 -- [ ] 重写IRC模块 -- [ ] 优化配置文件模块 -- [ ] FPSMaster Intelligence -- [x] HitMarker -- [ ] Waypoint +### 开发任务 +查看我们的[任务列表](docs/tasks.md)了解当前的开发计划和进度。 ## 开源许可证 diff --git a/docs/tasks.md b/docs/tasks.md new file mode 100644 index 00000000..12951163 --- /dev/null +++ b/docs/tasks.md @@ -0,0 +1,140 @@ +# FPSMaster 任务列表 + +本文档包含 FPSMaster 项目的任务和待办事项。 + +## 当前开发任务 + +以下是当前开发周期的紧急任务: + +- [x] 完全迁移到Java +- [x] 添加固定界面尺寸选项 +- [x] 组件尺寸自定义 +- [x] 修复音乐可视化 +- [x] 添加脚本插件系统 +- [x] 迁移优化代码 +- [x] HitMarker +- [ ] 优化代码结构 +- [ ] 重构MusicPlayer界面 +- [ ] 支持播放无损/VIP音乐 +- [ ] 添加界面自动对齐 +- [ ] 添加翻译功能 +- [ ] Waypoint + +## 长期改进任务 + +这是 FPSMaster 项目的综合改进任务列表。每个任务都按类别分类,并包含一个可在完成时标记的复选框。 + +## 架构改进 + +### 模块系统 +1. [ ] 创建使用注解而非硬编码列表的模块注册系统 +2. [ ] 实现适当的模块生命周期管理系统(初始化、启动、停止、销毁) +3. [ ] 开发模块依赖解析系统 +4. [ ] 重构模块类别以使用更灵活的分类法 + +### 事件系统 +1. [ ] 优化事件分发以提高性能 +2. [ ] 实现事件优先级 +3. [ ] 添加事件取消支持 +4. [ ] 创建全面的事件文档 +5. [ ] 添加事件调试/监控工具 + +### 配置系统 +1. [ ] 重构配置保存格式 +2. [ ] 实现配置版本迁移 +3. [ ] 实现多配置文件切换 + +### UI框架 +1. [ ] 开发更模块化的UI组件系统 +2. [ ] 实现UI组件的布局管理器,如自动布局等 +3. [ ] 重写主题系统 +4. [ ] 将UI逻辑与渲染代码分离 +5. [ ] 实现不同分辨率的UI缩放 + +## 性能优化 + +### 渲染 +1. [ ] 优化渲染管道以提高FPS +2. [ ] 实现UI组件的渲染批处理 +3. [ ] 优化动画以减少CPU使用率 + +### 内存管理 +1. [ ] 为频繁创建的对象实现对象池 +2. [ ] 添加内存使用监控 + +### 网络优化 +1. [ ] 为网络请求添加具有指数退避的重试机制 +2. [ ] 为网络请求/响应添加压缩 +3. [ ] 优化WebSocket通信 + +## 代码质量改进 + +### 重构 +1. [ ] 清理代码 +2. [ ] 解决代码重复问题 +3. [ ] 改进整个代码库的错误处理 +4. [ ] 去耦合,将长方法重构为更小的方法 + +### 最佳实践 +1. [ ] 为公共方法添加输入验证 +2. [x] 使用自定义异常实现适当的异常处理 +3. [ ] 添加空值检查和防御性编程 +4. [ ] 用命名常量替换魔法数字 + +### 代码组织 +1. [ ] 一致地组织导入 +2. [ ] 标准化包结构 +3. [ ] 实现适当的封装(减少公共字段) + +## 测试 + +## 文档 + +### 代码文档 +1. [ ] 为所有公共API添加全面的JavaDoc +2. [ ] 记录复杂算法和业务逻辑 +3. [ ] 创建架构图 +4. [ ] 记录模块依赖关系 +5. [ ] 为复杂代码段添加内联注释 + +### 用户文档 +1. [ ] 创建用户手册 +2. [ ] 添加帮助系统 +3. [ ] 为常见任务创建教程 +4. [ ] 为UI元素添加工具提示 + +### 开发者文档 +1. [ ] 创建开发者设置指南 +2. [ ] 记录构建过程 +3. [x] 添加贡献指南 +4. [ ] 创建API文档 + +## 安全改进 + +### 认证 +1. [ ] 实现安全令牌存储 +2. [ ] 改进会话管理 + +### 数据保护 +1. [ ] 加密敏感配置数据 + +## 国际化和可访问性 + +### 国际化 +1. [ ] 完成翻译系统 +2. [ ] 创建翻译贡献工具 +3. [ ] 添加语言自动检测 + +## 功能增强 + +### 用户体验 +1. [ ] 创建更直观的设置界面 +2. [ ] 为操作添加视觉反馈 +3. [ ] 实现撤销/重做功能 + +### 集成 +1. [ ] 添加对更多Minecraft版本的支持 +2. [ ] 添加与流行Minecraft服务器的集成 +3. [ ] 为其他模组创建兼容性层,如Optifine等 +4. [ ] 实现配置文件的云同步 +5. [ ] 添加AI相关功能的集成 From 1e989feef48cbed842bff9cea69c30f091c19129 Mon Sep 17 00:00:00 2001 From: SuperSkidder Date: Wed, 2 Jul 2025 01:57:55 +0800 Subject: [PATCH 065/193] docs: add development_environment.md --- README.md | 18 +----------------- docs/development_environment.md | 27 +++++++++++++++++++++++++++ docs/development_tutorial.md | 4 ++++ docs/tasks.md | 9 ++++----- 4 files changed, 36 insertions(+), 22 deletions(-) create mode 100644 docs/development_environment.md diff --git a/README.md b/README.md index f54ee222..3e996f01 100644 --- a/README.md +++ b/README.md @@ -26,23 +26,7 @@ FPSMaster 是一个免费、强大的 Minecraft PvP 客户端。 本项目采用 GPL-3.0 许可证。详情请参阅 [LICENSE](LICENSE) 文件。 ## 开发环境配置 -1. clone项目 -2. Link Gradle Script -3. 将Idea的Gradle jdk版本设置为java17 -4. 导入各版本gradle配置文件 -5. 执行`gradle genIntelliJRuns` -6. 执行`gradle runClient`(这一步会执行downloadAssets等任务,可能因为网络问题失败) -7. 把生成的Minecraft Client启动配置的运行java版本改为java8(注意,不要改gradle的jdk版本配置) - -可能遇到的问题: - -- 运行`genIntelliJRuns`之后并没有出现启动配置,此时需要把生成的`.idea/runConfiguration`复制到`v1.8.9/.idea/runConfiguration` -- 生成的启动配置的vmargs参数中`v1.8.9/.gradle/loom-cache/launch.cfg`中的目录路径可能无法启动,需要手动改成绝对路径 -- 生成的`v1.8.9/.gradle/loom-cache/launch.cfg`中的目录路径错误,这时需要手动修复 -- APPDATA/.gradle/caches/essential-loom/assets/ 目录中的资源无法正常下载,此时可以其他地方复制一份1.8的assets目录过来 - - - +查看我们的[开发环境配置指南](docs/development_environment.md)了解如何配置开发环境。 ![Alt](https://repobeats.axiom.co/api/embed/7d755c063aa9a34d74edb7045541e8bfe6e09b89.svg "Repobeats analytics image") diff --git a/docs/development_environment.md b/docs/development_environment.md new file mode 100644 index 00000000..15da97b2 --- /dev/null +++ b/docs/development_environment.md @@ -0,0 +1,27 @@ +# 配置开发环境 + +## 准备工作 +1. Git +2. JDK 1.8 +3. JDK 17 +4. IntelliJ IDEA Community / Ultimate + +## 配置项目 + +1. clone项目 +2. Link Gradle Script +3. 将Idea的Gradle jdk版本设置为java17 +4. 导入相应版本gradle配置文件 +5. 执行`gradle genIntelliJRuns` +6. 此时并不会出现启动配置,此时需要把生成的`v1.8.9/.idea/runConfiguration`复制到`.idea/runConfiguration`,随后重新打开项目即可识别 + +### 可能遇到的问题: + +- 生成的启动配置的vmargs参数中的目录路径可能无法正确识别,需要手动改为正确路径或绝对路径 +- 生成的`v1.8.9/.gradle/loom-cache/launch.cfg`中的目录路径错误,这时需要手动改为正确路径或绝对路径 +- `APPDATA/.gradle/caches/essential-loom/assets/` 目录中的资源无法正常下载,此时可以其他地方复制一份1.8的assets目录过来 + +## 启动项目 + +直接在IDEA的运行配置中选中Minecraft Client,并且将运行java版本改为jdk 1.8(注意,不要改gradle的jdk版本配置) + diff --git a/docs/development_tutorial.md b/docs/development_tutorial.md index 0e09c0c3..62fedd7a 100644 --- a/docs/development_tutorial.md +++ b/docs/development_tutorial.md @@ -2,6 +2,10 @@ 本教程将介绍如何为 FPSMaster 客户端添加新功能,包括基本功能、带界面组件的功能,以及如何使用 mixin 系统。此外,还将简要介绍客户端的命令系统和配置系统。 +## 前提条件 + +在开始开发前,你需要配置好本项目的开发环境,具体可以参考:[配置开发环境](development_environment.md) + ## 目录 1. [添加基本功能](#添加基本功能) diff --git a/docs/tasks.md b/docs/tasks.md index 12951163..1e2b6326 100644 --- a/docs/tasks.md +++ b/docs/tasks.md @@ -92,7 +92,7 @@ ### 代码文档 1. [ ] 为所有公共API添加全面的JavaDoc -2. [ ] 记录复杂算法和业务逻辑 +2. [ ] 记录复杂算法和逻辑 3. [ ] 创建架构图 4. [ ] 记录模块依赖关系 5. [ ] 为复杂代码段添加内联注释 @@ -104,10 +104,9 @@ 4. [ ] 为UI元素添加工具提示 ### 开发者文档 -1. [ ] 创建开发者设置指南 -2. [ ] 记录构建过程 -3. [x] 添加贡献指南 -4. [ ] 创建API文档 +1. [x] 创建开发者设置指南 +2. [x] 添加贡献指南 +3. [ ] 创建API文档 ## 安全改进 From 40e514f6c38197236dbe2af81c171e63036095ce Mon Sep 17 00:00:00 2001 From: SuperSkidder Date: Tue, 8 Jul 2025 22:37:29 +0800 Subject: [PATCH 066/193] change: some exception handling --- .../top/fpsmaster/features/command/Command.java | 4 +++- .../fpsmaster/features/command/CommandManager.java | 14 ++++++-------- .../top/fpsmaster/features/command/impl/AI.java | 5 +++-- .../utils/thirdparty/openai/OpenAIClient.java | 3 ++- 4 files changed, 14 insertions(+), 12 deletions(-) diff --git a/shared/java/top/fpsmaster/features/command/Command.java b/shared/java/top/fpsmaster/features/command/Command.java index 42c37f19..3db0f739 100644 --- a/shared/java/top/fpsmaster/features/command/Command.java +++ b/shared/java/top/fpsmaster/features/command/Command.java @@ -1,10 +1,12 @@ package top.fpsmaster.features.command; +import top.fpsmaster.exception.FileException; + public abstract class Command { String name; public Command(String name) { this.name = name; } - public abstract void execute(String[] args); + public abstract void execute(String[] args) throws FileException; } diff --git a/shared/java/top/fpsmaster/features/command/CommandManager.java b/shared/java/top/fpsmaster/features/command/CommandManager.java index 5afaccd4..0af0916d 100644 --- a/shared/java/top/fpsmaster/features/command/CommandManager.java +++ b/shared/java/top/fpsmaster/features/command/CommandManager.java @@ -4,6 +4,7 @@ import top.fpsmaster.event.EventDispatcher; import top.fpsmaster.event.Subscribe; import top.fpsmaster.event.events.EventSendChatMessage; +import top.fpsmaster.exception.FileException; import top.fpsmaster.features.command.impl.AI; import top.fpsmaster.features.command.impl.Dev; import top.fpsmaster.features.command.impl.IRCChat; @@ -28,19 +29,16 @@ public void init() { } @Subscribe - public void onChat(EventSendChatMessage e) { + public void onChat(EventSendChatMessage e) throws FileException { if (e.msg.startsWith(ClientSettings.prefix.getValue())) { e.cancel(); - try { - mc.ingameGUI.getChatGUI().addToSentMessages(e.msg); - runCommand(e.msg.substring(1)); - } catch (Exception ex) { - ex.printStackTrace(); - } + mc.ingameGUI.getChatGUI().addToSentMessages(e.msg); + runCommand(e.msg.substring(1)); + } } - private void runCommand(String command) { + private void runCommand(String command) throws FileException { String[] args = command.split(" "); String cmd = args[0]; if (args.length == 1) { diff --git a/shared/java/top/fpsmaster/features/command/impl/AI.java b/shared/java/top/fpsmaster/features/command/impl/AI.java index 7afb899d..8a62456d 100644 --- a/shared/java/top/fpsmaster/features/command/impl/AI.java +++ b/shared/java/top/fpsmaster/features/command/impl/AI.java @@ -2,6 +2,7 @@ import com.google.gson.JsonArray; import top.fpsmaster.FPSMaster; +import top.fpsmaster.exception.FileException; import top.fpsmaster.features.command.Command; import top.fpsmaster.modules.client.AsyncTask; import top.fpsmaster.modules.lua.LuaManager; @@ -64,7 +65,7 @@ public AI() { } @Override - public void execute(String[] args) { + public void execute(String[] args) throws FileException { StringBuilder sb = new StringBuilder(); if (args.length > 0) { if (args[0].equals("lua")) { @@ -95,7 +96,7 @@ public void onError(Exception e) { } @Override - public void onFinish(String string) { + public void onFinish(String string) throws FileException { FileUtils.saveFile("plugins/" + fileName + ".lua", luaScript.rawLua.code); luaScript.failedReason = ""; LuaManager.hotswap(); diff --git a/shared/java/top/fpsmaster/utils/thirdparty/openai/OpenAIClient.java b/shared/java/top/fpsmaster/utils/thirdparty/openai/OpenAIClient.java index 6b77f8bc..747d3f52 100644 --- a/shared/java/top/fpsmaster/utils/thirdparty/openai/OpenAIClient.java +++ b/shared/java/top/fpsmaster/utils/thirdparty/openai/OpenAIClient.java @@ -6,6 +6,7 @@ import org.apache.http.impl.client.HttpClients; import org.apache.http.entity.StringEntity; import com.google.gson.*; +import top.fpsmaster.exception.FileException; import java.io.BufferedReader; import java.io.InputStreamReader; @@ -144,7 +145,7 @@ public interface ResponseCallback { void onError(Exception e); // 当发生错误时调用 - void onFinish(String string); + void onFinish(String string) throws FileException; } public static class Message { From c939f82cb26285b48e30ec986a9a7fbdbe35aa01 Mon Sep 17 00:00:00 2001 From: SuperSkidder Date: Sun, 13 Jul 2025 10:35:11 +0800 Subject: [PATCH 067/193] fix: fix multiplayer render bug improve exceptions handling --- shared/java/top/fpsmaster/FPSMaster.java | 48 +++++--- .../top/fpsmaster/event/EventDispatcher.java | 2 +- .../fpsmaster/features/command/Command.java | 3 +- .../features/command/CommandManager.java | 4 +- .../fpsmaster/features/command/impl/AI.java | 2 +- .../fpsmaster/features/command/impl/Dev.java | 3 +- .../modules/config/ConfigManager.java | 109 ++++++++---------- .../top/fpsmaster/modules/dev/DevMode.java | 3 +- .../top/fpsmaster/modules/i18n/Language.java | 5 +- .../top/fpsmaster/modules/lua/LuaManager.java | 13 +-- .../top/fpsmaster/ui/click/MainPanel.java | 7 +- .../top/fpsmaster/ui/devspace/DevSpace.java | 11 +- .../top/fpsmaster/ui/mc/GuiMultiplayer.java | 57 +++++---- .../utils/thirdparty/openai/OpenAIClient.java | 10 +- .../main/java/top/fpsmaster/forge/Mod.java | 3 +- 15 files changed, 144 insertions(+), 136 deletions(-) diff --git a/shared/java/top/fpsmaster/FPSMaster.java b/shared/java/top/fpsmaster/FPSMaster.java index 0b0304f9..ff712326 100644 --- a/shared/java/top/fpsmaster/FPSMaster.java +++ b/shared/java/top/fpsmaster/FPSMaster.java @@ -1,6 +1,8 @@ package top.fpsmaster; import net.minecraftforge.fml.common.FMLCommonHandler; +import top.fpsmaster.exception.ExceptionHandler; +import top.fpsmaster.exception.FileException; import top.fpsmaster.features.GlobalSubmitter; import top.fpsmaster.features.command.CommandManager; import top.fpsmaster.features.manager.ModuleManager; @@ -88,12 +90,12 @@ private void initializeFonts() { fontManager.load(); } - private void initializeLang() { + private void initializeLang() throws FileException { ClientLogger.info("Initializing I18N..."); i18n.read("zh_cn"); } - private void initializeConfigures() { + private void initializeConfigures() throws Exception { ClientLogger.info("Initializing Config..."); configManager.loadConfig("default"); if ("dark".equals(themeSlot)) { @@ -144,7 +146,7 @@ private void initializeModules() { submitter.init(); } - private void initializePlugins() { + private void initializePlugins() throws FileException { luaManager.init(); } @@ -173,22 +175,26 @@ private void checkUpdate() { } public void initialize() { - initializeFonts(); - initializeLang(); - initializeMusic(); - initializeModules(); - initializeComponents(); - initializeConfigures(); - initializeCommands(); - initializePlugins(); - - if (phase == "release") { - checkUpdate(); - } - if (phase == "alpha") { - autoUpdate(); + try { + initializeFonts(); + initializeLang(); + initializeMusic(); + initializeModules(); + initializeComponents(); + initializeConfigures(); + initializeCommands(); + initializePlugins(); + + if (phase == "release") { + checkUpdate(); + } + if (phase == "alpha") { + autoUpdate(); + } + checkOptifine(); + } catch (Exception e) { + ExceptionHandler.handle(e); } - checkOptifine(); } public void autoUpdate() { @@ -196,6 +202,10 @@ public void autoUpdate() { } public void shutdown() { - configManager.saveConfig("default"); + try { + configManager.saveConfig("default"); + } catch (FileException e) { + throw new RuntimeException(e); + } } } \ No newline at end of file diff --git a/shared/java/top/fpsmaster/event/EventDispatcher.java b/shared/java/top/fpsmaster/event/EventDispatcher.java index 1da5a746..a3a023db 100644 --- a/shared/java/top/fpsmaster/event/EventDispatcher.java +++ b/shared/java/top/fpsmaster/event/EventDispatcher.java @@ -43,7 +43,7 @@ public static void dispatchEvent(Event event) { ExceptionHandler.handleModuleException((Exception) e, "Failed to dispatch event " + event.getClass().getSimpleName()); } else { // For non-Exception Throwables, we still need to log them - top.fpsmaster.modules.logger.ClientLogger.error("Non-Exception Throwable: " + e.getMessage()); + ClientLogger.error("Non-Exception Throwable: " + e.getMessage()); e.printStackTrace(); } } diff --git a/shared/java/top/fpsmaster/features/command/Command.java b/shared/java/top/fpsmaster/features/command/Command.java index 3db0f739..c1fbb31a 100644 --- a/shared/java/top/fpsmaster/features/command/Command.java +++ b/shared/java/top/fpsmaster/features/command/Command.java @@ -1,6 +1,5 @@ package top.fpsmaster.features.command; -import top.fpsmaster.exception.FileException; public abstract class Command { String name; @@ -8,5 +7,5 @@ public Command(String name) { this.name = name; } - public abstract void execute(String[] args) throws FileException; + public abstract void execute(String[] args) throws Exception; } diff --git a/shared/java/top/fpsmaster/features/command/CommandManager.java b/shared/java/top/fpsmaster/features/command/CommandManager.java index 0af0916d..d1ea02e2 100644 --- a/shared/java/top/fpsmaster/features/command/CommandManager.java +++ b/shared/java/top/fpsmaster/features/command/CommandManager.java @@ -29,7 +29,7 @@ public void init() { } @Subscribe - public void onChat(EventSendChatMessage e) throws FileException { + public void onChat(EventSendChatMessage e) throws Exception { if (e.msg.startsWith(ClientSettings.prefix.getValue())) { e.cancel(); mc.ingameGUI.getChatGUI().addToSentMessages(e.msg); @@ -38,7 +38,7 @@ public void onChat(EventSendChatMessage e) throws FileException { } } - private void runCommand(String command) throws FileException { + private void runCommand(String command) throws Exception { String[] args = command.split(" "); String cmd = args[0]; if (args.length == 1) { diff --git a/shared/java/top/fpsmaster/features/command/impl/AI.java b/shared/java/top/fpsmaster/features/command/impl/AI.java index 8a62456d..7ea0d1fd 100644 --- a/shared/java/top/fpsmaster/features/command/impl/AI.java +++ b/shared/java/top/fpsmaster/features/command/impl/AI.java @@ -65,7 +65,7 @@ public AI() { } @Override - public void execute(String[] args) throws FileException { + public void execute(String[] args) throws Exception { StringBuilder sb = new StringBuilder(); if (args.length > 0) { if (args[0].equals("lua")) { diff --git a/shared/java/top/fpsmaster/features/command/impl/Dev.java b/shared/java/top/fpsmaster/features/command/impl/Dev.java index 52cd5945..70741caf 100644 --- a/shared/java/top/fpsmaster/features/command/impl/Dev.java +++ b/shared/java/top/fpsmaster/features/command/impl/Dev.java @@ -2,6 +2,7 @@ import net.minecraft.client.Minecraft; import top.fpsmaster.FPSMaster; +import top.fpsmaster.exception.FileException; import top.fpsmaster.features.command.Command; import top.fpsmaster.interfaces.ProviderManager; import top.fpsmaster.modules.dev.DevMode; @@ -16,7 +17,7 @@ public Dev() { } @Override - public void execute(String[] args) { + public void execute(String[] args) throws Exception { if (args.length == 0) { DevMode.INSTACE.setDev(!DevMode.INSTACE.dev); Utility.sendClientNotify("Dev mode is now " + (DevMode.INSTACE.dev ? "enabled" : "disabled")); diff --git a/shared/java/top/fpsmaster/modules/config/ConfigManager.java b/shared/java/top/fpsmaster/modules/config/ConfigManager.java index 71d49e1b..bebda062 100644 --- a/shared/java/top/fpsmaster/modules/config/ConfigManager.java +++ b/shared/java/top/fpsmaster/modules/config/ConfigManager.java @@ -2,6 +2,7 @@ import com.google.gson.*; import top.fpsmaster.FPSMaster; +import top.fpsmaster.exception.FileException; import top.fpsmaster.features.impl.optimizes.OldAnimations; import top.fpsmaster.features.impl.optimizes.Performance; import top.fpsmaster.features.impl.render.ItemPhysics; @@ -27,7 +28,7 @@ public ConfigManager() { } } - private void saveComponents() { + private void saveComponents() throws FileException { JsonObject json = new JsonObject(); for (Component moduleComponent : FPSMaster.componentsManager.components) { JsonObject component = new JsonObject(); @@ -41,7 +42,7 @@ private void saveComponents() { FileUtils.saveFile("components.json", gson.toJson(json)); } - private void readComponents() { + private void readComponents() throws FileException { String jsonStr = FileUtils.readFile("components.json"); if (jsonStr.isEmpty()) return; JsonObject json = gson.fromJson(jsonStr, JsonObject.class); @@ -63,7 +64,7 @@ private void readComponents() { } } - public void saveConfig(String name) { + public void saveConfig(String name) throws FileException { saveComponents(); JsonObject json = new JsonObject(); json.addProperty("theme", FPSMaster.themeSlot); @@ -88,67 +89,59 @@ public void saveConfig(String name) { FileUtils.saveFile(name + ".json", gson.toJson(json)); } - public void loadConfig(String name) { - try { - String jsonStr = FileUtils.readFile(name + ".json"); - if (jsonStr.isEmpty()) { - openDefaultModules(); - saveConfig("default"); - loadConfig(name); - return; - } + public void loadConfig(String name) throws Exception { + String jsonStr = FileUtils.readFile(name + ".json"); + if (jsonStr.isEmpty()) { + openDefaultModules(); + saveConfig("default"); + loadConfig(name); + return; + } + + readComponents(); + jsonStr = FileUtils.readFile(name + ".json"); + JsonObject json = gson.fromJson(jsonStr, JsonObject.class); + FPSMaster.themeSlot = json.get("theme").getAsString(); - readComponents(); - jsonStr = FileUtils.readFile(name + ".json"); - JsonObject json = gson.fromJson(jsonStr, JsonObject.class); - FPSMaster.themeSlot = json.get("theme").getAsString(); - - for (Module module : FPSMaster.moduleManager.modules) { - JsonObject moduleJson = json.getAsJsonObject(module.name); - if (moduleJson != null) { - module.set(moduleJson.get("enabled").getAsBoolean()); - module.key = moduleJson.get("key").getAsInt(); - for (Setting setting : module.settings) { - try { - JsonElement settingValue = moduleJson.get(setting.name); - if (settingValue != null) { - if (setting instanceof BooleanSetting) { - BooleanSetting booleanSetting = (BooleanSetting) setting; - booleanSetting.value = settingValue.getAsBoolean(); - } else if (setting instanceof NumberSetting) { - NumberSetting numberSetting = (NumberSetting) setting; - numberSetting.value = settingValue.getAsDouble(); - } else if (setting instanceof ModeSetting) { - ModeSetting modeSetting = (ModeSetting) setting; - modeSetting.value = settingValue.getAsInt(); - } else if (setting instanceof TextSetting) { - TextSetting textSetting = (TextSetting) setting; - textSetting.value = settingValue.getAsString(); - } else if (setting instanceof ColorSetting) { - ColorSetting colorSetting = (ColorSetting) setting; - String[] colorParts = settingValue.getAsString().split("\\|"); - colorSetting.value.setColor( - Float.parseFloat(colorParts[0]), - Float.parseFloat(colorParts[1]), - Float.parseFloat(colorParts[2]), - Float.parseFloat(colorParts[3]) - ); - } else if (setting instanceof BindSetting) { - BindSetting bindSetting = (BindSetting) setting; - bindSetting.value = settingValue.getAsInt(); - } - } - } catch (Exception e) { - e.printStackTrace(); + for (Module module : FPSMaster.moduleManager.modules) { + JsonObject moduleJson = json.getAsJsonObject(module.name); + if (moduleJson != null) { + module.set(moduleJson.get("enabled").getAsBoolean()); + module.key = moduleJson.get("key").getAsInt(); + for (Setting setting : module.settings) { + JsonElement settingValue = moduleJson.get(setting.name); + if (settingValue != null) { + if (setting instanceof BooleanSetting) { + BooleanSetting booleanSetting = (BooleanSetting) setting; + booleanSetting.value = settingValue.getAsBoolean(); + } else if (setting instanceof NumberSetting) { + NumberSetting numberSetting = (NumberSetting) setting; + numberSetting.value = settingValue.getAsDouble(); + } else if (setting instanceof ModeSetting) { + ModeSetting modeSetting = (ModeSetting) setting; + modeSetting.value = settingValue.getAsInt(); + } else if (setting instanceof TextSetting) { + TextSetting textSetting = (TextSetting) setting; + textSetting.value = settingValue.getAsString(); + } else if (setting instanceof ColorSetting) { + ColorSetting colorSetting = (ColorSetting) setting; + String[] colorParts = settingValue.getAsString().split("\\|"); + colorSetting.value.setColor( + Float.parseFloat(colorParts[0]), + Float.parseFloat(colorParts[1]), + Float.parseFloat(colorParts[2]), + Float.parseFloat(colorParts[3]) + ); + } else if (setting instanceof BindSetting) { + BindSetting bindSetting = (BindSetting) setting; + bindSetting.value = settingValue.getAsInt(); } } } } - - configure.configures = gson.fromJson(json.get("clientConfigure").getAsString(), HashMap.class); - } catch (Exception e) { - e.printStackTrace(); } + + configure.configures = gson.fromJson(json.get("clientConfigure").getAsString(), HashMap.class); } private void openDefaultModules() { diff --git a/shared/java/top/fpsmaster/modules/dev/DevMode.java b/shared/java/top/fpsmaster/modules/dev/DevMode.java index 71329590..025818a6 100644 --- a/shared/java/top/fpsmaster/modules/dev/DevMode.java +++ b/shared/java/top/fpsmaster/modules/dev/DevMode.java @@ -3,6 +3,7 @@ import top.fpsmaster.event.EventDispatcher; import top.fpsmaster.event.Subscribe; import top.fpsmaster.event.events.EventUpdate; +import top.fpsmaster.exception.FileException; import top.fpsmaster.modules.lua.LuaManager; import top.fpsmaster.utils.math.MathTimer; @@ -27,7 +28,7 @@ public void setHotswap(boolean value) { MathTimer timer = new MathTimer(); @Subscribe - public void onUpdate(EventUpdate e) { + public void onUpdate(EventUpdate e) throws FileException { if (hotswap) { if (timer.delay(1000)) { LuaManager.hotswap(); diff --git a/shared/java/top/fpsmaster/modules/i18n/Language.java b/shared/java/top/fpsmaster/modules/i18n/Language.java index f3137c1c..808504f5 100644 --- a/shared/java/top/fpsmaster/modules/i18n/Language.java +++ b/shared/java/top/fpsmaster/modules/i18n/Language.java @@ -1,5 +1,6 @@ package top.fpsmaster.modules.i18n; +import top.fpsmaster.exception.FileException; import top.fpsmaster.utils.os.FileUtils; import java.io.IOException; @@ -16,7 +17,7 @@ public Language() { FileUtils.release("zh_cn"); } - public void save(String language) { + public void save(String language) throws FileException { StringBuilder sb = new StringBuilder(); for (Map.Entry entry : prompts.entrySet()) { sb.append(entry.getKey()).append("=").append(entry.getValue()).append(System.lineSeparator()); @@ -24,7 +25,7 @@ public void save(String language) { FileUtils.saveFile(language + ".lang", sb.toString()); } - public void read(String language) { + public void read(String language) throws FileException { String content = FileUtils.readFile(language + ".lang"); String[] lines = content.split(System.lineSeparator()); prompts.clear(); diff --git a/shared/java/top/fpsmaster/modules/lua/LuaManager.java b/shared/java/top/fpsmaster/modules/lua/LuaManager.java index 1b159512..2cbc8364 100644 --- a/shared/java/top/fpsmaster/modules/lua/LuaManager.java +++ b/shared/java/top/fpsmaster/modules/lua/LuaManager.java @@ -6,6 +6,7 @@ import party.iroiro.luajava.lua53.Lua53; import party.iroiro.luajava.value.LuaValue; import top.fpsmaster.FPSMaster; +import top.fpsmaster.exception.FileException; import top.fpsmaster.features.manager.Module; import top.fpsmaster.interfaces.ProviderManager; import top.fpsmaster.modules.dev.DevMode; @@ -29,12 +30,8 @@ public class LuaManager { public static ArrayList scripts = new ArrayList<>(); - public void init() { - try { - reload(); - } catch (Exception e) { - e.printStackTrace(); - } + public void init() throws FileException { + reload(); } @@ -205,7 +202,7 @@ public static void unloadLua(LuaScript script) { remove.forEach(FPSMaster.moduleManager::removeModule); } - public static void reload() { + public static void reload() throws FileException { ArrayList remove = new ArrayList<>(); FPSMaster.moduleManager.modules.forEach(m -> { if (m instanceof LuaModule) { @@ -227,7 +224,7 @@ public static void reload() { } } - public static void hotswap() { + public static void hotswap() throws FileException { ArrayList newRawLuaList = new ArrayList<>(); File[] luas = FileUtils.plugins.listFiles(); for (File luaFile : luas) { diff --git a/shared/java/top/fpsmaster/ui/click/MainPanel.java b/shared/java/top/fpsmaster/ui/click/MainPanel.java index aaba41ea..8731dc93 100644 --- a/shared/java/top/fpsmaster/ui/click/MainPanel.java +++ b/shared/java/top/fpsmaster/ui/click/MainPanel.java @@ -6,6 +6,7 @@ import org.lwjgl.input.Mouse; import org.lwjgl.opengl.GL11; import top.fpsmaster.FPSMaster; +import top.fpsmaster.exception.FileException; import top.fpsmaster.features.manager.Category; import top.fpsmaster.features.manager.Module; import top.fpsmaster.ui.ai.AIChatPanel; @@ -252,7 +253,11 @@ public void initGui() { @Override public void onGuiClosed() { super.onGuiClosed(); - FPSMaster.configManager.saveConfig("default"); + try { + FPSMaster.configManager.saveConfig("default"); + } catch (FileException e) { + throw new RuntimeException(e); + } } @Override diff --git a/shared/java/top/fpsmaster/ui/devspace/DevSpace.java b/shared/java/top/fpsmaster/ui/devspace/DevSpace.java index 266e3933..9b20f4e4 100644 --- a/shared/java/top/fpsmaster/ui/devspace/DevSpace.java +++ b/shared/java/top/fpsmaster/ui/devspace/DevSpace.java @@ -8,6 +8,7 @@ import org.lwjgl.input.Mouse; import org.lwjgl.opengl.GL11; import top.fpsmaster.FPSMaster; +import top.fpsmaster.exception.FileException; import top.fpsmaster.modules.lua.LuaManager; import top.fpsmaster.modules.lua.LuaScript; import top.fpsmaster.modules.lua.parser.Expression; @@ -280,11 +281,15 @@ protected void keyTyped(char typedChar, int keyCode) throws IOException { super.keyTyped(typedChar, keyCode); if (selectedTab == 0) { handleArrowKeys(keyCode); - handleCodeInput(typedChar, keyCode); + try { + handleCodeInput(typedChar, keyCode); + } catch (FileException e) { + throw new RuntimeException(e); + } } } - private void handleCodeInput(char typedChar, int keyCode) { + private void handleCodeInput(char typedChar, int keyCode) throws FileException { if (getCurrentScript() == null) return; @@ -333,7 +338,7 @@ private void handleCodeInput(char typedChar, int keyCode) { } } - private void saveCurrentScript() { + private void saveCurrentScript() throws FileException { FileUtils.saveFile("plugins/" + getCurrentScript().rawLua.filename, getCode(selectedLua)); LuaManager.hotswap(); needReload = true; diff --git a/shared/java/top/fpsmaster/ui/mc/GuiMultiplayer.java b/shared/java/top/fpsmaster/ui/mc/GuiMultiplayer.java index 0e65bcc6..d8d9b460 100644 --- a/shared/java/top/fpsmaster/ui/mc/GuiMultiplayer.java +++ b/shared/java/top/fpsmaster/ui/mc/GuiMultiplayer.java @@ -172,32 +172,32 @@ public void render(int mouseX, int mouseY, float partialTicks) { UFontRenderer title = FPSMaster.fontManager.s22; UFontRenderer font = FPSMaster.fontManager.s18; - title.drawCenteredString("多人游戏", width / 2f, 16, -1); + title.drawCenteredString("多人游戏", guiWidth / 2f, 16, -1); - Render2DUtils.drawOptimizedRoundedRect((width - 180) / 2f, 30, 180, 24, 3, new Color(0, 0, 0, 80).getRGB()); - Render2DUtils.drawOptimizedRoundedRect((width - 176) / 2f + 90 * tab, 32, 86, 20, 3, -1); - FPSMaster.fontManager.s16.drawCenteredString("服务器列表", (width - 90) / 2f, 36, tab == 0 ? new Color(50, 50, 50).getRGB() : -1); - FPSMaster.fontManager.s16.drawCenteredString("推荐服务器", (width + 90) / 2f, 36, tab == 1 ? new Color(50, 50, 50).getRGB() : -1); + Render2DUtils.drawOptimizedRoundedRect((guiWidth - 180) / 2f, 30, 180, 24, 3, new Color(0, 0, 0, 80).getRGB()); + Render2DUtils.drawOptimizedRoundedRect((guiWidth - 176) / 2f + 90 * tab, 32, 86, 20, 3, -1); + FPSMaster.fontManager.s16.drawCenteredString("服务器列表", (guiWidth - 90) / 2f, 36, tab == 0 ? new Color(50, 50, 50).getRGB() : -1); + FPSMaster.fontManager.s16.drawCenteredString("推荐服务器", (guiWidth + 90) / 2f, 36, tab == 1 ? new Color(50, 50, 50).getRGB() : -1); GL11.glPushMatrix(); GL11.glEnable(GL11.GL_SCISSOR_TEST); - Render2DUtils.doGlScissor((width - 400) / 2f, 60f, 400f, height - 120, scaleFactor); - scrollContainer.draw((width - 400) / 2f, 60, 396, height - 120, mouseX, mouseY, () -> { + Render2DUtils.doGlScissor((guiWidth - 400) / 2f, 60f, 400f, guiHeight - 120, scaleFactor); + scrollContainer.draw((guiWidth - 400) / 2f, 60, 396, guiHeight - 120, mouseX, mouseY, () -> { float y = 70 + scrollContainer.getScroll(); - Render2DUtils.drawOptimizedRoundedRect((width - 400) / 2f, y - 10, 400, height - y, 5, new Color(0, 0, 0, 100).getRGB()); + Render2DUtils.drawOptimizedRoundedRect((guiWidth - 400) / 2f, y - 10, 400, guiHeight - y, 5, new Color(0, 0, 0, 100).getRGB()); for (ServerListEntry server : serverListDisplay) { if (server.getServerData() == null) { return; } - Render2DUtils.drawOptimizedRoundedRect((width - 340) / 2f, y, 340, 54, new Color(0, 0, 0, 120)); - if (Render2DUtils.isHovered((width - 340) / 2f, y, 340, 54, mouseX, mouseY)) { - Render2DUtils.drawOptimizedRoundedRect((width - 340) / 2f, y, 340, 54, new Color(0, 0, 0, 50)); + Render2DUtils.drawOptimizedRoundedRect((guiWidth - 340) / 2f, y, 340, 54, new Color(0, 0, 0, 120)); + if (Render2DUtils.isHovered((guiWidth - 340) / 2f, y, 340, 54, mouseX, mouseY)) { + Render2DUtils.drawOptimizedRoundedRect((guiWidth - 340) / 2f, y, 340, 54, new Color(0, 0, 0, 50)); } if (selectedServer != null && selectedServer == server.getServerData()) { - Render2DUtils.drawOptimizedRoundedRect((width - 340) / 2f, y, 340, 54, new Color(255, 255, 255, 50)); + Render2DUtils.drawOptimizedRoundedRect((guiWidth - 340) / 2f, y, 340, 54, new Color(255, 255, 255, 50)); } - server.drawEntry(0, (width - 340) / 2, (int) y, 340, 54, mouseX, mouseY, false); + server.drawEntry(0, (int) ((guiWidth - 340) / 2), (int) y, 340, 54, mouseX, mouseY, false); y += 58; } scrollContainer.setHeight(y - 50 - scrollContainer.getScroll()); @@ -206,17 +206,14 @@ public void render(int mouseX, int mouseY, float partialTicks) { GL11.glPopMatrix(); - join.render((width - 400) / 2f + 20, height - 56, 380f / 3 - 20, 20, mouseX, mouseY); - connect.render((width - 400) / 2f + 20 + 380f / 3, height - 56, 380f / 3 - 20, 20, mouseX, mouseY); - add.render((width - 400) / 2f + 20 + 380f / 3 * 2, height - 56, 380f / 3 - 20, 20, mouseX, mouseY); - - - edit.render((width - 400) / 2f + 20, height - 26, 380f / 4 - 20, 20, mouseX, mouseY); - remove.render((width - 400) / 2f + 20 + 380f / 4, height - 26, 380f / 4 - 20, 20, mouseX, mouseY); - refresh.render((width - 400) / 2f + 20 + 380f / 4 * 2, height - 26, 380f / 4 - 20, 20, mouseX, mouseY); - back.render((width - 400) / 2f + 20 + 380f / 4 * 3, height - 26, 380f / 4 - 20, 20, mouseX, mouseY); - + join.render((guiWidth - 400) / 2f + 20, guiHeight - 56, 380f / 3 - 20, 20, mouseX, mouseY); + connect.render((guiWidth - 400) / 2f + 20 + 380f / 3, guiHeight - 56, 380f / 3 - 20, 20, mouseX, mouseY); + add.render((guiWidth - 400) / 2f + 20 + 380f / 3 * 2, guiHeight - 56, 380f / 3 - 20, 20, mouseX, mouseY); + edit.render((guiWidth - 400) / 2f + 20, guiHeight - 26, 380f / 4 - 20, 20, mouseX, mouseY); + remove.render((guiWidth - 400) / 2f + 20 + 380f / 4, guiHeight - 26, 380f / 4 - 20, 20, mouseX, mouseY); + refresh.render((guiWidth - 400) / 2f + 20 + 380f / 4 * 2, guiHeight - 26, 380f / 4 - 20, 20, mouseX, mouseY); + back.render((guiWidth - 400) / 2f + 20 + 380f / 4 * 3, guiHeight - 26, 380f / 4 - 20, 20, mouseX, mouseY); } @@ -246,16 +243,16 @@ public void onClick(int mouseX, int mouseY, int mouseButton) { back.mouseClick(mouseX, mouseY, mouseButton); - Render2DUtils.drawOptimizedRoundedRect((width - 180) / 2f, 30, 180, 24, 3, new Color(255, 255, 255, 80).getRGB()); - Render2DUtils.drawOptimizedRoundedRect((width - 176) / 2f, 32, 86, 20, 3, new Color(113, 127, 254).getRGB()); - FPSMaster.fontManager.s16.drawCenteredString("服务器列表", (width - 90) / 2f, 36, -1); - FPSMaster.fontManager.s16.drawCenteredString("推荐服务器", (width + 90) / 2f, 36, -1); + Render2DUtils.drawOptimizedRoundedRect((guiWidth - 180) / 2f, 30, 180, 24, 3, new Color(255, 255, 255, 80).getRGB()); + Render2DUtils.drawOptimizedRoundedRect((guiWidth - 176) / 2f, 32, 86, 20, 3, new Color(113, 127, 254).getRGB()); + FPSMaster.fontManager.s16.drawCenteredString("服务器列表", (guiWidth - 90) / 2f, 36, -1); + FPSMaster.fontManager.s16.drawCenteredString("推荐服务器", (guiWidth + 90) / 2f, 36, -1); - if (Render2DUtils.isHovered((width - 180) / 2f, 30, 90, 24, mouseX, mouseY)) { + if (Render2DUtils.isHovered((guiWidth - 180) / 2f, 30, 90, 24, mouseX, mouseY)) { tab = 0; serverListDisplay.clear(); serverListDisplay.addAll(serverListInternet); - } else if (Render2DUtils.isHovered((width) / 2f, 30, 90, 24, mouseX, mouseY)) { + } else if (Render2DUtils.isHovered((guiWidth) / 2f, 30, 90, 24, mouseX, mouseY)) { tab = 1; serverListDisplay.clear(); serverListDisplay.addAll(serverListRecommended); @@ -267,7 +264,7 @@ public void onClick(int mouseX, int mouseY, int mouseButton) { if (server.getServerData() == null) { return; } - if (Render2DUtils.isHovered((width - 340) / 2f, y, 340, 54, mouseX, mouseY)) { + if (Render2DUtils.isHovered((guiWidth - 340) / 2f, y, 340, 54, mouseX, mouseY)) { if (selectedServer != server.getServerData()) { selectedServer = server.getServerData(); timer.reset(); diff --git a/shared/java/top/fpsmaster/utils/thirdparty/openai/OpenAIClient.java b/shared/java/top/fpsmaster/utils/thirdparty/openai/OpenAIClient.java index 747d3f52..f2fa5bab 100644 --- a/shared/java/top/fpsmaster/utils/thirdparty/openai/OpenAIClient.java +++ b/shared/java/top/fpsmaster/utils/thirdparty/openai/OpenAIClient.java @@ -60,6 +60,8 @@ public static void getChatResponseAsync(ArrayList userMessages, Respons } callback.onResponse(responseBuilder.toString()); // 非阻塞调用,处理数据 } + } catch (FileException e) { + throw new RuntimeException(e); } } catch (IOException e) { callback.onError(e); @@ -73,12 +75,8 @@ private static HttpPost createPostRequest(String jsonBody) { postRequest.setHeader("Authorization", "Bearer " + API_KEY); postRequest.setHeader("Content-Type", "application/json; charset=UTF-8\""); - try { - StringEntity entity = new StringEntity(jsonBody, "UTF-8"); - postRequest.setEntity(entity); - } catch (Exception e) { - e.printStackTrace(); - } + StringEntity entity = new StringEntity(jsonBody, "UTF-8"); + postRequest.setEntity(entity); return postRequest; } diff --git a/v1.8.9/src/main/java/top/fpsmaster/forge/Mod.java b/v1.8.9/src/main/java/top/fpsmaster/forge/Mod.java index 5d4c6465..bc6aa5a9 100644 --- a/v1.8.9/src/main/java/top/fpsmaster/forge/Mod.java +++ b/v1.8.9/src/main/java/top/fpsmaster/forge/Mod.java @@ -3,8 +3,9 @@ import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.fml.common.event.FMLInitializationEvent; import top.fpsmaster.FPSMaster; +import top.fpsmaster.exception.FileException; -@net.minecraftforge.fml.common.Mod(modid = "fpsmaster", useMetadata=true) +@net.minecraftforge.fml.common.Mod(modid = "fpsmaster", useMetadata = true) public class Mod { @net.minecraftforge.fml.common.Mod.EventHandler public void init(FMLInitializationEvent event) { From e55c5f135eadf0af31a5bbe9dadf01e6517369c5 Mon Sep 17 00:00:00 2001 From: SuperSkidder Date: Sun, 13 Jul 2025 12:10:25 +0800 Subject: [PATCH 068/193] fix: oldanimation blockswing wouldn't send packets now fix: sprint may cause anticheat verbose in some servers add: devauth --- .../impl/optimizes/OldAnimations.java | 25 ++++++++++++++- .../features/impl/utility/Sprint.java | 31 ++++++++++--------- .../top/fpsmaster/ui/mc/GuiMultiplayer.java | 2 +- v1.8.9/build.gradle.kts | 3 +- .../forge/mixin/MixinKeybinding.java | 15 +++++++++ 5 files changed, 58 insertions(+), 18 deletions(-) diff --git a/shared/java/top/fpsmaster/features/impl/optimizes/OldAnimations.java b/shared/java/top/fpsmaster/features/impl/optimizes/OldAnimations.java index 3468837b..c203b7cc 100644 --- a/shared/java/top/fpsmaster/features/impl/optimizes/OldAnimations.java +++ b/shared/java/top/fpsmaster/features/impl/optimizes/OldAnimations.java @@ -3,6 +3,10 @@ import net.minecraft.client.Minecraft; import net.minecraft.client.entity.EntityPlayerSP; import net.minecraft.entity.EntityLivingBase; +import net.minecraft.item.ItemStack; +import net.minecraft.network.play.server.S0BPacketAnimation; +import net.minecraft.potion.Potion; +import net.minecraft.world.WorldServer; import top.fpsmaster.event.Subscribe; import top.fpsmaster.event.events.EventTick; import top.fpsmaster.features.manager.Category; @@ -12,6 +16,8 @@ import top.fpsmaster.features.settings.impl.NumberSetting; import top.fpsmaster.interfaces.ProviderManager; +import static top.fpsmaster.utils.Utility.mc; + public class OldAnimations extends Module { public static BooleanSetting noShield = new BooleanSetting("NoShield", true); @@ -71,7 +77,7 @@ public void onTick(EventTick event) { eyeHeight = START_HEIGHT - delta; } if (Minecraft.getMinecraft().gameSettings.keyBindAttack.isKeyDown() && thePlayer.isUsingItem() && blockSwing.value) { - ((EntityLivingBase) thePlayer).swingItem(); + swingItem(); } } @@ -91,4 +97,21 @@ public static boolean isUsing() { public static void setUsing(boolean using) { OldAnimations.using = using; } + + public void swingItem() { + ItemStack stack = mc.thePlayer.getHeldItem(); + if (stack == null || stack.getItem() == null || !stack.getItem().onEntitySwing(mc.thePlayer, stack)) { + if (!mc.thePlayer.isSwingInProgress || mc.thePlayer.swingProgressInt >= getArmSwingAnimationEnd() / 2 || mc.thePlayer.swingProgressInt < 0) { + mc.thePlayer.swingProgressInt = -1; + mc.thePlayer.isSwingInProgress = true; + if (mc.thePlayer.worldObj instanceof WorldServer) { + ((WorldServer)mc.thePlayer.worldObj).getEntityTracker().sendToAllTrackingEntity(mc.thePlayer, new S0BPacketAnimation(mc.thePlayer, 0)); + } + } + } + } + + private int getArmSwingAnimationEnd() { + return mc.thePlayer.isPotionActive(Potion.digSpeed) ? 6 - (1 + mc.thePlayer.getActivePotionEffect(Potion.digSpeed).getAmplifier()) : (mc.thePlayer.isPotionActive(Potion.digSlowdown) ? 6 + (1 + mc.thePlayer.getActivePotionEffect(Potion.digSlowdown).getAmplifier()) * 2 : 6); + } } diff --git a/shared/java/top/fpsmaster/features/impl/utility/Sprint.java b/shared/java/top/fpsmaster/features/impl/utility/Sprint.java index c60e0e62..8e0d98e3 100644 --- a/shared/java/top/fpsmaster/features/impl/utility/Sprint.java +++ b/shared/java/top/fpsmaster/features/impl/utility/Sprint.java @@ -15,6 +15,8 @@ import static top.fpsmaster.utils.Utility.mc; public class Sprint extends InterfaceModule { + public static boolean using = true; + public static boolean sprint = true; BooleanSetting toggleSprint = new BooleanSetting("ToggleSprint", true); @@ -23,29 +25,26 @@ public Sprint() { addSettings(toggleSprint, betterFont); } - public static boolean sprint = true; + + @Override + public void onEnable() { + super.onEnable(); + using = true; + } @Subscribe public void onUpdate(EventUpdate e) { - if (sprint || !toggleSprint.getValue()) { - if (mc.thePlayer.moveForward <= 0) - return; - if (mc.thePlayer.isCollidedHorizontally) - return; - if (mc.thePlayer.isPotionActive(Potion.blindness)) - return; - if (mc.thePlayer.getFoodStats().getFoodLevel() < 6f) - return; - if (mc.thePlayer.isUsingItem()) - return; - mc.thePlayer.setSprinting(true); + if (!toggleSprint.getValue()) { + sprint = true; } } @Subscribe - public void onKey(EventKey e){ - if (e.key == mc.gameSettings.keyBindSprint.getKeyCode()) { + public void onKey(EventKey e) { + if (toggleSprint.getValue() && e.key == mc.gameSettings.keyBindSprint.getKeyCode()) { sprint = !sprint; + if (!sprint) + mc.thePlayer.setSprinting(false); } } @@ -53,5 +52,7 @@ public void onKey(EventKey e){ public void onDisable() { super.onDisable(); ProviderManager.gameSettings.setKeyPress(mc.gameSettings.keyBindSprint, false); + mc.thePlayer.setSprinting(false); + using = false; } } \ No newline at end of file diff --git a/shared/java/top/fpsmaster/ui/mc/GuiMultiplayer.java b/shared/java/top/fpsmaster/ui/mc/GuiMultiplayer.java index d8d9b460..9ba3c326 100644 --- a/shared/java/top/fpsmaster/ui/mc/GuiMultiplayer.java +++ b/shared/java/top/fpsmaster/ui/mc/GuiMultiplayer.java @@ -106,7 +106,7 @@ public void initGui() { if (serverListRecommended.size() == 0) { AsyncTask asyncTask = new AsyncTask(100); asyncTask.runnable(() -> { - String s = HttpRequest.get("https://service.fpsmaster.top/getServers"); + String s = HttpRequest.get("https://service.fpsmaster.top/api/client/servers"); System.out.println(s); JsonObject jsonObject = gson.fromJson(s, JsonObject.class); jsonObject.get("data").getAsJsonArray().forEach(e -> { diff --git a/v1.8.9/build.gradle.kts b/v1.8.9/build.gradle.kts index db3989ed..e82246af 100644 --- a/v1.8.9/build.gradle.kts +++ b/v1.8.9/build.gradle.kts @@ -71,6 +71,7 @@ repositories { maven("https://repo.spongepowered.org/maven/") // If you don't want to log in with your real minecraft account, remove this line maven("https://pkgs.dev.azure.com/djtheredstoner/DevAuth/_packaging/public/maven/v1") + } val shadowImpl: Configuration by configurations.creating { @@ -112,7 +113,7 @@ dependencies { isTransitive = false } // If you don't want to log in with your real minecraft account, remove this line -// runtimeOnly("me.djtheredstoner:DevAuth-forge-legacy:1.1.2") + runtimeOnly("me.djtheredstoner:DevAuth-forge-legacy:1.1.2") implementation("javazoom:jlayer:1.0.1") // https://mvnrepository.com/artifact/net.sourceforge.jtransforms/jtransforms implementation("net.sourceforge.jtransforms:jtransforms:2.4.0") diff --git a/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinKeybinding.java b/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinKeybinding.java index 725d2e73..606037fa 100644 --- a/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinKeybinding.java +++ b/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinKeybinding.java @@ -1,12 +1,19 @@ package top.fpsmaster.forge.mixin; import net.minecraft.client.settings.KeyBinding; +import org.lwjgl.input.Keyboard; import org.spongepowered.asm.mixin.Implements; import org.spongepowered.asm.mixin.Interface; 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.callback.CallbackInfoReturnable; +import top.fpsmaster.features.impl.utility.Sprint; import top.fpsmaster.forge.api.IKeyBinding; +import static top.fpsmaster.utils.Utility.mc; + @Mixin(KeyBinding.class) @Implements(@Interface(iface = IKeyBinding.class, prefix = "fpsmaster$")) public class MixinKeybinding implements IKeyBinding { @@ -14,8 +21,16 @@ public class MixinKeybinding implements IKeyBinding { @Shadow private boolean pressed; + @Shadow private int keyCode; + @Override public void setPressed(boolean pressed) { this.pressed = pressed; } + + @Inject(method = "isKeyDown", at = @At("HEAD"), cancellable = true) + public void keyDown(CallbackInfoReturnable cir) { + if (Sprint.using && keyCode == mc.gameSettings.keyBindSprint.getKeyCode()) + cir.setReturnValue(Sprint.sprint); + } } From 70565b31b0c5eaad98861534f3d8f058d6db33f4 Mon Sep 17 00:00:00 2001 From: SuperSkidder Date: Sun, 13 Jul 2025 13:24:30 +0800 Subject: [PATCH 069/193] fix: Damage Indicator fix: fullbright wouldn't work when game restarting --- .../features/impl/render/DamageIndicator.java | 23 +++++++++++++++++- .../features/impl/render/FullBright.java | 7 ++++++ .../forge/mixin/MixinEntityLivingBase.java | 24 ------------------- 3 files changed, 29 insertions(+), 25 deletions(-) diff --git a/shared/java/top/fpsmaster/features/impl/render/DamageIndicator.java b/shared/java/top/fpsmaster/features/impl/render/DamageIndicator.java index e189ab75..fa3e69af 100644 --- a/shared/java/top/fpsmaster/features/impl/render/DamageIndicator.java +++ b/shared/java/top/fpsmaster/features/impl/render/DamageIndicator.java @@ -3,10 +3,13 @@ import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.GlStateManager; import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.item.EntityTNTPrimed; import org.lwjgl.opengl.GL11; import top.fpsmaster.event.Subscribe; +import top.fpsmaster.event.events.EventAttack; import top.fpsmaster.event.events.EventRender3D; +import top.fpsmaster.event.events.EventUpdate; import top.fpsmaster.features.manager.Category; import top.fpsmaster.features.manager.Module; import top.fpsmaster.interfaces.ProviderManager; @@ -19,6 +22,8 @@ import java.util.HashMap; public class DamageIndicator extends Module { + private EntityLivingBase lastAttack; + public DamageIndicator() { super("DamageIndicator", Category.RENDER); } @@ -30,7 +35,23 @@ public static void addIndicator(float x, float y, float z, float damage) { } MathTimer timer = new MathTimer(); + float health = 0; + + @Subscribe + public void onAttack(EventAttack e) { + if (e.target instanceof EntityLivingBase) { + lastAttack = (EntityLivingBase) e.target; + health = lastAttack.getHealth(); + } + } + @Subscribe + public void onUpdate(EventUpdate e) { + if (health - lastAttack.getHealth() != 0){ + addIndicator((float) (lastAttack.posX), (float) (lastAttack.posY - 1), (float) (lastAttack.posZ), health - lastAttack.getHealth()); + health = lastAttack.getHealth(); + } + } @Subscribe public void onRender(EventRender3D event) { @@ -71,7 +92,7 @@ public void doRender(Damage indicator) { GL11.glNormal3f(0.0f, 1.0f, 0.0f); GlStateManager.rotate(-mc.getRenderManager().playerViewY, 0.0f, 1.0f, 0.0f); GL11.glScalef(-scale / 2, -scale, -scale); - float width = ProviderManager.mcProvider.getFontRenderer().getStringWidth(damage) / 2.0f + 6.0f; + float width = ProviderManager.mcProvider.getFontRenderer().getStringWidth(damage) / 2.0f; GlStateManager.disableDepth(); GlStateManager.disableBlend(); GlStateManager.disableLighting(); diff --git a/shared/java/top/fpsmaster/features/impl/render/FullBright.java b/shared/java/top/fpsmaster/features/impl/render/FullBright.java index c47fffe1..3425c008 100644 --- a/shared/java/top/fpsmaster/features/impl/render/FullBright.java +++ b/shared/java/top/fpsmaster/features/impl/render/FullBright.java @@ -1,6 +1,8 @@ package top.fpsmaster.features.impl.render; import net.minecraft.client.Minecraft; +import top.fpsmaster.event.Subscribe; +import top.fpsmaster.event.events.EventUpdate; import top.fpsmaster.features.manager.Category; import top.fpsmaster.features.manager.Module; @@ -17,6 +19,11 @@ public void onEnable(){ super.onEnable(); } + @Subscribe + public void onUpdate(EventUpdate e){ + Minecraft.getMinecraft().gameSettings.gammaSetting = 100f; + } + @Override public void onDisable(){ Minecraft.getMinecraft().gameSettings.gammaSetting = oldGamma; diff --git a/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinEntityLivingBase.java b/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinEntityLivingBase.java index d77c3bc1..5b7f5aae 100644 --- a/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinEntityLivingBase.java +++ b/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinEntityLivingBase.java @@ -17,28 +17,4 @@ public abstract class MixinEntityLivingBase extends MixinEntity { @Shadow public abstract IAttributeInstance getEntityAttribute(IAttribute attribute); - - @Shadow - public abstract float getHealth(); - - @Inject(method = "damageEntity", at = @At(value = "INVOKE",target = "Lnet/minecraft/entity/EntityLivingBase;setHealth(F)V", shift = At.Shift.BEFORE)) - protected void damageEntity(DamageSource damageSrc, float damageAmount, CallbackInfo ci) { - EntityLivingBase entity = (EntityLivingBase) ((Object) this); - BlockPos position = entity.getPosition(); - if (damageAmount > entity.getHealth()){ - damageAmount = entity.getHealth(); - } - DamageIndicator.addIndicator(position.getX(), position.getY(), position.getZ(), damageAmount); - } - - @Inject(method = "heal", at = @At(value = "INVOKE",target = "Lnet/minecraft/entity/EntityLivingBase;setHealth(F)V", shift = At.Shift.BEFORE)) - public void heal(float healAmount, CallbackInfo ci) { - EntityLivingBase entity = (EntityLivingBase) ((Object) this); - BlockPos position = entity.getPosition(); - if (healAmount > entity.getMaxHealth() - entity.getHealth()) { - healAmount = entity.getMaxHealth() - entity.getHealth(); - } - DamageIndicator.addIndicator(position.getX(), position.getY(), position.getZ(), -healAmount); - } - } From 521a8f57e29f101db56ccd6cefd9db841dcc9ded Mon Sep 17 00:00:00 2001 From: SuperSkidder Date: Sun, 13 Jul 2025 13:30:02 +0800 Subject: [PATCH 070/193] chore: github action and better readme --- README.md | 7 +++++-- docs/tasks.md | 10 ++++------ 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 3e996f01..42b8e764 100644 --- a/README.md +++ b/README.md @@ -18,8 +18,11 @@ FPSMaster 是一个免费、强大的 Minecraft PvP 客户端。 3. 本分支的1.12.2版本代码暂时不会更新,因此使用1.12.2版本会报错是正常现象。 -### 开发任务 -查看我们的[任务列表](docs/tasks.md)了解当前的开发计划和进度。 +### 开发 + - 查看我们的[代码规范](docs/code_standards.md)了解如何编写符合我们要求的代码。 + - 查看我们的[环境配置](docs/development_environment.md)了解如何配置开发环境。 + - 查看我们的[开发指南](docs/development_tutorial.md)了解如何使用我们的模块系统、配置系统等,并完成你的需求。 + - 查看我们的[任务列表](docs/tasks.md)了解当前的开发计划和进度。 ## 开源许可证 diff --git a/docs/tasks.md b/docs/tasks.md index 1e2b6326..ed0c9066 100644 --- a/docs/tasks.md +++ b/docs/tasks.md @@ -28,16 +28,14 @@ ### 模块系统 1. [ ] 创建使用注解而非硬编码列表的模块注册系统 -2. [ ] 实现适当的模块生命周期管理系统(初始化、启动、停止、销毁) -3. [ ] 开发模块依赖解析系统 -4. [ ] 重构模块类别以使用更灵活的分类法 +2. [ ] 重构模块类别以使用更灵活的分类法 +3. [ ] 实现更加高级的Values系统 ### 事件系统 1. [ ] 优化事件分发以提高性能 2. [ ] 实现事件优先级 -3. [ ] 添加事件取消支持 -4. [ ] 创建全面的事件文档 -5. [ ] 添加事件调试/监控工具 +3. [ ] 创建全面的事件文档 +4. [ ] 添加事件调试/监控工具 ### 配置系统 1. [ ] 重构配置保存格式 From 74ecbdab6b06e054881652e4876328bd25679df7 Mon Sep 17 00:00:00 2001 From: SuperSkidder Date: Sun, 13 Jul 2025 13:30:44 +0800 Subject: [PATCH 071/193] chore: github action --- .github/workflows/gradle.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml index b475bde3..ecb758ce 100644 --- a/.github/workflows/gradle.yml +++ b/.github/workflows/gradle.yml @@ -90,4 +90,4 @@ jobs: --data-urlencode "date=$(date -u +%Y-%m-%dT%H:%M:%SZ)" \ --data-urlencode "link=$DOWNLOAD_URL" \ --data-urlencode "release=false" \ - "https://service.fpsmaster.top/pushVersion" + "https://service.fpsmaster.top/api/github/push" From ffd0ee3b5d3f6d27487173a9f1469d9aecb40c55 Mon Sep 17 00:00:00 2001 From: SuperSkidder Date: Sun, 13 Jul 2025 14:09:45 +0800 Subject: [PATCH 072/193] chore: github action version name --- .github/workflows/gradle.yml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml index ecb758ce..de335329 100644 --- a/.github/workflows/gradle.yml +++ b/.github/workflows/gradle.yml @@ -40,8 +40,10 @@ jobs: run: | cd v1.8.9 - version=$(awk -F'=' '/^version[[:space:]]*=/ {print $2}' gradle.properties | tr -d '[:space:]') - + plain_version=$(awk -F'=' '/^version[[:space:]]*=/ {print $2}' gradle.properties | tr -d '[:space:]') + sha=$(git rev-parse --short=6 HEAD) + version="${plain_version}-${sha}" + mkdir -p build/libs cd build/libs From de37ac1a0f1a3a8da5bd4e41c7142ff991d3f581 Mon Sep 17 00:00:00 2001 From: SuperSkidder Date: Sun, 13 Jul 2025 18:09:30 +0800 Subject: [PATCH 073/193] fix: new service api --- .../fpsmaster/exception/ExceptionHandler.java | 21 +++++----- .../features/impl/render/DamageIndicator.java | 2 + .../modules/account/AccountManager.java | 41 +++++++------------ .../ui/screens/oobe/impls/Login.java | 31 ++++++-------- 4 files changed, 41 insertions(+), 54 deletions(-) diff --git a/shared/java/top/fpsmaster/exception/ExceptionHandler.java b/shared/java/top/fpsmaster/exception/ExceptionHandler.java index a5739a93..f4871b9d 100644 --- a/shared/java/top/fpsmaster/exception/ExceptionHandler.java +++ b/shared/java/top/fpsmaster/exception/ExceptionHandler.java @@ -89,16 +89,17 @@ private static void logExceptionDetails(Exception e, String category) { if (cause != null) { ClientLogger.error(category + " Exception", "Caused by: " + cause.getClass().getName() + ": " + cause.getMessage()); } + e.printStackTrace(); - // Log stack trace in a structured way - StringWriter sw = new StringWriter(); - PrintWriter pw = new PrintWriter(sw); - e.printStackTrace(pw); - - // Split the stack trace into lines and log each line - String[] stackTraceLines = sw.toString().split("\\r?\\n"); - for (String line : stackTraceLines) { - ClientLogger.debug(line); - } +// Log stack trace in a structured way +// StringWriter sw = new StringWriter(); +// PrintWriter pw = new PrintWriter(sw); +// e.printStackTrace(pw); +// +// // Split the stack trace into lines and log each line +// String[] stackTraceLines = sw.toString().split("\\r?\\n"); +// for (String line : stackTraceLines) { +// ClientLogger.debug(line); +// } } } diff --git a/shared/java/top/fpsmaster/features/impl/render/DamageIndicator.java b/shared/java/top/fpsmaster/features/impl/render/DamageIndicator.java index fa3e69af..64ce9dbc 100644 --- a/shared/java/top/fpsmaster/features/impl/render/DamageIndicator.java +++ b/shared/java/top/fpsmaster/features/impl/render/DamageIndicator.java @@ -47,6 +47,8 @@ public void onAttack(EventAttack e) { @Subscribe public void onUpdate(EventUpdate e) { + if (lastAttack == null) + return; if (health - lastAttack.getHealth() != 0){ addIndicator((float) (lastAttack.posX), (float) (lastAttack.posY - 1), (float) (lastAttack.posZ), health - lastAttack.getHealth()); health = lastAttack.getHealth(); diff --git a/shared/java/top/fpsmaster/modules/account/AccountManager.java b/shared/java/top/fpsmaster/modules/account/AccountManager.java index 5b8ba597..b136daf5 100644 --- a/shared/java/top/fpsmaster/modules/account/AccountManager.java +++ b/shared/java/top/fpsmaster/modules/account/AccountManager.java @@ -11,6 +11,8 @@ import top.fpsmaster.utils.os.FileUtils; import top.fpsmaster.utils.os.HttpRequest; +import java.util.HashMap; + public class AccountManager { private String token = ""; private String username = ""; @@ -34,12 +36,11 @@ public void autoLogin() { private void doAutoLogin() throws FileException, AccountException, NetworkException { token = FileUtils.readTempValue("token").trim(); - username = FPSMaster.configManager.configure.getOrCreate("username", "").trim(); // Since we do the empty check, we should make it empty. + username = FPSMaster.configManager.configure.getOrCreate("username", "").trim(); if (!token.isEmpty() && !username.isEmpty()) { if (attemptLogin(username, token)) { ClientLogger.info("自动登录成功! " + username); FPSMaster.INSTANCE.loggedIn = true; - getItems(username, token); } else { ClientLogger.info(username); ClientLogger.error("自动登录失败!"); @@ -53,32 +54,16 @@ private boolean attemptLogin(String username, String token) throws NetworkExcept return false; } try { - String s = HttpRequest.get(FPSMaster.SERVICE_API + "/checkToken?username=" + username + "&token=" + token + "×tamp=" + System.currentTimeMillis()); + HashMap headers = new HashMap<>(); + headers.put("Authorization","Bearer " + token); + System.out.println("Bearer " + token); + String s = HttpRequest.get(FPSMaster.SERVICE_API + "/api/auth/validate-jwt", headers); JsonObject json = parser.parse(s).getAsJsonObject(); this.username = username; this.token = token; - return json.get("code").getAsInt() == 200; + return json.get("data").getAsJsonObject().get("success").getAsBoolean(); } catch (Exception e) { - throw new NetworkException("Failed to check token", e); - } - } - - public void getItems(String username, String token) throws NetworkException { - try { - String s = HttpRequest.get(FPSMaster.SERVICE_API + "/getWebUser?username=" + username + "&token=" + token + "×tamp=" + System.currentTimeMillis()); - JsonObject json = parser.parse(s).getAsJsonObject(); - if (json.get("code").getAsInt() == 200) { - String items = json.getAsJsonObject("data").getAsJsonObject("items").getAsString(); - itemsHeld = items.split(","); - itemsHeld = itemsHeld.length > 0 ? itemsHeld : new String[0]; // Ensuring it's not empty - } else { - throw new NetworkException("Failed to get items: " + json.get("message").getAsString()); - } - } catch (Exception e) { - if (e instanceof NetworkException) { - throw (NetworkException) e; - } - throw new NetworkException("Failed to get items", e); + throw new NetworkException("Failed to login via token", e); } } @@ -88,9 +73,13 @@ public void getItems(String username, String token) throws NetworkException { public static JsonObject login(String username, String password) throws NetworkException { try { - String s = HttpRequest.get(FPSMaster.SERVICE_API + "/login?username=" + username + "&password=" + password + "×tamp=" + System.currentTimeMillis()); + JsonObject body = new JsonObject(); + body.addProperty("username", username); + body.addProperty("password", password); + String s = HttpRequest.post(FPSMaster.SERVICE_API + "/api/auth/login", body.toString()); + JsonObject jsonObject = parser.parse(s).getAsJsonObject(); - if (jsonObject.get("code").getAsInt() != 200) { + if (!jsonObject.get("data").getAsJsonObject().get("success").getAsBoolean()) { throw new NetworkException("Login failed: " + jsonObject.get("message").getAsString()); } return jsonObject; diff --git a/shared/java/top/fpsmaster/ui/screens/oobe/impls/Login.java b/shared/java/top/fpsmaster/ui/screens/oobe/impls/Login.java index 50cdfe61..af8b182a 100644 --- a/shared/java/top/fpsmaster/ui/screens/oobe/impls/Login.java +++ b/shared/java/top/fpsmaster/ui/screens/oobe/impls/Login.java @@ -43,25 +43,20 @@ public Login(boolean isOOBE) { btn = new GuiButton(FPSMaster.i18n.get("oobe.login.login"), () -> { try { JsonObject login = AccountManager.login(username.getText(), password.getText()); - if (login.get("code").getAsInt() == 200) { - if (FPSMaster.accountManager != null) { - FPSMaster.accountManager.setUsername(username.getText()); - FPSMaster.accountManager.setToken(login.get("msg").getAsString()); - } - try { - FileUtils.saveTempValue("token", FPSMaster.accountManager.getToken()); - } catch (FileException e) { - ExceptionHandler.handleFileException(e, "无法保存登录令牌"); - } - FPSMaster.INSTANCE.loggedIn = true; - if (isOOBE) { - FPSMaster.oobeScreen.nextScene(); - } else { - Minecraft.getMinecraft().displayGuiScreen(new MainMenu()); - } + if (FPSMaster.accountManager != null) { + FPSMaster.accountManager.setUsername(username.getText()); + FPSMaster.accountManager.setToken(login.get("data").getAsJsonObject().get("token").getAsString()); + } + try { + FileUtils.saveTempValue("token", FPSMaster.accountManager.getToken()); + } catch (FileException e) { + ExceptionHandler.handleFileException(e, "无法保存登录令牌"); + } + FPSMaster.INSTANCE.loggedIn = true; + if (isOOBE) { + FPSMaster.oobeScreen.nextScene(); } else { - msg = login.get("msg").getAsString(); - msgbox = true; + Minecraft.getMinecraft().displayGuiScreen(new MainMenu()); } } catch (NetworkException e) { ExceptionHandler.handleNetworkException(e, "登录失败"); From b19d002037c8fee02f0bad2c639c719ae33a155d Mon Sep 17 00:00:00 2001 From: SuperSkidder Date: Sun, 13 Jul 2025 19:01:48 +0800 Subject: [PATCH 074/193] change phase to beta auto update some adjust --- .github/workflows/nightly.yml | 124 ++++++++++++++++++ .github/workflows/{gradle.yml => publish.yml} | 5 +- shared/java/top/fpsmaster/FPSMaster.java | 28 ++-- .../modules/account/AccountManager.java | 1 - .../ui/screens/mainmenu/MainMenu.java | 4 +- .../thirdparty/github/UpdateChecker.java | 5 +- .../assets/minecraft/client/lang/zh_cn.lang | 2 +- v1.8.9/gradle.properties | 2 +- 8 files changed, 144 insertions(+), 27 deletions(-) create mode 100644 .github/workflows/nightly.yml rename .github/workflows/{gradle.yml => publish.yml} (97%) diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml new file mode 100644 index 00000000..45527192 --- /dev/null +++ b/.github/workflows/nightly.yml @@ -0,0 +1,124 @@ +name: Java CI with Gradle - Nightly + +on: + schedule: + - cron: '0 2 * * *' + workflow_dispatch: + +jobs: + build: + runs-on: ubuntu-latest + permissions: + contents: read + + steps: + - uses: actions/checkout@v4 + + - name: Get latest commit hash + id: current + run: | + echo "sha=$(git rev-parse HEAD)" >> $GITHUB_OUTPUT + + - name: Get last published commit hash + id: last + run: | + last_sha=$(curl -s "https://service.fpsmaster.top/api/github/latest/commit?branch=${GITHUB_REF}") + echo "sha=$last_sha" >> $GITHUB_OUTPUT + + - name: Check if new commit exists + id: check + run: | + if [ "${{ steps.current.outputs.sha }}" = "${{ steps.last.outputs.sha }}" ]; then + echo "No new commit since last build. Skipping." + echo "skip=true" >> $GITHUB_OUTPUT + else + echo "New commit detected. Continuing." + echo "skip=false" >> $GITHUB_OUTPUT + fi + + - name: Stop if no new commit + if: steps.check.outputs.skip == 'true' + run: exit 0 + + - name: Set up JDK 17 + uses: actions/setup-java@v4 + with: + java-version: '17' + distribution: 'temurin' + + - name: Setup Gradle + uses: gradle/actions/setup-gradle@417ae3ccd767c252f5661f1ace9f835f9654f2b5 # v3.1.0 + with: + gradle-version: '8.6' + + - name: Build with Gradle Wrapper + run: | + chmod +x ./v1.8.9/gradlew + cd v1.8.9 + ./gradlew build + + - name: Upload v1.8.9 artifacts + uses: actions/upload-artifact@v4.3.3 + with: + name: v1.8.9 + path: v1.8.9/build/libs/ + + - name: Upload artifact + run: | + cd v1.8.9 + + plain_version=$(awk -F'=' '/^version[[:space:]]*=/ {print $2}' gradle.properties | tr -d '[:space:]') + sha=$(git rev-parse --short=6 HEAD) + date=$(date -u +%Y%m%d) + version="${plain_version}-nightly-${sha}" + filename="fpsmaster-nightly-${date}.zip" + + mkdir -p build/libs + cd build/libs + + export JAR=$(find . -name "*.jar") + mkdir -p zip + cp "$JAR" zip/fpsmaster.jar + cd zip + zip -r "$filename" * + + # 创建存储目录 + RESPONSE=$(curl --location --request POST "https://api.kstore.space/api/v1/file/create" \ + --header "X-GitHub-Event: workflow_run" \ + --header "User-Agent: Apifox/1.0.0 (https://apifox.com)" \ + --form "access_token=${{ secrets.OSS }}" \ + --form "fileId=0" \ + --form "name=action-${{ github.sha }}") + + DIR_ID=$(echo "$RESPONSE" | jq -r '.data.id') + echo "DirectoryId: $DIR_ID" + + # 上传文件 + UPLOAD_RESPONSE=$(curl --location --request POST "https://upload.kstore.space/upload/$DIR_ID?access_token=${{ secrets.OSS }}" \ + -F "file=@$filename") + + DOWNLOAD_URL=$(echo "$UPLOAD_RESPONSE" | jq -r '.data.downloadUrl') + FILE_ID=$(echo "$UPLOAD_RESPONSE" | jq -r '.data.id') + + echo "FileId: $FILE_ID" + echo "URL: $DOWNLOAD_URL" + + # 设为直接下载 + RESPONSE=$(curl --location --request POST "https://api.kstore.cc/api/v1/file/direct?access_token=${{ secrets.OSS }}" \ + --form "fileId=$FILE_ID" \ + --form "isDirect=1") + + echo "$RESPONSE" + + echo "$(date -u +%Y-%m-%dT%H:%M:%SZ)" + + # 推送版本信息 + curl --get \ + --data-urlencode "key=${{ secrets.API_KEY }}" \ + --data-urlencode "commit=${{ github.sha }}" \ + --data-urlencode "branch=${{ github.ref }}" \ + --data-urlencode "version=$version" \ + --data-urlencode "date=$(date -u +%Y-%m-%dT%H:%M:%SZ)" \ + --data-urlencode "link=$DOWNLOAD_URL" \ + --data-urlencode "release=false" \ + "https://service.fpsmaster.top/api/github/push" diff --git a/.github/workflows/gradle.yml b/.github/workflows/publish.yml similarity index 97% rename from .github/workflows/gradle.yml rename to .github/workflows/publish.yml index de335329..08f496ad 100644 --- a/.github/workflows/gradle.yml +++ b/.github/workflows/publish.yml @@ -1,8 +1,9 @@ name: Java CI with Gradle on: - push: - branches: [ "master", "v4" ] +# push: +# branches: [ "master", "v4" ] + workflow_dispatch: jobs: build: diff --git a/shared/java/top/fpsmaster/FPSMaster.java b/shared/java/top/fpsmaster/FPSMaster.java index ff712326..21d69ce2 100644 --- a/shared/java/top/fpsmaster/FPSMaster.java +++ b/shared/java/top/fpsmaster/FPSMaster.java @@ -36,7 +36,7 @@ public class FPSMaster { public boolean loggedIn; public WsClient wsClient; - public static final String phase = "alpha"; + public static final String phase = "beta"; public static final String SERVICE_API = "https://service.fpsmaster.top"; public static final String EDITION = Constants.EDITION; @@ -76,11 +76,12 @@ private static void checkDevelopment() { public static String getClientTitle() { checkDevelopment(); - return CLIENT_NAME + " " + CLIENT_VERSION + " - " + phase + " " + Constants.VERSION + " (" + GitInfo.getBranch() + " - " + GitInfo.getCommitIdAbbrev() + ")" + (development ? " - Developer Mode" : ""); + return CLIENT_NAME + " Client (" + phase + ") "+Constants.VERSION + " (" + GitInfo.getBranch() +" - "+ GitInfo.getCommitIdAbbrev() + ")" + (development ? " - dev" : ""); } private void initializeFonts() { ClientLogger.info("Initializing Fonts..."); + // add more fonts and add fallback font File file = new File(FileUtils.fonts, "harmony_bold.ttf"); if (!file.exists()) { ClientLogger.info("Downloading Fonts..."); @@ -162,15 +163,17 @@ private void checkUpdate() { AsyncTask asyncTask = new AsyncTask(100); asyncTask.runnable(() -> { String s = UpdateChecker.getLatestVersion(); - if (s == null) { + if (s == null || s.isEmpty()) { isLatest = false; updateFailed = true; + ClientLogger.error("获取最新版本信息失败"); return; } - if (!s.isEmpty()) { - latest = s; - isLatest = CLIENT_VERSION.equals(s); - } + s = s.trim(); +// ClientLogger.info("最新版本: " + s); +// ClientLogger.info("当前版本: " + GitInfo.getCommitId()); + latest = s; + isLatest = GitInfo.getCommitId().equals(s); }); } @@ -184,22 +187,13 @@ public void initialize() { initializeConfigures(); initializeCommands(); initializePlugins(); - - if (phase == "release") { - checkUpdate(); - } - if (phase == "alpha") { - autoUpdate(); - } + checkUpdate(); checkOptifine(); } catch (Exception e) { ExceptionHandler.handle(e); } } - public void autoUpdate() { - File mods = FMLCommonHandler.instance().getMinecraftServerInstance().getFile("mods"); - } public void shutdown() { try { diff --git a/shared/java/top/fpsmaster/modules/account/AccountManager.java b/shared/java/top/fpsmaster/modules/account/AccountManager.java index b136daf5..c22c34ed 100644 --- a/shared/java/top/fpsmaster/modules/account/AccountManager.java +++ b/shared/java/top/fpsmaster/modules/account/AccountManager.java @@ -56,7 +56,6 @@ private boolean attemptLogin(String username, String token) throws NetworkExcept try { HashMap headers = new HashMap<>(); headers.put("Authorization","Bearer " + token); - System.out.println("Bearer " + token); String s = HttpRequest.get(FPSMaster.SERVICE_API + "/api/auth/validate-jwt", headers); JsonObject json = parser.parse(s).getAsJsonObject(); this.username = username; diff --git a/shared/java/top/fpsmaster/ui/screens/mainmenu/MainMenu.java b/shared/java/top/fpsmaster/ui/screens/mainmenu/MainMenu.java index 6636644a..12a00635 100644 --- a/shared/java/top/fpsmaster/ui/screens/mainmenu/MainMenu.java +++ b/shared/java/top/fpsmaster/ui/screens/mainmenu/MainMenu.java @@ -105,7 +105,7 @@ public void render(int mouseX, int mouseY, float partialTicks) { if (FPSMaster.isLatest) { info = TextFormattingProvider.getGreen() + FPSMaster.i18n.get("mainmenu.latest"); } else { - info = TextFormattingProvider.getRed().toString() + TextFormattingProvider.getBold().toString() + String.format(FPSMaster.i18n.get("mainmenu.notlatest"), FPSMaster.latest); + info = TextFormattingProvider.getRed().toString() + TextFormattingProvider.getBold().toString() + FPSMaster.i18n.get("mainmenu.notlatest"); needUpdate = true; } } @@ -137,7 +137,7 @@ public void onClick(int mouseX, int mouseY, int mouseButton) { if (Render2DUtils.isHovered(4f, guiHeight - 40, uw, 14f, mouseX, mouseY) && needUpdate) { try { - Desktop.getDesktop().browse(new URI("https://fpsmaster.top/download")); + Desktop.getDesktop().browse(new URI("https://fpsmaster.top")); } catch (Exception e) { e.printStackTrace(); } diff --git a/shared/java/top/fpsmaster/utils/thirdparty/github/UpdateChecker.java b/shared/java/top/fpsmaster/utils/thirdparty/github/UpdateChecker.java index 56c55d3c..84f9c176 100644 --- a/shared/java/top/fpsmaster/utils/thirdparty/github/UpdateChecker.java +++ b/shared/java/top/fpsmaster/utils/thirdparty/github/UpdateChecker.java @@ -2,14 +2,13 @@ import com.google.gson.JsonObject; import com.google.gson.JsonParser; +import top.fpsmaster.utils.GitInfo; import top.fpsmaster.utils.os.HttpRequest; import java.io.IOException; public class UpdateChecker { public static String getLatestVersion() { - String json = HttpRequest.get("https://api.github.com/repos/FPSMasterTeam/FPSMaster/releases/latest"); - JsonObject jsonObject = new JsonParser().parse(json).getAsJsonObject(); - return jsonObject.get("tag_name").getAsString(); + return HttpRequest.get("https://service.fpsmaster.top/api/github/latest/commit?branch=refs/heads/"+ GitInfo.getBranch()); } } \ No newline at end of file diff --git a/shared/resources/assets/minecraft/client/lang/zh_cn.lang b/shared/resources/assets/minecraft/client/lang/zh_cn.lang index 8fc591a9..2484ef62 100644 --- a/shared/resources/assets/minecraft/client/lang/zh_cn.lang +++ b/shared/resources/assets/minecraft/client/lang/zh_cn.lang @@ -7,7 +7,7 @@ mainmenu.notlogin=您未登录,点此登录 mainmenu.welcome=欢迎您,%s mainmenu.latest=您使用的是最新版本! mainmenu.failed=获取更新失败! -mainmenu.notlatest=检测到新版本!最新版本:%s,点此更新 +mainmenu.notlatest=您使用的不是最新版本,点此更新! music.title=音乐 music.search=搜索 diff --git a/v1.8.9/gradle.properties b/v1.8.9/gradle.properties index fda508d4..7fff2582 100644 --- a/v1.8.9/gradle.properties +++ b/v1.8.9/gradle.properties @@ -3,4 +3,4 @@ org.gradle.jvmargs=-Xmx2g --add-opens java.base/java.io=ALL-UNNAMED baseGroup = top.fpsmaster mcVersion = 1.8.9 modid = fpsmaster -version = v4-alpha +version = v4-beta From 3d92de13b463f8ded692aa528927b8d3717cc029 Mon Sep 17 00:00:00 2001 From: SuperSkidder Date: Sun, 13 Jul 2025 22:50:34 +0800 Subject: [PATCH 075/193] remove a useless test file --- .../top/fpsmaster/modules/lua/ParserTest.java | 47 ------------------- 1 file changed, 47 deletions(-) delete mode 100644 shared/test/java/top/fpsmaster/modules/lua/ParserTest.java diff --git a/shared/test/java/top/fpsmaster/modules/lua/ParserTest.java b/shared/test/java/top/fpsmaster/modules/lua/ParserTest.java deleted file mode 100644 index b1d4b8e9..00000000 --- a/shared/test/java/top/fpsmaster/modules/lua/ParserTest.java +++ /dev/null @@ -1,47 +0,0 @@ -//package top.fpsmaster.modules.lua; -// -//import top.fpsmaster.modules.lua.parser.LuaParser; -//import top.fpsmaster.modules.lua.parser.ParseError; -//import top.fpsmaster.modules.lua.parser.Statement; -// -//import java.util.List; -// -//public class ParserTest { -// public static void main(String[] args) { -// String code = "local longStr = [[\n" + -// "This is a long string\n" + -// "that spans multiple lines.\n" + -// "]]\n" + -// "\n" + -// "-- 18. 注释\n" + -// "-- 单行注释\n" + -// "--[[\n" + -// "多行注释\n" + -// "]]\n" + -// "--[[2333]]\n" + -// "--[[dhausd\n" + -// "asldjkhlasd\n" + -// "adasd]]\n" + -// "--[[\n" + -// "dsada\n" + -// "asdasd\n" + -// "asd\n" + -// "adsad]]\n" + -// "local longStr = [[\n" + -// "This is a long string\n" + -// "that spans multiple lines.]]\n" + -// "local longStr = [[This is a long string\n" + -// "that spans multiple lines.\n" + -// "]]"; -// -// List parse = null; -// try { -// parse = LuaParser.parse(code); -// } catch (ParseError e) { -// throw new RuntimeException(e); -// } -// for (Statement stmt : parse) { -// System.out.println(stmt.toString()); -// } -// } -//} From df74a9a663be2127a7fb065158d6787d1ab55766 Mon Sep 17 00:00:00 2001 From: SuperSkidder Date: Mon, 14 Jul 2025 00:53:43 +0800 Subject: [PATCH 076/193] feat: IRC update, player information sync, and more fix: SkinChanger may cause stuck --- shared/java/top/fpsmaster/FPSMaster.java | 16 ++++++--- .../fpsmaster/features/GlobalSubmitter.java | 36 +++++++++++++++---- .../features/command/impl/IRCChat.java | 14 ++++++++ .../fpsmaster/features/impl/utility/IRC.java | 22 ------------ .../features/impl/utility/SkinChanger.java | 5 ++- .../modules/account/AccountManager.java | 14 ++------ .../fpsmaster/modules/client/ClientUser.java | 22 ++++++++++++ .../modules/client/ClientUsersManager.java | 18 ++++++++++ .../top/fpsmaster/ui/mc/GuiMultiplayer.java | 5 ++- shared/java/top/fpsmaster/utils/Utility.java | 23 ++++++++++-- .../fpsmaster/websocket/client/WsClient.java | 34 +++++++++--------- .../websocket/data/message/PacketType.java | 13 +++---- .../message/client/CosmeticInfoPacket.java | 15 -------- .../data/message/client/FetchInfoPacket.java | 20 ----------- .../message/client/FetchPlayerPacket.java | 15 ++++++++ .../data/message/client/PlayerInfoPacket.java | 12 ++++++- .../data/message/client/ServerInfoPacket.java | 16 --------- .../data/message/server/SDataPacket.java | 19 ---------- .../message/server/SFetchPlayerPacket.java | 27 ++++++++++++++ 19 files changed, 199 insertions(+), 147 deletions(-) create mode 100644 shared/java/top/fpsmaster/modules/client/ClientUser.java create mode 100644 shared/java/top/fpsmaster/modules/client/ClientUsersManager.java delete mode 100644 shared/java/top/fpsmaster/websocket/data/message/client/CosmeticInfoPacket.java delete mode 100644 shared/java/top/fpsmaster/websocket/data/message/client/FetchInfoPacket.java create mode 100644 shared/java/top/fpsmaster/websocket/data/message/client/FetchPlayerPacket.java delete mode 100644 shared/java/top/fpsmaster/websocket/data/message/client/ServerInfoPacket.java delete mode 100644 shared/java/top/fpsmaster/websocket/data/message/server/SDataPacket.java create mode 100644 shared/java/top/fpsmaster/websocket/data/message/server/SFetchPlayerPacket.java diff --git a/shared/java/top/fpsmaster/FPSMaster.java b/shared/java/top/fpsmaster/FPSMaster.java index 21d69ce2..8e02d68f 100644 --- a/shared/java/top/fpsmaster/FPSMaster.java +++ b/shared/java/top/fpsmaster/FPSMaster.java @@ -9,6 +9,7 @@ import top.fpsmaster.font.FontManager; import top.fpsmaster.modules.account.AccountManager; import top.fpsmaster.modules.client.AsyncTask; +import top.fpsmaster.modules.client.ClientUsersManager; import top.fpsmaster.modules.config.ConfigManager; import top.fpsmaster.modules.logger.ClientLogger; import top.fpsmaster.modules.lua.LuaManager; @@ -55,6 +56,7 @@ public class FPSMaster { public static ConfigManager configManager = new ConfigManager(); public static OOBEScreen oobeScreen = new OOBEScreen(); public static AccountManager accountManager = new AccountManager(); + public static ClientUsersManager clientUsersManager = new ClientUsersManager(); public static GlobalSubmitter submitter = new GlobalSubmitter(); public static CommandManager commandManager = new CommandManager(); public static ComponentsManager componentsManager = new ComponentsManager(); @@ -76,7 +78,7 @@ private static void checkDevelopment() { public static String getClientTitle() { checkDevelopment(); - return CLIENT_NAME + " Client (" + phase + ") "+Constants.VERSION + " (" + GitInfo.getBranch() +" - "+ GitInfo.getCommitIdAbbrev() + ")" + (development ? " - dev" : ""); + return CLIENT_NAME + " Client (" + phase + ") " + Constants.VERSION + " (" + GitInfo.getBranch() + " - " + GitInfo.getCommitIdAbbrev() + ")" + (development ? " - dev" : ""); } private void initializeFonts() { @@ -164,10 +166,13 @@ private void checkUpdate() { asyncTask.runnable(() -> { String s = UpdateChecker.getLatestVersion(); if (s == null || s.isEmpty()) { - isLatest = false; - updateFailed = true; - ClientLogger.error("获取最新版本信息失败"); - return; + s = UpdateChecker.getLatestVersion(); + if (s == null || s.isEmpty()) { + isLatest = false; + updateFailed = true; + ClientLogger.error("获取最新版本信息失败"); + return; + } } s = s.trim(); // ClientLogger.info("最新版本: " + s); @@ -197,6 +202,7 @@ public void initialize() { public void shutdown() { try { + ClientLogger.info("Saving configs"); configManager.saveConfig("default"); } catch (FileException e) { throw new RuntimeException(e); diff --git a/shared/java/top/fpsmaster/features/GlobalSubmitter.java b/shared/java/top/fpsmaster/features/GlobalSubmitter.java index 7b4b8cac..0ec3a481 100644 --- a/shared/java/top/fpsmaster/features/GlobalSubmitter.java +++ b/shared/java/top/fpsmaster/features/GlobalSubmitter.java @@ -8,12 +8,17 @@ import top.fpsmaster.event.Subscribe; import top.fpsmaster.event.events.*; import top.fpsmaster.features.impl.interfaces.ClientSettings; +import top.fpsmaster.interfaces.ProviderManager; import top.fpsmaster.modules.music.MusicPlayer; import top.fpsmaster.ui.notification.NotificationManager; +import top.fpsmaster.utils.Utility; import top.fpsmaster.utils.math.MathTimer; import top.fpsmaster.utils.render.StencilUtil; import top.fpsmaster.utils.render.shader.KawaseBlur; import top.fpsmaster.utils.render.shader.RoundedUtil; +import top.fpsmaster.websocket.client.WsClient; + +import java.net.URISyntaxException; public class GlobalSubmitter { @@ -38,12 +43,31 @@ public void onChatSend(EventSendChatMessage e) { } @Subscribe - public void onTick(EventTick e) { - if (musicSwitchTimer.delay(1000)) { - if (MusicPlayer.isPlaying && MusicPlayer.getPlayProgress() > 0.999) { - MusicPlayer.curPlayProgress = 0f; - MusicPlayer.playList.next(); - } + public void onTick(EventTick e) throws URISyntaxException { + if (musicSwitchTimer.delay(500)) { + FPSMaster.async.runnable(() -> { + if (MusicPlayer.isPlaying && MusicPlayer.getPlayProgress() > 0.999) { + MusicPlayer.curPlayProgress = 0f; + MusicPlayer.playList.next(); + } + if (ProviderManager.mcProvider.getWorld() != null){ + Utility.flush(); + } + if (FPSMaster.INSTANCE.loggedIn) { + if (FPSMaster.INSTANCE.wsClient == null) { + try { + FPSMaster.INSTANCE.wsClient = WsClient.start("wss://service.fpsmaster.top/"); + } catch (URISyntaxException ex) { + throw new RuntimeException(ex); + } + Utility.sendClientDebug("尝试连接"); + } else if (FPSMaster.INSTANCE.wsClient.isClosed() && !FPSMaster.INSTANCE.wsClient.isOpen()) { + FPSMaster.INSTANCE.wsClient.close(); + FPSMaster.INSTANCE.wsClient.connect(); + Utility.sendClientDebug("尝试重连"); + } + } + }); } } diff --git a/shared/java/top/fpsmaster/features/command/impl/IRCChat.java b/shared/java/top/fpsmaster/features/command/impl/IRCChat.java index 01badf5d..f06bb23f 100644 --- a/shared/java/top/fpsmaster/features/command/impl/IRCChat.java +++ b/shared/java/top/fpsmaster/features/command/impl/IRCChat.java @@ -2,8 +2,14 @@ import top.fpsmaster.FPSMaster; import top.fpsmaster.features.command.Command; +import top.fpsmaster.features.impl.utility.IRC; +import top.fpsmaster.features.impl.utility.SkinChanger; +import top.fpsmaster.interfaces.ProviderManager; +import top.fpsmaster.modules.account.AccountManager; import top.fpsmaster.utils.Utility; +import static top.fpsmaster.utils.Utility.mc; + public class IRCChat extends Command { public IRCChat() { @@ -12,6 +18,10 @@ public IRCChat() { @Override public void execute(String[] args) { + if (!IRC.using) { + Utility.sendClientNotify("IRC is not using"); + return; + } if (args.length > 0) { StringBuilder sb = new StringBuilder(); @@ -35,6 +45,10 @@ public void execute(String[] args) { } String message = sb.toString(); FPSMaster.INSTANCE.wsClient.sendDM(args[1], message); + } else if ("update".equals(args[0])) { + FPSMaster.INSTANCE.wsClient.sendInformation(AccountManager.skin, "", ProviderManager.mcProvider.getPlayer().getName(), ProviderManager.mcProvider.getServerAddress()); + } else if ("fetch".equals(args[0])) { + FPSMaster.INSTANCE.wsClient.fetchPlayer(ProviderManager.mcProvider.getPlayer().getGameProfile().getId().toString(), ProviderManager.mcProvider.getPlayer().getName()); } else { for (String arg : args) { if (arg.equals(args[args.length - 1])) { diff --git a/shared/java/top/fpsmaster/features/impl/utility/IRC.java b/shared/java/top/fpsmaster/features/impl/utility/IRC.java index caa19c31..8c4a1c83 100644 --- a/shared/java/top/fpsmaster/features/impl/utility/IRC.java +++ b/shared/java/top/fpsmaster/features/impl/utility/IRC.java @@ -18,7 +18,6 @@ public class IRC extends Module { public static boolean using = false; public static final BooleanSetting showMates = new BooleanSetting("showMates", true); - private final MathTimer timer = new MathTimer(); public IRC() { super("IRC", Category.Utility); @@ -31,30 +30,9 @@ public void onEnable() { using = true; } - @Subscribe - public void onTick(EventTick e) throws URISyntaxException { - if (!timer.delay(5000)) { - return; - } - if (ProviderManager.mcProvider.getWorld() == null) { - return; - } - if (FPSMaster.INSTANCE.wsClient == null) { - FPSMaster.INSTANCE.wsClient = WsClient.start("wss://service.fpsmaster.top/"); - Utility.sendClientDebug("尝试连接"); - } else if (FPSMaster.INSTANCE.wsClient != null && FPSMaster.INSTANCE.wsClient.isClosed() && !FPSMaster.INSTANCE.wsClient.isOpen()) { - FPSMaster.INSTANCE.wsClient.close(); - FPSMaster.INSTANCE.wsClient.connect(); - Utility.sendClientDebug("尝试连接"); - } - } - @Override public void onDisable() { super.onDisable(); - if (FPSMaster.INSTANCE.wsClient != null && FPSMaster.INSTANCE.wsClient.isOpen()) { - FPSMaster.INSTANCE.wsClient.close(); - } using = false; } } diff --git a/shared/java/top/fpsmaster/features/impl/utility/SkinChanger.java b/shared/java/top/fpsmaster/features/impl/utility/SkinChanger.java index 870bb1d5..26bc110a 100644 --- a/shared/java/top/fpsmaster/features/impl/utility/SkinChanger.java +++ b/shared/java/top/fpsmaster/features/impl/utility/SkinChanger.java @@ -45,9 +45,12 @@ public void onEnable() { @Subscribe public void onTick(EventTick e) { if (ProviderManager.mcProvider.getPlayer() != null && ProviderManager.mcProvider.getPlayer().ticksExisted % 30 == 0) { + if (AccountManager.skin.equals(skinName.getValue())) + return; FPSMaster.async.runnable(this::update); + AccountManager.skin = skinName.getValue(); + } - AccountManager.skin = skinName.getValue(); } public void update() { diff --git a/shared/java/top/fpsmaster/modules/account/AccountManager.java b/shared/java/top/fpsmaster/modules/account/AccountManager.java index c22c34ed..be55ba8f 100644 --- a/shared/java/top/fpsmaster/modules/account/AccountManager.java +++ b/shared/java/top/fpsmaster/modules/account/AccountManager.java @@ -16,7 +16,8 @@ public class AccountManager { private String token = ""; private String username = ""; - private String[] itemsHeld = new String[0]; + public static JsonParser parser = new JsonParser(); + public static String skin = ""; public void autoLogin() { FPSMaster.async.runnable(() -> { @@ -66,9 +67,6 @@ private boolean attemptLogin(String username, String token) throws NetworkExcept } } - public static JsonParser parser = new JsonParser(); - public static String cape = ""; - public static String skin = ""; public static JsonObject login(String username, String password) throws NetworkException { try { @@ -106,12 +104,4 @@ public String getUsername() { public void setUsername(String username) { this.username = username; } - - public String[] getItemsHeld() { - return itemsHeld; - } - - public void setItemsHeld(String[] itemsHeld) { - this.itemsHeld = itemsHeld; - } } diff --git a/shared/java/top/fpsmaster/modules/client/ClientUser.java b/shared/java/top/fpsmaster/modules/client/ClientUser.java new file mode 100644 index 00000000..0845666a --- /dev/null +++ b/shared/java/top/fpsmaster/modules/client/ClientUser.java @@ -0,0 +1,22 @@ +package top.fpsmaster.modules.client; + +public class ClientUser { + public String uid; + public String name; + public String uuid; + public String gameId; + public String cosmetics; + public String skin; + public String rank; + public String customRank; + public ClientUser(String uid, String name, String uuid, String gameId, String cosmetics, String skin, String rank, String customRank) { + this.uid = uid; + this.name = name; + this.uuid = uuid; + this.gameId = gameId; + this.cosmetics = cosmetics; + this.skin = skin; + this.rank = rank; + this.customRank = customRank; + } +} diff --git a/shared/java/top/fpsmaster/modules/client/ClientUsersManager.java b/shared/java/top/fpsmaster/modules/client/ClientUsersManager.java new file mode 100644 index 00000000..36705061 --- /dev/null +++ b/shared/java/top/fpsmaster/modules/client/ClientUsersManager.java @@ -0,0 +1,18 @@ +package top.fpsmaster.modules.client; + +import top.fpsmaster.websocket.data.message.server.SFetchPlayerPacket; + +import java.util.ArrayList; + +public class ClientUsersManager { + public ArrayList users = new ArrayList<>(); + + public void addFromFetch(SFetchPlayerPacket packet) { + ClientUser clientUser = new ClientUser(packet.uid, packet.name, packet.uuid, packet.gameId, packet.cosmetics, packet.skin, packet.rank, packet.customRank); + for (ClientUser user : users) { + if (user.uid.equals(clientUser.uid)) + return; + } + users.add(clientUser); + } +} diff --git a/shared/java/top/fpsmaster/ui/mc/GuiMultiplayer.java b/shared/java/top/fpsmaster/ui/mc/GuiMultiplayer.java index 9ba3c326..fd54e717 100644 --- a/shared/java/top/fpsmaster/ui/mc/GuiMultiplayer.java +++ b/shared/java/top/fpsmaster/ui/mc/GuiMultiplayer.java @@ -103,14 +103,13 @@ public void initGui() { } serverListDisplay.clear(); serverListDisplay.addAll(serverListInternet); - if (serverListRecommended.size() == 0) { + if (serverListRecommended.isEmpty()) { AsyncTask asyncTask = new AsyncTask(100); asyncTask.runnable(() -> { String s = HttpRequest.get("https://service.fpsmaster.top/api/client/servers"); - System.out.println(s); JsonObject jsonObject = gson.fromJson(s, JsonObject.class); jsonObject.get("data").getAsJsonArray().forEach(e -> { - this.serverListRecommended.add(new ServerListEntry(this, new ServerData(e.getAsJsonObject().get("name").getAsString() + " - " + e.getAsJsonObject().get("description").getAsString(), e.getAsJsonObject().get("address").getAsString(), false))); + serverListRecommended.add(new ServerListEntry(this, new ServerData(e.getAsJsonObject().get("name").getAsString() + " - " + e.getAsJsonObject().get("description").getAsString(), e.getAsJsonObject().get("address").getAsString(), false))); }); }); } diff --git a/shared/java/top/fpsmaster/utils/Utility.java b/shared/java/top/fpsmaster/utils/Utility.java index f6b7cec4..ce4dd7f3 100644 --- a/shared/java/top/fpsmaster/utils/Utility.java +++ b/shared/java/top/fpsmaster/utils/Utility.java @@ -4,27 +4,46 @@ import top.fpsmaster.interfaces.ProviderManager; import top.fpsmaster.modules.dev.DevMode; +import java.util.ArrayList; + public class Utility { public static Minecraft mc = Minecraft.getMinecraft(); + static ArrayList messages = new ArrayList<>(); + public static void sendClientMessage(String msg) { if (ProviderManager.mcProvider.getWorld() != null) { ProviderManager.mcProvider.printChatMessage(ProviderManager.utilityProvider.makeChatComponent(msg)); + } else { + messages.add(msg); } } public static void sendClientNotify(String msg) { + String msg1 = "§9[FPSMaster]§r " + msg; if (ProviderManager.mcProvider.getWorld() != null) { - ProviderManager.mcProvider.printChatMessage(ProviderManager.utilityProvider.makeChatComponent("§9[FPSMaster]§r " + msg)); + ProviderManager.mcProvider.printChatMessage(ProviderManager.utilityProvider.makeChatComponent(msg1)); + } else { + messages.add(msg1); } } public static void sendClientDebug(String msg) { if (DevMode.INSTACE.dev) { + String msg1 = "§9[FPSMaster]§r " + msg; if (ProviderManager.mcProvider.getWorld() != null) { - ProviderManager.mcProvider.printChatMessage(ProviderManager.utilityProvider.makeChatComponent("§9[FPSMaster]§r " + msg)); + ProviderManager.mcProvider.printChatMessage(ProviderManager.utilityProvider.makeChatComponent(msg1)); + } else { + messages.add(msg1); } } } + + public static void flush() { + for (String message : messages) { + ProviderManager.mcProvider.printChatMessage(ProviderManager.utilityProvider.makeChatComponent(message)); + } + messages.clear(); + } } diff --git a/shared/java/top/fpsmaster/websocket/client/WsClient.java b/shared/java/top/fpsmaster/websocket/client/WsClient.java index 42616d3d..03993ad8 100644 --- a/shared/java/top/fpsmaster/websocket/client/WsClient.java +++ b/shared/java/top/fpsmaster/websocket/client/WsClient.java @@ -6,12 +6,13 @@ import org.java_websocket.handshake.ServerHandshake; import top.fpsmaster.FPSMaster; import top.fpsmaster.features.impl.interfaces.ClientSettings; +import top.fpsmaster.features.impl.utility.IRC; import top.fpsmaster.interfaces.ProviderManager; -import top.fpsmaster.modules.dev.DevMode; +import top.fpsmaster.modules.client.ClientUsersManager; import top.fpsmaster.utils.Utility; import top.fpsmaster.websocket.data.message.Packet; import top.fpsmaster.websocket.data.message.client.*; -import top.fpsmaster.websocket.data.message.server.SDataPacket; +import top.fpsmaster.websocket.data.message.server.SFetchPlayerPacket; import top.fpsmaster.websocket.data.message.server.SMessagePacket; import java.net.URI; @@ -25,9 +26,9 @@ public WsClient(URI serverURI) { @Override public void onOpen(ServerHandshake handshakedata) { - Utility.sendClientDebug("成功连接到irc服务器"); + Utility.sendClientDebug("成功连接到irc服务器,开始验证登录信息"); if (ProviderManager.mcProvider.getPlayer() != null) { - Utility.sendClientMessage(FPSMaster.i18n.get("irc.enable").replace("%s",ClientSettings.prefix.getValue())); + Utility.sendClientMessage(FPSMaster.i18n.get("irc.enable").replace("%s", ClientSettings.prefix.getValue())); } assert FPSMaster.accountManager != null; send(new LoginPacket(FPSMaster.accountManager.getUsername(), FPSMaster.accountManager.getToken()).toJson()); @@ -37,12 +38,8 @@ public void sendMessage(String message) { send(new MessagePacket(MessagePacket.MessageType.CHAT, message).toJson()); } - public void sendInformation(String skin, String cape, String gameID, String serverAddress) { - if (ProviderManager.mcProvider.getPlayer() == null) - return; - send(new PlayerInfoPacket(gameID, ProviderManager.mcProvider.getPlayer().getUniqueID().toString()).toJson()); - send(new ServerInfoPacket(serverAddress).toJson()); - send(new CosmeticInfoPacket(skin, cape).toJson()); + public void sendInformation(String skin, String cosmetics, String gameID, String serverAddress) { + send(new PlayerInfoPacket(gameID, ProviderManager.mcProvider.getPlayer().getUniqueID().toString(), serverAddress, skin, cosmetics).toJson()); } @@ -60,13 +57,12 @@ public void onMessage(String message) { switch (packet.type) { case SERVER_MESSAGE: SMessagePacket parsePacket = (SMessagePacket) Packet.parsePacket(message, SMessagePacket.class); - Utility.sendClientMessage(parsePacket.msg); - break; - case SERVER_DATA: - SDataPacket packet1 = (SDataPacket) packet; - String data = packet1.data; - JsonObject asJsonObject = new JsonParser().parse(data).getAsJsonObject(); + if (IRC.using) + Utility.sendClientMessage(parsePacket.msg); break; + case SERVER_FETCH_PLAYER: + SFetchPlayerPacket parsePacket1 = (SFetchPlayerPacket) Packet.parsePacket(message, SFetchPlayerPacket.class); + FPSMaster.clientUsersManager.addFromFetch(parsePacket1); } } @@ -78,7 +74,7 @@ public void onClose(int code, String reason, boolean remote) { @Override public void onError(Exception ex) { - Utility.sendClientDebug("聊天服务错误: " + ex.getMessage()); + Utility.sendClientDebug("聊天服务错误 " + ex.getMessage()); } public static WsClient start(String addr) throws URISyntaxException { @@ -86,4 +82,8 @@ public static WsClient start(String addr) throws URISyntaxException { client.connect(); return client; } + + public void fetchPlayer(String uuid, String name) { + send(new FetchPlayerPacket(uuid, name).toJson()); + } } \ No newline at end of file diff --git a/shared/java/top/fpsmaster/websocket/data/message/PacketType.java b/shared/java/top/fpsmaster/websocket/data/message/PacketType.java index 095997c8..79c88cf1 100644 --- a/shared/java/top/fpsmaster/websocket/data/message/PacketType.java +++ b/shared/java/top/fpsmaster/websocket/data/message/PacketType.java @@ -3,21 +3,18 @@ import com.google.gson.annotations.SerializedName; public enum PacketType { - // CLIENT_SIDE @SerializedName("CLIENT_LOGIN") CLIENT_LOGIN, @SerializedName("CLIENT_MESSAGE") CLIENT_MESSAGE, @SerializedName("CLIENT_DIRECT_MSG") CLIENT_DIRECT_MSG, - @SerializedName("CLIENT_SERVER_INFO") - CLIENT_SERVER_INFO, @SerializedName("CLIENT_PLAYER_INFO") CLIENT_PLAYER_INFO, - @SerializedName("CLIENT_COSMETIC_INFO") - CLIENT_COSMETIC_INFO, - - CLIENT_FETCH, // SERVER_SIDE - SERVER_DATA, @SerializedName("SERVER_MESSAGE") + @SerializedName("CLIENT_FETCH_PLAYER") + CLIENT_FETCH_PLAYER, + @SerializedName("SERVER_FETCH_PLAYER") + SERVER_FETCH_PLAYER, + @SerializedName("SERVER_MESSAGE") SERVER_MESSAGE } diff --git a/shared/java/top/fpsmaster/websocket/data/message/client/CosmeticInfoPacket.java b/shared/java/top/fpsmaster/websocket/data/message/client/CosmeticInfoPacket.java deleted file mode 100644 index be0eebf5..00000000 --- a/shared/java/top/fpsmaster/websocket/data/message/client/CosmeticInfoPacket.java +++ /dev/null @@ -1,15 +0,0 @@ -package top.fpsmaster.websocket.data.message.client; - -import top.fpsmaster.websocket.data.message.Packet; -import top.fpsmaster.websocket.data.message.PacketType; - -public class CosmeticInfoPacket extends Packet { - public String skin; - public String cape; - - public CosmeticInfoPacket(String skin, String cape) { - super(PacketType.CLIENT_COSMETIC_INFO); - this.skin = skin; - this.cape = cape; - } -} diff --git a/shared/java/top/fpsmaster/websocket/data/message/client/FetchInfoPacket.java b/shared/java/top/fpsmaster/websocket/data/message/client/FetchInfoPacket.java deleted file mode 100644 index 6d543bfa..00000000 --- a/shared/java/top/fpsmaster/websocket/data/message/client/FetchInfoPacket.java +++ /dev/null @@ -1,20 +0,0 @@ -package top.fpsmaster.websocket.data.message.client; - -import com.google.gson.annotations.SerializedName; -import top.fpsmaster.websocket.data.message.Packet; -import top.fpsmaster.websocket.data.message.PacketType; - -public class FetchInfoPacket extends Packet { - @SerializedName("type") - public InfoType type; - @SerializedName("data") - public String data; - - public FetchInfoPacket(InfoType type, String data) { - super(PacketType.CLIENT_FETCH); - this.type = type; - } - public enum InfoType { - CLIENT_PLAYER_INFO - } -} diff --git a/shared/java/top/fpsmaster/websocket/data/message/client/FetchPlayerPacket.java b/shared/java/top/fpsmaster/websocket/data/message/client/FetchPlayerPacket.java new file mode 100644 index 00000000..dfda60b6 --- /dev/null +++ b/shared/java/top/fpsmaster/websocket/data/message/client/FetchPlayerPacket.java @@ -0,0 +1,15 @@ +package top.fpsmaster.websocket.data.message.client; + +import top.fpsmaster.websocket.data.message.Packet; +import top.fpsmaster.websocket.data.message.PacketType; + +public class FetchPlayerPacket extends Packet { + public String uuid; + public String gameId; + + public FetchPlayerPacket(String uuid, String gameId) { + super(PacketType.CLIENT_FETCH_PLAYER); + this.uuid = uuid; + this.gameId = gameId; + } +} diff --git a/shared/java/top/fpsmaster/websocket/data/message/client/PlayerInfoPacket.java b/shared/java/top/fpsmaster/websocket/data/message/client/PlayerInfoPacket.java index 6fb6f8b6..5f7086c1 100644 --- a/shared/java/top/fpsmaster/websocket/data/message/client/PlayerInfoPacket.java +++ b/shared/java/top/fpsmaster/websocket/data/message/client/PlayerInfoPacket.java @@ -9,9 +9,19 @@ public class PlayerInfoPacket extends Packet { public String playerName; @SerializedName("UUID") public String UUID; - public PlayerInfoPacket(String playerName, String UUID) { + @SerializedName("server") + public String server; + @SerializedName("skin") + public String skin; + @SerializedName("cosmetics") + public String cosmetics; + + public PlayerInfoPacket(String playerName, String UUID, String server, String skin, String cosmetics) { super(PacketType.CLIENT_PLAYER_INFO); this.playerName = playerName; this.UUID = UUID; + this.server = server; + this.skin = skin; + this.cosmetics = cosmetics; } } diff --git a/shared/java/top/fpsmaster/websocket/data/message/client/ServerInfoPacket.java b/shared/java/top/fpsmaster/websocket/data/message/client/ServerInfoPacket.java deleted file mode 100644 index f5e779b8..00000000 --- a/shared/java/top/fpsmaster/websocket/data/message/client/ServerInfoPacket.java +++ /dev/null @@ -1,16 +0,0 @@ -package top.fpsmaster.websocket.data.message.client; - -import com.google.gson.annotations.SerializedName; -import top.fpsmaster.websocket.data.message.Packet; -import top.fpsmaster.websocket.data.message.PacketType; - -public class ServerInfoPacket extends Packet { - - @SerializedName("serverIP") - public String serverIP; - - public ServerInfoPacket(String serverIP) { - super(PacketType.CLIENT_SERVER_INFO); - this.serverIP = serverIP; - } -} diff --git a/shared/java/top/fpsmaster/websocket/data/message/server/SDataPacket.java b/shared/java/top/fpsmaster/websocket/data/message/server/SDataPacket.java deleted file mode 100644 index 12271067..00000000 --- a/shared/java/top/fpsmaster/websocket/data/message/server/SDataPacket.java +++ /dev/null @@ -1,19 +0,0 @@ -package top.fpsmaster.websocket.data.message.server; - -import com.google.gson.annotations.SerializedName; -import top.fpsmaster.websocket.data.message.Packet; -import top.fpsmaster.websocket.data.message.PacketType; -import top.fpsmaster.websocket.data.message.client.FetchInfoPacket; - -public class SDataPacket extends Packet { - @SerializedName("type") - public FetchInfoPacket.InfoType type; - @SerializedName("data") - public String data; - - public SDataPacket(FetchInfoPacket.InfoType type, String data) { - super(PacketType.SERVER_DATA); - this.type = type; - this.data = data; - } -} diff --git a/shared/java/top/fpsmaster/websocket/data/message/server/SFetchPlayerPacket.java b/shared/java/top/fpsmaster/websocket/data/message/server/SFetchPlayerPacket.java new file mode 100644 index 00000000..9d359a0f --- /dev/null +++ b/shared/java/top/fpsmaster/websocket/data/message/server/SFetchPlayerPacket.java @@ -0,0 +1,27 @@ +package top.fpsmaster.websocket.data.message.server; + +import top.fpsmaster.websocket.data.message.Packet; +import top.fpsmaster.websocket.data.message.PacketType; + +public class SFetchPlayerPacket extends Packet { + public String uid; + public String name; + public String uuid; + public String gameId; + public String cosmetics; + public String skin; + public String rank; + public String customRank; + + public SFetchPlayerPacket(String uid, String name, String uuid, String gameId, String cosmetics, String skin, String rank, String customRank) { + super(PacketType.SERVER_FETCH_PLAYER); + this.uid = uid; + this.name = name; + this.uuid = uuid; + this.gameId = gameId; + this.cosmetics = cosmetics; + this.skin = skin; + this.rank = rank; + this.customRank = customRank; + } +} From da72d5e8fb8afc25adabb2346858664873d24d2c Mon Sep 17 00:00:00 2001 From: SuperSkidder Date: Mon, 14 Jul 2025 00:56:46 +0800 Subject: [PATCH 077/193] change: github action run time --- .github/workflows/nightly.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index 45527192..705dc0fe 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -2,7 +2,7 @@ name: Java CI with Gradle - Nightly on: schedule: - - cron: '0 2 * * *' + - cron: '0 17 * * *' workflow_dispatch: jobs: From ff1d31c451620a53c6525e4a27390ea8afc70064 Mon Sep 17 00:00:00 2001 From: SuperSkidder Date: Mon, 14 Jul 2025 01:43:33 +0800 Subject: [PATCH 078/193] fix: fix duplicated value in potion display --- .../top/fpsmaster/features/impl/interfaces/PotionDisplay.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/shared/java/top/fpsmaster/features/impl/interfaces/PotionDisplay.java b/shared/java/top/fpsmaster/features/impl/interfaces/PotionDisplay.java index 6da8f8b7..1bf31913 100644 --- a/shared/java/top/fpsmaster/features/impl/interfaces/PotionDisplay.java +++ b/shared/java/top/fpsmaster/features/impl/interfaces/PotionDisplay.java @@ -8,7 +8,7 @@ public class PotionDisplay extends InterfaceModule { public PotionDisplay() { super("PotionDisplay", Category.Interface); - addSettings(rounded, backgroundColor, fontShadow, betterFont, bg, rounded, roundRadius); + addSettings(backgroundColor, fontShadow, betterFont, bg, rounded, roundRadius); } @Override From fe6a53a0fb8ca80f41591b6635c66ec8f83630db Mon Sep 17 00:00:00 2001 From: SuperSkidder Date: Mon, 14 Jul 2025 14:25:44 +0800 Subject: [PATCH 079/193] feat: add onValueChange event fix: gui blur rendering issue when fast render is on some optimizations --- .../event/events/EventValueChange.java | 16 +++++++++ .../fpsmaster/features/GlobalSubmitter.java | 3 +- .../impl/interfaces/ClientSettings.java | 19 +++++++++++ .../features/impl/interfaces/ModsList.java | 33 ++++-------------- .../impl/optimizes/OldAnimations.java | 2 +- .../features/impl/utility/ChatBot.java | 14 ++++---- .../fpsmaster/features/settings/Setting.java | 11 ++++-- .../settings/impl/BooleanSetting.java | 2 +- .../features/settings/impl/ColorSetting.java | 4 +-- .../features/settings/impl/ModeSetting.java | 10 +++--- .../features/settings/impl/NumberSetting.java | 7 +--- .../modules/config/ConfigManager.java | 20 ++++++----- .../modules/music/IngameOverlay.java | 2 +- .../click/modules/impl/BindSettingRender.java | 6 ++-- .../top/fpsmaster/ui/custom/Component.java | 2 +- .../ui/custom/ComponentsManager.java | 4 +-- .../ui/custom/impl/ArmorDisplayComponent.java | 6 ++-- .../custom/impl/CoordsDisplayComponent.java | 4 +-- .../ui/custom/impl/ModsListComponent.java | 34 ++++++++++--------- .../fpsmaster/utils/render/Render2DUtils.java | 4 +-- .../utils/render/shader/GradientUtils.java | 2 +- .../assets/minecraft/client/lang/zh_cn.lang | 2 ++ ...unkRenderDispatcherMixin_LimitUpdates.java | 2 +- .../EntityFXMixin_StaticParticleColor.java | 2 +- .../forge/mixin/MixinFontRender.java | 4 +-- .../forge/mixin/MixinGuiContainer.java | 2 +- .../ModelRendererMixin_BatchDrawing.java | 8 ++--- .../mixin/TexturedQuadMixin_BatchDraw.java | 4 +-- .../mixin/WorldClientMixin_AnimationTick.java | 2 +- 29 files changed, 129 insertions(+), 102 deletions(-) create mode 100644 shared/java/top/fpsmaster/event/events/EventValueChange.java diff --git a/shared/java/top/fpsmaster/event/events/EventValueChange.java b/shared/java/top/fpsmaster/event/events/EventValueChange.java new file mode 100644 index 00000000..0e2ecce7 --- /dev/null +++ b/shared/java/top/fpsmaster/event/events/EventValueChange.java @@ -0,0 +1,16 @@ +package top.fpsmaster.event.events; + +import top.fpsmaster.event.CancelableEvent; +import top.fpsmaster.event.Event; +import top.fpsmaster.features.settings.Setting; + +public class EventValueChange extends CancelableEvent { + public Setting setting; + public Object oldValue; + public Object newValue; + public EventValueChange(Setting setting, Object oldValue, Object newValue) { + this.setting = setting; + this.oldValue = oldValue; + this.newValue = newValue; + } +} diff --git a/shared/java/top/fpsmaster/features/GlobalSubmitter.java b/shared/java/top/fpsmaster/features/GlobalSubmitter.java index 0ec3a481..eb2c1dd9 100644 --- a/shared/java/top/fpsmaster/features/GlobalSubmitter.java +++ b/shared/java/top/fpsmaster/features/GlobalSubmitter.java @@ -11,6 +11,7 @@ import top.fpsmaster.interfaces.ProviderManager; import top.fpsmaster.modules.music.MusicPlayer; import top.fpsmaster.ui.notification.NotificationManager; +import top.fpsmaster.utils.OptifineUtil; import top.fpsmaster.utils.Utility; import top.fpsmaster.utils.math.MathTimer; import top.fpsmaster.utils.render.StencilUtil; @@ -77,7 +78,7 @@ public void onRender(EventRender2D e) { float mouseX = (float) Mouse.getX() / scaledResolution.getScaleFactor(); float mouseY = scaledResolution.getScaledHeight() - (float) Mouse.getY() / scaledResolution.getScaleFactor(); - if (ClientSettings.blur.value) { + if (ClientSettings.blur.getValue()) { StencilUtil.initStencilToWrite(); EventDispatcher.dispatchEvent(new EventShader()); FPSMaster.componentsManager.draw((int) mouseX, (int) mouseY); diff --git a/shared/java/top/fpsmaster/features/impl/interfaces/ClientSettings.java b/shared/java/top/fpsmaster/features/impl/interfaces/ClientSettings.java index 0c10ce5f..af62d1da 100644 --- a/shared/java/top/fpsmaster/features/impl/interfaces/ClientSettings.java +++ b/shared/java/top/fpsmaster/features/impl/interfaces/ClientSettings.java @@ -1,11 +1,17 @@ package top.fpsmaster.features.impl.interfaces; import org.lwjgl.input.Keyboard; +import top.fpsmaster.FPSMaster; +import top.fpsmaster.event.EventDispatcher; +import top.fpsmaster.event.Subscribe; +import top.fpsmaster.event.events.EventValueChange; import top.fpsmaster.features.impl.InterfaceModule; import top.fpsmaster.features.manager.Category; import top.fpsmaster.features.settings.impl.BindSetting; import top.fpsmaster.features.settings.impl.BooleanSetting; import top.fpsmaster.features.settings.impl.TextSetting; +import top.fpsmaster.utils.OptifineUtil; +import top.fpsmaster.utils.Utility; public class ClientSettings extends InterfaceModule { public static BooleanSetting blur = new BooleanSetting("blur", false); @@ -16,6 +22,7 @@ public class ClientSettings extends InterfaceModule { public ClientSettings() { super("ClientSettings", Category.Utility); addSettings(prefix, keyBind, fixedScale, blur); + EventDispatcher.registerListener(this); } @Override @@ -23,4 +30,16 @@ public void onEnable() { super.onEnable(); this.set(false); } + + @Subscribe + public void onValueChange(EventValueChange e){ + if (e.setting == blur && ((boolean) e.newValue)){ + if (OptifineUtil.isFastRender()) { + Utility.sendClientNotify(FPSMaster.i18n.get("blur.fast_render")); + e.cancel(); + } else { + Utility.sendClientNotify(FPSMaster.i18n.get("blur.performance")); + } + } + } } diff --git a/shared/java/top/fpsmaster/features/impl/interfaces/ModsList.java b/shared/java/top/fpsmaster/features/impl/interfaces/ModsList.java index fbd6c2b0..0b3aa785 100644 --- a/shared/java/top/fpsmaster/features/impl/interfaces/ModsList.java +++ b/shared/java/top/fpsmaster/features/impl/interfaces/ModsList.java @@ -4,39 +4,20 @@ import top.fpsmaster.features.manager.Category; import top.fpsmaster.features.settings.impl.BooleanSetting; import top.fpsmaster.features.settings.impl.ColorSetting; +import top.fpsmaster.features.settings.impl.TextSetting; import java.awt.Color; public class ModsList extends InterfaceModule { - private BooleanSetting showLogo; - private BooleanSetting english; - private BooleanSetting rainbow; - private ColorSetting color; + public BooleanSetting showLogo = new BooleanSetting("ShowText", true); + public BooleanSetting english = new BooleanSetting("English", true); + public BooleanSetting rainbow = new BooleanSetting("Rainbow", true); + public ColorSetting color = new ColorSetting("Color", new Color(255, 255, 255), () -> !rainbow.getValue()); + public TextSetting text = new TextSetting("Text", "FPSMaster", () -> showLogo.getValue()); public ModsList() { super("ModsList", Category.Interface); - showLogo = new BooleanSetting("ShowLogo", true); - english = new BooleanSetting("English", true); - rainbow = new BooleanSetting("Rainbow", true); - color = new ColorSetting("Color", new Color(255, 255, 255), () -> !rainbow.value); - - addSettings(showLogo, english, color, rainbow, betterFont, backgroundColor, bg); - } - - public BooleanSetting getShowLogo() { - return showLogo; - } - - public BooleanSetting getEnglish() { - return english; - } - - public BooleanSetting getRainbow() { - return rainbow; - } - - public ColorSetting getColor() { - return color; + addSettings(showLogo, text, english, color, rainbow, betterFont, backgroundColor, bg); } } diff --git a/shared/java/top/fpsmaster/features/impl/optimizes/OldAnimations.java b/shared/java/top/fpsmaster/features/impl/optimizes/OldAnimations.java index c203b7cc..4c43dbbb 100644 --- a/shared/java/top/fpsmaster/features/impl/optimizes/OldAnimations.java +++ b/shared/java/top/fpsmaster/features/impl/optimizes/OldAnimations.java @@ -76,7 +76,7 @@ public void onTick(EventTick event) { delta *= 0.4f; eyeHeight = START_HEIGHT - delta; } - if (Minecraft.getMinecraft().gameSettings.keyBindAttack.isKeyDown() && thePlayer.isUsingItem() && blockSwing.value) { + if (Minecraft.getMinecraft().gameSettings.keyBindAttack.isKeyDown() && thePlayer.isUsingItem() && blockSwing.getValue()) { swingItem(); } } diff --git a/shared/java/top/fpsmaster/features/impl/utility/ChatBot.java b/shared/java/top/fpsmaster/features/impl/utility/ChatBot.java index 58ae5e4f..1c02fbd7 100644 --- a/shared/java/top/fpsmaster/features/impl/utility/ChatBot.java +++ b/shared/java/top/fpsmaster/features/impl/utility/ChatBot.java @@ -49,7 +49,7 @@ public ChatBot() { @Subscribe public void onSend(EventSendChatMessage e) { - if (ignoreSelf.value) { + if (ignoreSelf.getValue()) { String s = e.msg; lastMsg = s.length() > 20 ? s.substring(0, 20) : s; } @@ -57,14 +57,14 @@ public void onSend(EventSendChatMessage e) { @Subscribe public void onChat(EventPacket e) { - if (ProviderManager.packetChat.isPacket(e.packet) && timer.delay(cooldown.value.longValue())) { + if (ProviderManager.packetChat.isPacket(e.packet) && timer.delay(cooldown.getValue().longValue())) { String formattedText = ProviderManager.packetChat.getUnformattedText(e.packet); if (formattedText.contains(lastMsg) && lastMsg.length() > 1) { System.out.println(lastMsg); return; } FPSMaster.async.runnable(() -> { - Pattern pattern = Pattern.compile(regex.value); + Pattern pattern = Pattern.compile(regex.getValue()); if (pattern.matcher(formattedText).find()) { OpenAI openAi; NotificationManager.addNotification("ChatGPT", formattedText, 1f); @@ -74,14 +74,14 @@ public void onChat(EventPacket e) { userRole.addProperty("content", formattedText); msgs.add(userRole); if (mode.isMode("Custom")) { - openAi = new OpenAI(apiUrl.value, apiKey.value, model.value, prompt.value); + openAi = new OpenAI(apiUrl.getValue(), apiKey.getValue(), model.getValue(), prompt.getValue()); JsonArray msgs1 = new JsonArray(); msgs.forEach(msgs1::add); s = openAi.requestNewAnswer(formattedText, msgs1).replace("\n", "").trim(); } else { JsonArray msgs1 = new JsonArray(); msgs.forEach(msgs1::add); - String[] requestClientAI = OpenAI.requestClientAI(prompt.value, model.value, msgs1); + String[] requestClientAI = OpenAI.requestClientAI(prompt.getValue(), model.getValue(), msgs1); if ("200".equals(requestClientAI[0])) { s = requestClientAI[1]; } else { @@ -94,12 +94,12 @@ public void onChat(EventPacket e) { aiRole.addProperty("role", "assistant"); aiRole.addProperty("content", s); msgs.add(aiRole); - if (msgs.size() > maxContext.value.intValue()) { + if (msgs.size() > maxContext.getValue().intValue()) { // remove the oldest message msgs.remove(0); } try { - Thread.sleep(delay.value.longValue()); + Thread.sleep(delay.getValue().longValue()); } catch (InterruptedException e1) { e1.printStackTrace(); } diff --git a/shared/java/top/fpsmaster/features/settings/Setting.java b/shared/java/top/fpsmaster/features/settings/Setting.java index 81d155d8..5885ba1a 100644 --- a/shared/java/top/fpsmaster/features/settings/Setting.java +++ b/shared/java/top/fpsmaster/features/settings/Setting.java @@ -1,9 +1,12 @@ package top.fpsmaster.features.settings; +import top.fpsmaster.event.EventDispatcher; +import top.fpsmaster.event.events.EventValueChange; + public class Setting { public String name; - public T value; + T value; public VisibleCondition visible; public Setting(String name, T value) { @@ -30,6 +33,10 @@ public T getValue() { } public void setValue(T value) { - this.value = value; + EventValueChange event = new EventValueChange(this, this.value, value); + EventDispatcher.dispatchEvent(event); + if (!event.isCanceled()) { + this.value = value; + } } } diff --git a/shared/java/top/fpsmaster/features/settings/impl/BooleanSetting.java b/shared/java/top/fpsmaster/features/settings/impl/BooleanSetting.java index bb86d8b0..a259d172 100644 --- a/shared/java/top/fpsmaster/features/settings/impl/BooleanSetting.java +++ b/shared/java/top/fpsmaster/features/settings/impl/BooleanSetting.java @@ -14,6 +14,6 @@ public BooleanSetting(String name, Boolean value, VisibleCondition visible) { } public void toggle() { - value = !value; + setValue(!getValue()); } } diff --git a/shared/java/top/fpsmaster/features/settings/impl/ColorSetting.java b/shared/java/top/fpsmaster/features/settings/impl/ColorSetting.java index ae123862..b090ad51 100644 --- a/shared/java/top/fpsmaster/features/settings/impl/ColorSetting.java +++ b/shared/java/top/fpsmaster/features/settings/impl/ColorSetting.java @@ -23,10 +23,10 @@ public ColorSetting(String name, Color value) { } public int getRGB() { - return value.getRGB(); + return getValue().getRGB(); } public Color getColor() { - return value.getColor(); + return getValue().getColor(); } } diff --git a/shared/java/top/fpsmaster/features/settings/impl/ModeSetting.java b/shared/java/top/fpsmaster/features/settings/impl/ModeSetting.java index 4bb1bc2e..5baabb9e 100644 --- a/shared/java/top/fpsmaster/features/settings/impl/ModeSetting.java +++ b/shared/java/top/fpsmaster/features/settings/impl/ModeSetting.java @@ -2,6 +2,8 @@ import top.fpsmaster.features.settings.Setting; +import java.util.Objects; + public class ModeSetting extends Setting { private String[] modes; @@ -17,7 +19,7 @@ public ModeSetting(String name, int value, VisibleCondition visible, String... m } public void cycle() { - value = (value + 1) % modes.length; + setValue((getValue() + 1) % modes.length); } public String getMode(int num) { @@ -25,15 +27,15 @@ public String getMode(int num) { } public boolean isMode(String mode) { - return modes[value] == mode; + return Objects.equals(modes[getValue()], mode); } public String getModeName() { - return modes[value]; + return modes[getValue()]; } public int getMode() { - return value; + return getValue(); } public int getModesSize() { diff --git a/shared/java/top/fpsmaster/features/settings/impl/NumberSetting.java b/shared/java/top/fpsmaster/features/settings/impl/NumberSetting.java index b5fe8c13..557cf4e9 100644 --- a/shared/java/top/fpsmaster/features/settings/impl/NumberSetting.java +++ b/shared/java/top/fpsmaster/features/settings/impl/NumberSetting.java @@ -22,15 +22,10 @@ public NumberSetting(String name, Number value, Number min, Number max, Number i this.inc = inc; } - @Override - public Number getValue() { - return value; - } - @Override public void setValue(Number newValue) { double closestMultipleOfInc = Math.round(newValue.doubleValue() / inc.doubleValue()) * inc.doubleValue(); closestMultipleOfInc = Math.round(closestMultipleOfInc * 100) / 100.0; - value = Math.max(min.doubleValue(), Math.min(max.doubleValue(), closestMultipleOfInc)); + super.setValue(Math.max(min.doubleValue(), Math.min(max.doubleValue(), closestMultipleOfInc))); } } diff --git a/shared/java/top/fpsmaster/modules/config/ConfigManager.java b/shared/java/top/fpsmaster/modules/config/ConfigManager.java index bebda062..454788ef 100644 --- a/shared/java/top/fpsmaster/modules/config/ConfigManager.java +++ b/shared/java/top/fpsmaster/modules/config/ConfigManager.java @@ -10,6 +10,7 @@ import top.fpsmaster.features.manager.Module; import top.fpsmaster.features.settings.Setting; import top.fpsmaster.features.settings.impl.*; +import top.fpsmaster.features.settings.impl.utils.CustomColor; import top.fpsmaster.ui.custom.Component; import top.fpsmaster.ui.custom.Position; import top.fpsmaster.utils.os.FileUtils; @@ -75,11 +76,12 @@ public void saveConfig(String name) throws FileException { moduleJson.addProperty("enabled", module.isEnabled()); moduleJson.addProperty("key", module.key); for (Setting setting : module.settings) { - String settingValue = setting.value.toString(); + String settingValue = setting.getValue().toString(); if (setting instanceof ColorSetting) { ColorSetting colorSetting = (ColorSetting) setting; - settingValue = colorSetting.value.hue + "|" + colorSetting.value.saturation + - "|" + colorSetting.value.brightness + "|" + colorSetting.value.alpha; + CustomColor value = colorSetting.getValue(); + settingValue = value.hue + "|" + value.saturation + + "|" + value.brightness + "|" + value.alpha; } moduleJson.addProperty(setting.name, settingValue); } @@ -113,20 +115,20 @@ public void loadConfig(String name) throws Exception { if (settingValue != null) { if (setting instanceof BooleanSetting) { BooleanSetting booleanSetting = (BooleanSetting) setting; - booleanSetting.value = settingValue.getAsBoolean(); + booleanSetting.setValue(settingValue.getAsBoolean()); } else if (setting instanceof NumberSetting) { NumberSetting numberSetting = (NumberSetting) setting; - numberSetting.value = settingValue.getAsDouble(); + numberSetting.setValue(settingValue.getAsDouble()); } else if (setting instanceof ModeSetting) { ModeSetting modeSetting = (ModeSetting) setting; - modeSetting.value = settingValue.getAsInt(); + modeSetting.setValue(settingValue.getAsInt()); } else if (setting instanceof TextSetting) { TextSetting textSetting = (TextSetting) setting; - textSetting.value = settingValue.getAsString(); + textSetting.setValue(settingValue.getAsString()); } else if (setting instanceof ColorSetting) { ColorSetting colorSetting = (ColorSetting) setting; String[] colorParts = settingValue.getAsString().split("\\|"); - colorSetting.value.setColor( + colorSetting.getValue().setColor( Float.parseFloat(colorParts[0]), Float.parseFloat(colorParts[1]), Float.parseFloat(colorParts[2]), @@ -134,7 +136,7 @@ public void loadConfig(String name) throws Exception { ); } else if (setting instanceof BindSetting) { BindSetting bindSetting = (BindSetting) setting; - bindSetting.value = settingValue.getAsInt(); + bindSetting.setValue(settingValue.getAsInt()); } } } diff --git a/shared/java/top/fpsmaster/modules/music/IngameOverlay.java b/shared/java/top/fpsmaster/modules/music/IngameOverlay.java index b156b26f..2c5c3a98 100644 --- a/shared/java/top/fpsmaster/modules/music/IngameOverlay.java +++ b/shared/java/top/fpsmaster/modules/music/IngameOverlay.java @@ -45,7 +45,7 @@ public static void onRender() { averageMagnitude = Math.sqrt(averageMagnitude); smoothCurve[bar] = AnimationUtils.base(smoothCurve[bar], averageMagnitude, 0.1); float xPos = (float) bar / numBars * screenWidth; - float height = (float) (smoothCurve[bar] * 100f * MusicOverlay.amplitude.value.floatValue()); + float height = (float) (smoothCurve[bar] * 100f * MusicOverlay.amplitude.getValue().floatValue()); Render2DUtils.drawRect( xPos, diff --git a/shared/java/top/fpsmaster/ui/click/modules/impl/BindSettingRender.java b/shared/java/top/fpsmaster/ui/click/modules/impl/BindSettingRender.java index 9d681650..a44e3016 100644 --- a/shared/java/top/fpsmaster/ui/click/modules/impl/BindSettingRender.java +++ b/shared/java/top/fpsmaster/ui/click/modules/impl/BindSettingRender.java @@ -28,7 +28,7 @@ public void render(float x, float y, float width, float height, float mouseX, fl FPSMaster.i18n.get((mod.name + "." + setting.name).toLowerCase(Locale.getDefault())), x + 10, y + 2, FPSMaster.theme.getTextColorTitle().getRGB() ); - String keyName = Keyboard.getKeyName(setting.value); + String keyName = Keyboard.getKeyName(setting.getValue()); UFontRenderer s16b = FPSMaster.fontManager.s16; float width1 = 10 + s16b.getStringWidth(keyName); if (Render2DUtils.isHovered(x + 15 + fw, y, width1, 14f, (int) mouseX, (int) mouseY)) { @@ -55,7 +55,7 @@ public void mouseClick(float x, float y, float width, float height, float mouseX float fw = FPSMaster.fontManager.s16.getStringWidth( FPSMaster.i18n.get((mod.name + "." + setting.name).toLowerCase(Locale.getDefault())) ); - String keyName = Keyboard.getKeyName(setting.value); + String keyName = Keyboard.getKeyName(setting.getValue()); UFontRenderer s16b = FPSMaster.fontManager.s16; if (Render2DUtils.isHovered( x + 25 + fw, @@ -74,7 +74,7 @@ public void mouseClick(float x, float y, float width, float height, float mouseX @Override public void keyTyped(char typedChar, int keyCode) { if (MainPanel.bindLock.equals(setting.name)) { - setting.value = Keyboard.getEventKey(); + setting.setValue(Keyboard.getEventKey()); MainPanel.bindLock = ""; } } diff --git a/shared/java/top/fpsmaster/ui/custom/Component.java b/shared/java/top/fpsmaster/ui/custom/Component.java index 53d545c3..859b61bf 100644 --- a/shared/java/top/fpsmaster/ui/custom/Component.java +++ b/shared/java/top/fpsmaster/ui/custom/Component.java @@ -137,7 +137,7 @@ public void scaleDown() { private void move(int x, int y) { ScaledResolution sr = new ScaledResolution(Utility.mc); int scaleFactor = 2; - if (ClientSettings.fixedScale.value) { + if (ClientSettings.fixedScale.getValue()) { scaleFactor = sr.getScaleFactor(); } float guiWidth = sr.getScaledWidth() / 2f * scaleFactor; diff --git a/shared/java/top/fpsmaster/ui/custom/ComponentsManager.java b/shared/java/top/fpsmaster/ui/custom/ComponentsManager.java index 600d2d61..86cdf859 100644 --- a/shared/java/top/fpsmaster/ui/custom/ComponentsManager.java +++ b/shared/java/top/fpsmaster/ui/custom/ComponentsManager.java @@ -53,9 +53,9 @@ public void draw(int mouseX, int mouseY) { GL11.glPushMatrix(); // Adjust mouse coordinates if fixed scale is enabled - if (ClientSettings.fixedScale.value) { + if (ClientSettings.fixedScale.getValue()) { ScaledResolution sr = new ScaledResolution(Utility.mc); - int scaleFactor = ClientSettings.fixedScale.value ? sr.getScaleFactor() : 2; + int scaleFactor = ClientSettings.fixedScale.getValue() ? sr.getScaleFactor() : 2; float guiWidth = sr.getScaledWidth() / 2f * scaleFactor; float guiHeight = sr.getScaledHeight() / 2f * scaleFactor; diff --git a/shared/java/top/fpsmaster/ui/custom/impl/ArmorDisplayComponent.java b/shared/java/top/fpsmaster/ui/custom/impl/ArmorDisplayComponent.java index c24ad7f5..a0355e58 100644 --- a/shared/java/top/fpsmaster/ui/custom/impl/ArmorDisplayComponent.java +++ b/shared/java/top/fpsmaster/ui/custom/impl/ArmorDisplayComponent.java @@ -31,7 +31,7 @@ public void draw(float x, float y) { int x1 = (int) (x + i * 18); int y1 = (int) y; - switch (ArmorDisplay.mode.value) { + switch (ArmorDisplay.mode.getValue()) { case 0: itemStack = armorInventory.get(armorInventory.size() - 1 - i); break; @@ -65,7 +65,7 @@ public void draw(float x, float y) { GlStateManager.disableRescaleNormal(); GlStateManager.disableBlend(); - if (ArmorDisplay.mode.value == 2) { + if (ArmorDisplay.mode.getValue() == 2) { // Draw durability int durability = itemStack.getMaxDamage() - itemStack.getItemDamage(); float dura = (float) durability / itemStack.getMaxDamage(); @@ -89,7 +89,7 @@ public void draw(float x, float y) { } } - switch (ArmorDisplay.mode.value) { + switch (ArmorDisplay.mode.getValue()) { case 0: width = 70f; height = 18f; diff --git a/shared/java/top/fpsmaster/ui/custom/impl/CoordsDisplayComponent.java b/shared/java/top/fpsmaster/ui/custom/impl/CoordsDisplayComponent.java index 5f7fe593..150d4a70 100644 --- a/shared/java/top/fpsmaster/ui/custom/impl/CoordsDisplayComponent.java +++ b/shared/java/top/fpsmaster/ui/custom/impl/CoordsDisplayComponent.java @@ -23,7 +23,7 @@ public void draw(float x, float y) { (int) ProviderManager.mcProvider.getPlayer().posY, (int) ProviderManager.mcProvider.getPlayer().posZ); - if (((CoordsDisplay) mod).limitDisplay.value) { + if (((CoordsDisplay) mod).limitDisplay.getValue()) { String yStr = getString(); s = String.format("X:%d Y:%d(%s) Z:%d", @@ -41,7 +41,7 @@ public void draw(float x, float y) { } private @NotNull String getString() { - int restHeight = ((CoordsDisplay) mod).limitDisplayY.value.intValue() - (int) ProviderManager.mcProvider.getPlayer().posY; + int restHeight = ((CoordsDisplay) mod).limitDisplayY.getValue().intValue() - (int) ProviderManager.mcProvider.getPlayer().posY; String yStr; // color diff --git a/shared/java/top/fpsmaster/ui/custom/impl/ModsListComponent.java b/shared/java/top/fpsmaster/ui/custom/impl/ModsListComponent.java index f6b2ea0f..0763491a 100644 --- a/shared/java/top/fpsmaster/ui/custom/impl/ModsListComponent.java +++ b/shared/java/top/fpsmaster/ui/custom/impl/ModsListComponent.java @@ -4,6 +4,7 @@ import top.fpsmaster.features.impl.interfaces.ModsList; import top.fpsmaster.features.manager.Category; import top.fpsmaster.features.manager.Module; +import top.fpsmaster.features.settings.impl.TextSetting; import top.fpsmaster.font.impl.UFontRenderer; import top.fpsmaster.ui.custom.Component; import top.fpsmaster.utils.render.Render2DUtils; @@ -18,7 +19,7 @@ public class ModsListComponent extends Component { List modules = new ArrayList<>(); - + public ModsListComponent() { super(ModsList.class); this.x = 1f; @@ -31,9 +32,10 @@ public void draw(float x, float y) { UFontRenderer font = FPSMaster.fontManager.s18; float modY = 0f; - if (((ModsList) mod).getShowLogo().value) { - drawString(36, "FPS V3", x + 0.5f, y + 0.5f, new Color(0, 0, 0, 150).getRGB()); - drawString(36, "FPS V3", x, y, FPSMaster.theme.getPrimary().getRGB()); + ModsList modlist = (ModsList) mod; + if (modlist.showLogo.getValue()) { + drawString(36, modlist.text.getValue(), x + 0.5f, y + 0.5f, new Color(0, 0, 0, 100).getRGB()); + drawString(36, modlist.text.getValue(), x, y, FPSMaster.theme.getPrimary().getRGB()); modY = 20f; } @@ -43,12 +45,12 @@ public void draw(float x, float y) { if (ProviderManager.mcProvider.getPlayer().ticksExisted % 20 == 0) modules = FPSMaster.moduleManager.modules.stream() .sorted((m1, m2) -> { - float w1 = (mod).betterFont.value - ? font.getStringWidth(((ModsList) mod).getEnglish().value ? m1.name : FPSMaster.i18n.get(m1.name.toLowerCase())) - : ProviderManager.mcProvider.getFontRenderer().getStringWidth(((ModsList) mod).getEnglish().value ? m1.name : FPSMaster.i18n.get(m1.name.toLowerCase())); - float w2 = (mod.betterFont.value - ? font.getStringWidth(((ModsList) mod).getEnglish().value ? m2.name : FPSMaster.i18n.get(m2.name.toLowerCase())) - : ProviderManager.mcProvider.getFontRenderer().getStringWidth(((ModsList) mod).getEnglish().value ? m2.name : FPSMaster.i18n.get(m2.name.toLowerCase()))); + float w1 = (mod).betterFont.getValue() + ? font.getStringWidth(modlist.english.getValue() ? m1.name : FPSMaster.i18n.get(m1.name.toLowerCase())) + : ProviderManager.mcProvider.getFontRenderer().getStringWidth(modlist.english.getValue() ? m1.name : FPSMaster.i18n.get(m1.name.toLowerCase())); + float w2 = (mod.betterFont.getValue() + ? font.getStringWidth(modlist.english.getValue() ? m2.name : FPSMaster.i18n.get(m2.name.toLowerCase())) + : ProviderManager.mcProvider.getFontRenderer().getStringWidth(modlist.english.getValue() ? m2.name : FPSMaster.i18n.get(m2.name.toLowerCase()))); return Float.compare(w2, w1); }).collect(Collectors.toList()); @@ -64,11 +66,11 @@ public void draw(float x, float y) { } String name = FPSMaster.i18n.get(module.name.toLowerCase()); - if (((ModsList) mod).getEnglish().value) { + if (modlist.english.getValue()) { name = module.name; } - float width = mod.betterFont.value + float width = mod.betterFont.getValue() ? font.getStringWidth(name) : ProviderManager.mcProvider.getFontRenderer().getStringWidth(name); @@ -76,13 +78,13 @@ public void draw(float x, float y) { width2 = width + 5; } - Render2DUtils.drawRect(x - width - 4, y + modY, width + 4, 14f, ((ModsList) mod).backgroundColor.getColor()); - Color color = ((ModsList) mod).getColor().getColor(); - if (((ModsList) mod).getRainbow().value) { + Render2DUtils.drawRect(x - width - 4, y + modY, width + 4, 14f, modlist.backgroundColor.getColor()); + Color color = modlist.color.getColor(); + if (modlist.rainbow.getValue()) { color = col; } - if (mod.betterFont.value) { + if (mod.betterFont.getValue()) { font.drawStringWithShadow(name, x - width - 2, y + modY + 2, color.getRGB()); } else { ProviderManager.mcProvider.getFontRenderer().drawStringWithShadow(name, x - width - 2, y + modY, color.getRGB()); diff --git a/shared/java/top/fpsmaster/utils/render/Render2DUtils.java b/shared/java/top/fpsmaster/utils/render/Render2DUtils.java index 949ac08e..cee28e99 100644 --- a/shared/java/top/fpsmaster/utils/render/Render2DUtils.java +++ b/shared/java/top/fpsmaster/utils/render/Render2DUtils.java @@ -205,7 +205,7 @@ public static int fixScale() { public static int getFixedScale() { ScaledResolution sr = new ScaledResolution(mc); int scaleFactor; - if (ClientSettings.fixedScale.value) { + if (ClientSettings.fixedScale.getValue()) { scaleFactor = sr.getScaleFactor(); } else { scaleFactor = 2; @@ -216,7 +216,7 @@ public static int getFixedScale() { public static float[] getFixedBounds() { ScaledResolution sr = new ScaledResolution(mc); int scaleFactor; - if (ClientSettings.fixedScale.value) { + if (ClientSettings.fixedScale.getValue()) { scaleFactor = sr.getScaleFactor(); } else { scaleFactor = 2; diff --git a/shared/java/top/fpsmaster/utils/render/shader/GradientUtils.java b/shared/java/top/fpsmaster/utils/render/shader/GradientUtils.java index 3e09827e..8195bf2d 100644 --- a/shared/java/top/fpsmaster/utils/render/shader/GradientUtils.java +++ b/shared/java/top/fpsmaster/utils/render/shader/GradientUtils.java @@ -28,7 +28,7 @@ public static void applyGradient(float x, float y, float width, float height, fl ScaledResolution sr = new ScaledResolution(Minecraft.getMinecraft()); int factor = sr.getScaleFactor(); - if (ClientSettings.fixedScale.value) { + if (ClientSettings.fixedScale.getValue()) { factor = 2; } gradientMaskShader.setUniformf("location", x * factor, (Minecraft.getMinecraft().displayHeight - (height * factor)) - (y * factor)); diff --git a/shared/resources/assets/minecraft/client/lang/zh_cn.lang b/shared/resources/assets/minecraft/client/lang/zh_cn.lang index 2484ef62..85282bb1 100644 --- a/shared/resources/assets/minecraft/client/lang/zh_cn.lang +++ b/shared/resources/assets/minecraft/client/lang/zh_cn.lang @@ -521,6 +521,8 @@ irc.disconnect=§c[IRC] §r§c您已断开连接,请重新连接。 special.under_dev=正在开发中,请等待版本更新 translate.hover=点此翻译 command.notfound=未找到命令,如果客户端命令影响了您的消息,请关闭实用->客户端命令 功能。 +blur.fast_render=组件模糊与快速渲染不兼容,如要使用模糊效果,请先在设置中关闭快速渲染。 +blur.performance=组件模糊会极大影响性能,若您的配置较低,不建议开启! # 插件 plugin_manager.title=插件市场 \ No newline at end of file diff --git a/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/ChunkRenderDispatcherMixin_LimitUpdates.java b/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/ChunkRenderDispatcherMixin_LimitUpdates.java index 14074355..3156594e 100644 --- a/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/ChunkRenderDispatcherMixin_LimitUpdates.java +++ b/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/ChunkRenderDispatcherMixin_LimitUpdates.java @@ -14,7 +14,7 @@ public class ChunkRenderDispatcherMixin_LimitUpdates { @SuppressWarnings("BusyWait") @Inject(method = "getNextChunkUpdate", at = @At("HEAD")) private void patcher$limitChunkUpdates(CallbackInfoReturnable cir) throws InterruptedException { - while (Performance.limitChunks.value && RenderChunk.renderChunksUpdated >= Performance.chunkUpdateLimit.getValue().intValue()) { + while (Performance.limitChunks.getValue() && RenderChunk.renderChunksUpdated >= Performance.chunkUpdateLimit.getValue().intValue()) { Thread.sleep(50L); } } diff --git a/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/EntityFXMixin_StaticParticleColor.java b/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/EntityFXMixin_StaticParticleColor.java index ceaa9e5a..a69ecd27 100644 --- a/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/EntityFXMixin_StaticParticleColor.java +++ b/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/EntityFXMixin_StaticParticleColor.java @@ -10,6 +10,6 @@ public class EntityFXMixin_StaticParticleColor { @Redirect(method = "renderParticle", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/particle/EntityFX;getBrightnessForRender(F)I")) private int patcher$staticParticleColor(EntityFX entityFX, float partialTicks) { - return Performance.staticParticleColor.value ? 15728880 : entityFX.getBrightnessForRender(partialTicks); + return Performance.staticParticleColor.getValue() ? 15728880 : entityFX.getBrightnessForRender(partialTicks); } } diff --git a/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinFontRender.java b/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinFontRender.java index 4d663f9a..6330c5f4 100644 --- a/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinFontRender.java +++ b/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinFontRender.java @@ -32,7 +32,7 @@ public abstract class MixinFontRender { @Inject(method = "getStringWidth", at = @At("HEAD"), cancellable = true) public void getStringWidth(String text, CallbackInfoReturnable cir) { text = GlobalTextFilter.filter(text); - if (Performance.fontOptimize.value) { + if (Performance.fontOptimize.getValue()) { cir.setReturnValue(this.patcher$fontRendererHook.getStringWidth(text)); } else { int i = 0; @@ -67,7 +67,7 @@ public void getStringWidth(String text, CallbackInfoReturnable cir) { @Inject(method = "renderStringAtPos", at = @At("HEAD"), cancellable = true) private void patcher$useOptimizedRendering(String text, boolean shadow, CallbackInfo ci) { - if (Performance.fontOptimize.value) { + if (Performance.fontOptimize.getValue()) { if (this.patcher$fontRendererHook.renderStringAtPos(text, shadow)) { ci.cancel(); } diff --git a/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinGuiContainer.java b/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinGuiContainer.java index 6ab0ee43..b5a5c003 100644 --- a/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinGuiContainer.java +++ b/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinGuiContainer.java @@ -31,7 +31,7 @@ public void logo(int mouseX, int mouseY, float partialTicks, CallbackInfo ci) { ScaledResolution sr = new ScaledResolution(Minecraft.getMinecraft()); GL11.glPushMatrix(); Render2DUtils.fixScale(); - if (ClientSettings.fixedScale.value) { + if (ClientSettings.fixedScale.getValue()) { Render2DUtils.drawImage(new ResourceLocation("client/gui/settings/logo.png"), 0, (float) sr.getScaledHeight() * sr.getScaleFactor() / 2 - 32, 163 / 2f, 32, -1); } else { Render2DUtils.drawImage(new ResourceLocation("client/gui/settings/logo.png"), 0, (float) sr.getScaledHeight() - 32, 163 / 2f, 32, -1); diff --git a/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/ModelRendererMixin_BatchDrawing.java b/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/ModelRendererMixin_BatchDrawing.java index 7523e10e..61975007 100644 --- a/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/ModelRendererMixin_BatchDrawing.java +++ b/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/ModelRendererMixin_BatchDrawing.java @@ -21,22 +21,22 @@ public class ModelRendererMixin_BatchDrawing { @Inject(method = "render", at = @At("HEAD")) private void patcher$resetCompiled(float j, CallbackInfo ci) { - if (patcher$compiledState != Performance.batchModelRendering.value) { + if (patcher$compiledState != Performance.batchModelRendering.getValue()) { this.compiled = false; } } @Inject(method = "compileDisplayList", at = @At(value = "INVOKE_ASSIGN", target = "Lnet/minecraft/client/renderer/Tessellator;getWorldRenderer()Lnet/minecraft/client/renderer/WorldRenderer;")) private void patcher$beginRendering(CallbackInfo ci) { - this.patcher$compiledState = Performance.batchModelRendering.value; - if (Performance.batchModelRendering.value) { + this.patcher$compiledState = Performance.batchModelRendering.getValue(); + if (Performance.batchModelRendering.getValue()) { Tessellator.getInstance().getWorldRenderer().begin(7, DefaultVertexFormats.OLDMODEL_POSITION_TEX_NORMAL); } } @Inject(method = "compileDisplayList", at = @At(value = "INVOKE", target = "Lorg/lwjgl/opengl/GL11;glEndList()V", remap = false)) private void patcher$draw(CallbackInfo ci) { - if (Performance.batchModelRendering.value) { + if (Performance.batchModelRendering.getValue()) { Tessellator.getInstance().draw(); } } diff --git a/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/TexturedQuadMixin_BatchDraw.java b/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/TexturedQuadMixin_BatchDraw.java index bfee6618..f6404356 100644 --- a/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/TexturedQuadMixin_BatchDraw.java +++ b/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/TexturedQuadMixin_BatchDraw.java @@ -22,14 +22,14 @@ public class TexturedQuadMixin_BatchDraw { @Redirect(method = "draw", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/WorldRenderer;begin(ILnet/minecraft/client/renderer/vertex/VertexFormat;)V")) private void patcher$beginDraw(WorldRenderer renderer, int glMode, VertexFormat format) { this.patcher$drawOnSelf = !((WorldRendererAccessor) renderer).isDrawing(); - if (this.patcher$drawOnSelf || !Performance.batchModelRendering.value) { + if (this.patcher$drawOnSelf || !Performance.batchModelRendering.getValue()) { renderer.begin(glMode, DefaultVertexFormats.POSITION_TEX_NORMAL); } } @Redirect(method = "draw", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/Tessellator;draw()V")) private void patcher$endDraw(Tessellator tessellator) { - if (this.patcher$drawOnSelf || !Performance.batchModelRendering.value) { + if (this.patcher$drawOnSelf || !Performance.batchModelRendering.getValue()) { tessellator.draw(); } } diff --git a/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/WorldClientMixin_AnimationTick.java b/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/WorldClientMixin_AnimationTick.java index aae56f2b..dd20c205 100644 --- a/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/WorldClientMixin_AnimationTick.java +++ b/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/WorldClientMixin_AnimationTick.java @@ -10,6 +10,6 @@ public class WorldClientMixin_AnimationTick { @ModifyConstant(method = "doVoidFogParticles", constant = @Constant(intValue = 1000)) private int patcher$lowerTickCount(int original) { - return Performance.lowAnimationTick.value ? 100 : original; + return Performance.lowAnimationTick.getValue() ? 100 : original; } } \ No newline at end of file From 42bdafff85bc01b29fba924ac88baa8b527eddc8 Mon Sep 17 00:00:00 2001 From: SuperSkidder Date: Mon, 14 Jul 2025 14:40:13 +0800 Subject: [PATCH 080/193] fix: TextInputBox doesn't render until being focused fix: add missing translations --- shared/java/top/fpsmaster/ui/common/TextField.java | 2 +- .../java/top/fpsmaster/ui/custom/impl/ModsListComponent.java | 5 +++-- shared/resources/assets/minecraft/client/lang/zh_cn.lang | 3 ++- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/shared/java/top/fpsmaster/ui/common/TextField.java b/shared/java/top/fpsmaster/ui/common/TextField.java index 3b13f997..be7c6008 100644 --- a/shared/java/top/fpsmaster/ui/common/TextField.java +++ b/shared/java/top/fpsmaster/ui/common/TextField.java @@ -105,7 +105,7 @@ public void setText(String text) { this.text = text; } - this.setCursorPositionEnd(); + this.setCursorPositionZero(); } } diff --git a/shared/java/top/fpsmaster/ui/custom/impl/ModsListComponent.java b/shared/java/top/fpsmaster/ui/custom/impl/ModsListComponent.java index 0763491a..491df9a9 100644 --- a/shared/java/top/fpsmaster/ui/custom/impl/ModsListComponent.java +++ b/shared/java/top/fpsmaster/ui/custom/impl/ModsListComponent.java @@ -34,8 +34,9 @@ public void draw(float x, float y) { ModsList modlist = (ModsList) mod; if (modlist.showLogo.getValue()) { - drawString(36, modlist.text.getValue(), x + 0.5f, y + 0.5f, new Color(0, 0, 0, 100).getRGB()); - drawString(36, modlist.text.getValue(), x, y, FPSMaster.theme.getPrimary().getRGB()); + float stringWidth = getStringWidth(36, modlist.text.getValue()); + drawString(36, modlist.text.getValue(), (float) (x + 0.5 + width - stringWidth), y + 0.5f, new Color(0, 0, 0, 100).getRGB()); + drawString(36, modlist.text.getValue(), x + width - stringWidth, y, FPSMaster.theme.getPrimary().getRGB()); modY = 20f; } diff --git a/shared/resources/assets/minecraft/client/lang/zh_cn.lang b/shared/resources/assets/minecraft/client/lang/zh_cn.lang index 85282bb1..7d52fa36 100644 --- a/shared/resources/assets/minecraft/client/lang/zh_cn.lang +++ b/shared/resources/assets/minecraft/client/lang/zh_cn.lang @@ -454,7 +454,8 @@ coordsdisplay.background=背景 modslist=功能列表 modslist.desc=显示开启的功能 -modslist.showlogo=显示客户端标志 +modslist.showtext=显示自定义文本 +modslist.text=自定义文本 modslist.english=显示英文功能名 modslist.color=功能列表颜色 modslist.rainbow=功能列表彩色 From 7b13257e8ef72e1afaf82b65773d195c37af17e4 Mon Sep 17 00:00:00 2001 From: SuperSkidder Date: Mon, 14 Jul 2025 16:17:45 +0800 Subject: [PATCH 081/193] feat: new motionblur mode --- .../features/impl/render/MotionBlur.java | 60 +++++++++++++++++-- .../assets/minecraft/client/lang/zh_cn.lang | 7 ++- .../minecraft/shaders/post/motionblur.json | 35 +++++++++++ .../shaders/post/motionblur_core.json | 36 +++++++++++ .../minecraft/shaders/program/motionblur.fsh | 28 +++++++++ .../minecraft/shaders/program/motionblur.json | 20 +++++++ .../shaders/program/motionblur_core.fsh | 30 ++++++++++ .../shaders/program/motionblur_core.json | 20 +++++++ .../src/main/resources/mixins.fpsmaster.json | 1 + 9 files changed, 228 insertions(+), 9 deletions(-) create mode 100644 shared/resources/assets/minecraft/shaders/post/motionblur.json create mode 100644 shared/resources/assets/minecraft/shaders/post/motionblur_core.json create mode 100644 shared/resources/assets/minecraft/shaders/program/motionblur.fsh create mode 100644 shared/resources/assets/minecraft/shaders/program/motionblur.json create mode 100644 shared/resources/assets/minecraft/shaders/program/motionblur_core.fsh create mode 100644 shared/resources/assets/minecraft/shaders/program/motionblur_core.json diff --git a/shared/java/top/fpsmaster/features/impl/render/MotionBlur.java b/shared/java/top/fpsmaster/features/impl/render/MotionBlur.java index fc989fe5..592d57fa 100644 --- a/shared/java/top/fpsmaster/features/impl/render/MotionBlur.java +++ b/shared/java/top/fpsmaster/features/impl/render/MotionBlur.java @@ -2,29 +2,42 @@ import net.minecraft.client.Minecraft; import net.minecraft.client.gui.ScaledResolution; +import net.minecraft.client.renderer.EntityRenderer; import net.minecraft.client.renderer.GlStateManager; import net.minecraft.client.renderer.OpenGlHelper; import net.minecraft.client.renderer.Tessellator; import net.minecraft.client.renderer.vertex.DefaultVertexFormats; import net.minecraft.client.shader.Framebuffer; +import net.minecraft.client.shader.Shader; +import net.minecraft.util.ResourceLocation; import org.lwjgl.opengl.GL11; +import top.fpsmaster.FPSMaster; import top.fpsmaster.event.Subscribe; import top.fpsmaster.event.events.EventMotionBlur; import top.fpsmaster.features.manager.Category; import top.fpsmaster.features.manager.Module; +import top.fpsmaster.features.settings.impl.ModeSetting; import top.fpsmaster.features.settings.impl.NumberSetting; +import top.fpsmaster.forge.api.IShaderGroup; import top.fpsmaster.interfaces.ProviderManager; import top.fpsmaster.utils.OptifineUtil; +import top.fpsmaster.utils.Utility; import top.fpsmaster.wrapper.renderEngine.bufferbuilder.WrapperBufferBuilder; +import java.util.List; + +import static top.fpsmaster.utils.Utility.mc; + public class MotionBlur extends Module { private static Framebuffer blurBufferMain; private static Framebuffer blurBufferInto; - private NumberSetting multiplier = new NumberSetting("Multiplier", 2, 0, 10, 0.5); + + private ModeSetting mode = new ModeSetting("Mode", 1, "Old", "New"); + private NumberSetting multiplier = new NumberSetting("Strength", 2, 0, 10, 0.5); public MotionBlur() { super("MotionBlur", Category.RENDER); - addSettings(multiplier); + addSettings(mode, multiplier); } @Override @@ -32,6 +45,7 @@ public void onEnable() { super.onEnable(); if (OptifineUtil.isFastRender()) { OptifineUtil.setFastRender(false); + Utility.sendClientNotify(FPSMaster.i18n.get("motionblur.fast_render")); } } @@ -66,14 +80,48 @@ private static void drawTexturedRectNoBlend(float x, float y, float width, float @Subscribe public void renderOverlay(EventMotionBlur event) { - if (ProviderManager.mcProvider.getPlayer() == null || ProviderManager.mcProvider.getPlayer().ticksExisted < 20) + if (ProviderManager.mcProvider.getWorld() == null) return; - if (Minecraft.getMinecraft().currentScreen == null) { - blur(multiplier.getValue().floatValue()); + if (mode.isMode("Old")) { + if (Minecraft.getMinecraft().currentScreen == null) { + if (isUsingShader()) + Minecraft.getMinecraft().entityRenderer.stopUseShader(); + blur(multiplier.getValue().floatValue()); + } + } else if (mode.isMode("New")) { + if (mc.currentScreen != null) + return; + if (!isUsingShader()) { + mc.entityRenderer.loadShader(new ResourceLocation("shaders/post/motionblur.json")); + mc.entityRenderer.loadShader(new ResourceLocation("shaders/post/motionblur_core.json")); + } + float strength = 0.7f + multiplier.getValue().floatValue() / 100.0f * 3.0f - 0.01f; + IShaderGroup shaderGroup = (IShaderGroup) mc.entityRenderer.getShaderGroup(); + if (shaderGroup == null) + return; + List listShaders = shaderGroup.getListShaders(); + if (listShaders == null) + return; + listShaders.forEach(it -> { + if (it.getShaderManager().getShaderUniform("Phosphor") != null) { + it.getShaderManager().getShaderUniform("Phosphor").set(strength, 0, 0); + } + }); } } + private boolean isUsingShader() { + EntityRenderer entityRenderer = mc.entityRenderer; + return entityRenderer.isShaderActive() && entityRenderer.getShaderGroup() != null && entityRenderer.getShaderGroup().getShaderGroupName().equalsIgnoreCase("minecraft:shaders/post/motionblur_core.json"); + } + + @Override + public void onDisable() { + super.onDisable(); + Minecraft.getMinecraft().entityRenderer.stopUseShader(); + } + public static void blur(float multiplier) { if (OpenGlHelper.isFramebufferEnabled()) { ScaledResolution sr = new ScaledResolution(Minecraft.getMinecraft()); @@ -82,7 +130,7 @@ public static void blur(float multiplier) { GlStateManager.matrixMode(GL11.GL_PROJECTION); GlStateManager.loadIdentity(); - GlStateManager.ortho(0.0, width / sr.getScaleFactor(), height / sr.getScaleFactor(), 0.0, 2000.0, 4000.0); + GlStateManager.ortho(0.0, (double) width / sr.getScaleFactor(), (double) height / sr.getScaleFactor(), 0.0, 2000.0, 4000.0); GlStateManager.matrixMode(GL11.GL_MODELVIEW); GlStateManager.loadIdentity(); GlStateManager.translate(0f, 0f, -2000f); diff --git a/shared/resources/assets/minecraft/client/lang/zh_cn.lang b/shared/resources/assets/minecraft/client/lang/zh_cn.lang index 7d52fa36..4df038af 100644 --- a/shared/resources/assets/minecraft/client/lang/zh_cn.lang +++ b/shared/resources/assets/minecraft/client/lang/zh_cn.lang @@ -205,9 +205,9 @@ moreparticles.killeffect=击杀效果 motionblur=运动模糊 motionblur.desc=运动模糊 -motionblur.multiplier=运动模糊倍数 +motionblur.strength=运动模糊倍数 motionblur.mode=运动模糊模式 -motionblur.mode.classic=经典 +motionblur.mode.old=经典 motionblur.mode.new=新的 motionblur.fastrender=注意!动态模糊功能与快速渲染并不兼容,我们已为您自动关闭了快速渲染。 @@ -523,7 +523,8 @@ special.under_dev=正在开发中,请等待版本更新 translate.hover=点此翻译 command.notfound=未找到命令,如果客户端命令影响了您的消息,请关闭实用->客户端命令 功能。 blur.fast_render=组件模糊与快速渲染不兼容,如要使用模糊效果,请先在设置中关闭快速渲染。 -blur.performance=组件模糊会极大影响性能,若您的配置较低,不建议开启! +blur.performance=组件模糊会极大影响性能,若您的配置较低则不建议开启! +motionblur.fast_render=快速渲染与运动模糊不兼容,已为您自动关闭快速渲染。 # 插件 plugin_manager.title=插件市场 \ No newline at end of file diff --git a/shared/resources/assets/minecraft/shaders/post/motionblur.json b/shared/resources/assets/minecraft/shaders/post/motionblur.json new file mode 100644 index 00000000..d34eaff1 --- /dev/null +++ b/shared/resources/assets/minecraft/shaders/post/motionblur.json @@ -0,0 +1,35 @@ +{ + "targets": [ + "swap", + "previous" + ], + "passes": [ + { + "name": "motionblur", + "intarget": "minecraft:main", + "outtarget": "swap", + "auxtargets": [ + { + "name": "PrevSampler", + "id": "previous" + } + ], + "uniforms": [ + { + "name": "Phosphor", + "values": [ 0.95, 0.95, 0.95 ] + } + ] + }, + { + "name": "blit", + "intarget": "swap", + "outtarget": "previous" + }, + { + "name": "blit", + "intarget": "swap", + "outtarget": "minecraft:main" + } + ] +} diff --git a/shared/resources/assets/minecraft/shaders/post/motionblur_core.json b/shared/resources/assets/minecraft/shaders/post/motionblur_core.json new file mode 100644 index 00000000..f7c5f4e4 --- /dev/null +++ b/shared/resources/assets/minecraft/shaders/post/motionblur_core.json @@ -0,0 +1,36 @@ +{ + "targets": [ + "swap", + "previous" + ], + "passes": [ + { + "name": "motionblur_core", + "intarget": "minecraft:main", + "outtarget": "swap", + "use_linear_filter": true, + "auxtargets": [ + { + "name": "PrevSampler", + "id": "previous" + } + ], + "uniforms": [ + { + "name": "Phosphor", + "values": [ 0.95, 0.95, 0.95 ] + } + ] + }, + { + "name": "blit", + "intarget": "swap", + "outtarget": "previous" + }, + { + "name": "blit", + "intarget": "swap", + "outtarget": "minecraft:main" + } + ] +} diff --git a/shared/resources/assets/minecraft/shaders/program/motionblur.fsh b/shared/resources/assets/minecraft/shaders/program/motionblur.fsh new file mode 100644 index 00000000..9300bbcc --- /dev/null +++ b/shared/resources/assets/minecraft/shaders/program/motionblur.fsh @@ -0,0 +1,28 @@ +#version 120 + +uniform sampler2D DiffuseSampler; +uniform sampler2D PrevSampler; + +varying vec2 texCoord; +varying vec2 oneTexel; + +uniform vec2 InSize; + +uniform vec3 Phosphor = vec3(0.7, 0.0, 0.0); + +void main() { + vec4 CurrTexel = texture2D(DiffuseSampler, texCoord); + vec4 PrevTexel = texture2D(PrevSampler, texCoord); + float factor = Phosphor.r; + + if (Phosphor.g == 0) { + gl_FragColor = vec4(max(PrevTexel.rgb * vec3(factor), CurrTexel.rgb), 1.0); + } else if (Phosphor.g == 1) { + gl_FragColor = vec4(mix(PrevTexel.rgb, CurrTexel.rgb, factor), 1.0); + } else { + PrevTexel.a = max(0.0, min(PrevTexel.a - 0.325, PrevTexel.a * factor * 0.95)); + + vec3 blendedRGB = PrevTexel.rgb * PrevTexel.a + CurrTexel.rgb * (1.0 - PrevTexel.a); + gl_FragColor = vec4(blendedRGB, 1.0); + } +} diff --git a/shared/resources/assets/minecraft/shaders/program/motionblur.json b/shared/resources/assets/minecraft/shaders/program/motionblur.json new file mode 100644 index 00000000..4ab2b006 --- /dev/null +++ b/shared/resources/assets/minecraft/shaders/program/motionblur.json @@ -0,0 +1,20 @@ +{ + "blend": { + "func": "add", + "srcrgb": "one", + "dstrgb": "zero" + }, + "vertex": "sobel", + "fragment": "motionblur", + "attributes": [ "Position" ], + "samplers": [ + { "name": "DiffuseSampler" }, + { "name": "PrevSampler" } + ], + "uniforms": [ + { "name": "ProjMat", "type": "matrix4x4", "count": 16, "values": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 ] }, + { "name": "InSize", "type": "float", "count": 2, "values": [ 1.0, 1.0 ] }, + { "name": "OutSize", "type": "float", "count": 2, "values": [ 1.0, 1.0 ] }, + { "name": "Phosphor", "type": "float", "count": 3, "values": [ 0.3, 0.3, 0.3 ] } + ] +} diff --git a/shared/resources/assets/minecraft/shaders/program/motionblur_core.fsh b/shared/resources/assets/minecraft/shaders/program/motionblur_core.fsh new file mode 100644 index 00000000..c9d1aa1f --- /dev/null +++ b/shared/resources/assets/minecraft/shaders/program/motionblur_core.fsh @@ -0,0 +1,30 @@ +#version 150 + +uniform sampler2D DiffuseSampler; +uniform sampler2D PrevSampler; + +in vec2 texCoord; +in vec2 oneTexel; + +uniform vec2 InSize; + +uniform vec3 Phosphor = vec3(0.7, 0.0, 0.0); + +out vec4 fragColor; + +void main() { + vec4 CurrTexel = texture(DiffuseSampler, texCoord); + vec4 PrevTexel = texture(PrevSampler, texCoord); + float factor = Phosphor.r; + + if (Phosphor.g == 0) { + fragColor = vec4(max(PrevTexel.rgb * vec3(factor), CurrTexel.rgb), 1.0); + } else if (Phosphor.g == 1) { + fragColor = vec4(mix(PrevTexel.rgb, CurrTexel.rgb, factor), 1.0); + } else { + PrevTexel.a = max(0.0, min(PrevTexel.a - 0.325, PrevTexel.a * factor * 0.95)); + + vec3 blendedRGB = PrevTexel.rgb * PrevTexel.a + CurrTexel.rgb * (1.0 - PrevTexel.a); + fragColor = vec4(blendedRGB, 1.0); + } +} diff --git a/shared/resources/assets/minecraft/shaders/program/motionblur_core.json b/shared/resources/assets/minecraft/shaders/program/motionblur_core.json new file mode 100644 index 00000000..4e2799d4 --- /dev/null +++ b/shared/resources/assets/minecraft/shaders/program/motionblur_core.json @@ -0,0 +1,20 @@ +{ + "blend": { + "func": "add", + "srcrgb": "one", + "dstrgb": "zero" + }, + "vertex": "sobel", + "fragment": "motionblur_core", + "attributes": [ "Position" ], + "samplers": [ + { "name": "DiffuseSampler" }, + { "name": "PrevSampler" } + ], + "uniforms": [ + { "name": "ProjMat", "type": "matrix4x4", "count": 16, "values": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 ] }, + { "name": "InSize", "type": "float", "count": 2, "values": [ 1.0, 1.0 ] }, + { "name": "OutSize", "type": "float", "count": 2, "values": [ 1.0, 1.0 ] }, + { "name": "Phosphor", "type": "float", "count": 3, "values": [ 0.3, 0.3, 0.3 ] } + ] +} diff --git a/v1.8.9/src/main/resources/mixins.fpsmaster.json b/v1.8.9/src/main/resources/mixins.fpsmaster.json index 5b0dd946..2c59be17 100644 --- a/v1.8.9/src/main/resources/mixins.fpsmaster.json +++ b/v1.8.9/src/main/resources/mixins.fpsmaster.json @@ -43,6 +43,7 @@ "MixinRenderManager", "MixinRenderTNTPrimed", "MixinServerSelectionList", + "MixinShaderGroup", "WorldClientMixin_AnimationTick", "accessor.FontRendererAccessor", "accessor.GlStateManagerAccessor", From beb0a75386a1f295f78d8502210d931e02d69743 Mon Sep 17 00:00:00 2001 From: SuperSkidder Date: Mon, 14 Jul 2025 16:58:44 +0800 Subject: [PATCH 082/193] lang: update zh_cn and en_us --- .../features/command/CommandManager.java | 2 +- .../impl/interfaces/ClientSettings.java | 9 +- .../assets/minecraft/client/lang/en_us.lang | 578 ++++++++++++------ .../assets/minecraft/client/lang/zh_cn.lang | 88 +-- 4 files changed, 446 insertions(+), 231 deletions(-) diff --git a/shared/java/top/fpsmaster/features/command/CommandManager.java b/shared/java/top/fpsmaster/features/command/CommandManager.java index d1ea02e2..0786b79f 100644 --- a/shared/java/top/fpsmaster/features/command/CommandManager.java +++ b/shared/java/top/fpsmaster/features/command/CommandManager.java @@ -30,7 +30,7 @@ public void init() { @Subscribe public void onChat(EventSendChatMessage e) throws Exception { - if (e.msg.startsWith(ClientSettings.prefix.getValue())) { + if (ClientSettings.clientCommand.getValue() && e.msg.startsWith(ClientSettings.prefix.getValue())) { e.cancel(); mc.ingameGUI.getChatGUI().addToSentMessages(e.msg); runCommand(e.msg.substring(1)); diff --git a/shared/java/top/fpsmaster/features/impl/interfaces/ClientSettings.java b/shared/java/top/fpsmaster/features/impl/interfaces/ClientSettings.java index af62d1da..23d2189b 100644 --- a/shared/java/top/fpsmaster/features/impl/interfaces/ClientSettings.java +++ b/shared/java/top/fpsmaster/features/impl/interfaces/ClientSettings.java @@ -17,11 +17,12 @@ public class ClientSettings extends InterfaceModule { public static BooleanSetting blur = new BooleanSetting("blur", false); public static BindSetting keyBind = new BindSetting("ClickGuiKey", Keyboard.KEY_RSHIFT); public static BooleanSetting fixedScale = new BooleanSetting("FixedScale", true); - public static final TextSetting prefix = new TextSetting("prefix", "#"); + public static BooleanSetting clientCommand = new BooleanSetting("Command", true); + public static final TextSetting prefix = new TextSetting("prefix", "#", () -> clientCommand.getValue()); public ClientSettings() { super("ClientSettings", Category.Utility); - addSettings(prefix, keyBind, fixedScale, blur); + addSettings(keyBind, fixedScale, blur, clientCommand, prefix); EventDispatcher.registerListener(this); } @@ -32,8 +33,8 @@ public void onEnable() { } @Subscribe - public void onValueChange(EventValueChange e){ - if (e.setting == blur && ((boolean) e.newValue)){ + public void onValueChange(EventValueChange e) { + if (e.setting == blur && ((boolean) e.newValue)) { if (OptifineUtil.isFastRender()) { Utility.sendClientNotify(FPSMaster.i18n.get("blur.fast_render")); e.cancel(); diff --git a/shared/resources/assets/minecraft/client/lang/en_us.lang b/shared/resources/assets/minecraft/client/lang/en_us.lang index 15dba463..e7ead5dc 100644 --- a/shared/resources/assets/minecraft/client/lang/en_us.lang +++ b/shared/resources/assets/minecraft/client/lang/en_us.lang @@ -1,163 +1,286 @@ -# Interface -mainmenu.single=Single player +# UI +mainmenu.single=Singleplayer mainmenu.multi=Multiplayer -mainmenu.proxy=Netease Proxy mainmenu.settings=Settings -mainmenu.login=Click to login! -mainmenu.notlogin=You are not logged in, click here! -mainmenu.latest=You are using latest version! -mainmenu.notlatest=You are not latest! Latest version: -mainmenu.welcome=Welcome, -mainmenu.toupdate=, Click here to update! +mainmenu.notlogin=You're not logged in. Click here to log in +mainmenu.welcome=Welcome, %s +mainmenu.latest=You're using the latest version! +mainmenu.failed=Failed to fetch update! +mainmenu.notlatest=You're not on the latest version. Click to update! music.title=Music music.search=Search -music.disabled=Music function is off, check details at fpsmaster.top/faq/music -music.name=Search Name -music.list=Search Playlist ID -music.notloggedin=Not logged in -music.scantitle=Scan Code to login -music.waitscan=Waiting for scan -music.waitconfirmation=Waiting for confirmation -music.loggedin=Logged in +music.name=Search by Title +music.list=Search by Playlist ID +music.daily=Daily Mix +music.notloggedin=Not Logged In +music.scantitle=Scan to Log In +music.waitscan=Waiting for scan +music.waitconfirmation=Waiting for confirmation +music.loggedin=Logged In + theme.title=Theme theme.dark=Dark theme.light=Light -theme.free=Free -theme.vip=Sponsor oobe.welcome.title=Welcome oobe.welcome.next=Next -oobe.login.privacy=We collect some anonymous data to improve experience, by continuing you agree to "Privacy Policy" and "Terms of Service" -oobe.login.title=Login Account -oobe.login.desc=You can register on the official FPSMaster website +oobe.login.privacy=We collect anonymous data to improve the experience. By continuing, you agree to our Privacy Policy and Terms of Service. +oobe.login.title=Log In +oobe.login.desc=Register at the official FPSMaster site. oobe.login.username=Username oobe.login.password=Password -oobe.login.register=Register Account -oobe.login.login=Login -oobe.login.skip=Offline Playing +oobe.login.register=Register +oobe.login.login=Log In +oobe.login.skip=Play Offline oobe.login.info=Error Message! oobe.first.title=View Tutorial oobe.first.desc=First time here? -oobe.first.next=Okay +oobe.first.next=Got it oobe.first.skip=Skip -oobe.done.title=Done! -oobe.done.desc=Welcome to use +oobe.done.title=All Set! +oobe.done.desc=Welcome to the client oobe.done.start=Start -microsoft.login.title=Logging into Microsoft Account -microsoft.login.desc=Please go to the browser to continue - -# Function -armordisplay=Armor Display -armordisplay.desc=Display Armor Information -betterchat=Chat Box -betterchat.desc=Improved Chat Box -betterchat.color=Color -betterchat.betterfont=Better Font -combodisplay=Combo Display -combodisplay.desc=Display Combo Count -combodisplay.color=Color -cpsdisplay=Click Speed Display -cpsdisplay.desc=Display Click Speed -cpsdisplay.color=Color -fpsdisplay=Frame Rate Display -fpsdisplay.desc=Display Frame Rate -fpsdisplay.color=Color -hotbar=Item Bar -hotbar.desc=Improved Item Bar -keystrokes=Key Display -keystrokes.desc=Display Keys -keystrokes.color=Color +microsoft.login.title=Logging in with Microsoft... + +# Modules +armordisplay=Armor HUD +armordisplay.desc=Displays equipped armor durability +armordisplay.round=Rounded Corners +armordisplay.backgroundcolor=Background Color +armordisplay.fontshadow=Font Shadow +armordisplay.betterfont=Clean Font +armordisplay.mode=Display Mode +armordisplay.mode.simplehoriz=Simple Horizontal +armordisplay.mode.simplevertical=Simple Vertical +armordisplay.mode.vertical=Detailed Vertical +armordisplay.roundradius=Corner Radius +armordisplay.background=Show Background + +betterchat=Chat Customizer +betterchat.desc=Customize the chat background, font, and animations +betterchat.color=Text Color +betterchat.backgroundcolor=Background Color +betterchat.fontshadow=Font Shadow +betterchat.betterfont=Clean Font +betterchat.roundradius=Corner Radius +betterchat.background=Show Background + +combodisplay=Combo Counter +combodisplay.desc=Displays current combo count +combodisplay.textcolor=Text Color +combodisplay.round=Rounded Corners +combodisplay.backgroundcolor=Background Color +combodisplay.fontshadow=Font Shadow +combodisplay.betterfont=Clean Font +combodisplay.roundradius=Corner Radius +combodisplay.background=Show Background + +cpsdisplay=CPS Counter +cpsdisplay.desc=Displays Clicks Per Second +cpsdisplay.textcolor=Text Color +cpsdisplay.round=Rounded Corners +cpsdisplay.backgroundcolor=Background Color +cpsdisplay.fontshadow=Font Shadow +cpsdisplay.betterfont=Clean Font +cpsdisplay.roundradius=Corner Radius +cpsdisplay.background=Show Background + +fpsdisplay=FPS Counter +fpsdisplay.desc=Displays Frames Per Second +fpsdisplay.textcolor=Text Color +fpsdisplay.roundradius=Corner Radius +fpsdisplay.background=Show Background +fpsdisplay.round=Rounded Corners +fpsdisplay.backgroundcolor=Background Color +fpsdisplay.fontshadow=Font Shadow +fpsdisplay.betterfont=Clean Font + +minimap=Minimap +minimap.desc=Minimap overlay + +hotbar=Hotbar +hotbar.desc=Enhanced hotbar visuals + +keystrokes=Keystrokes +keystrokes.desc=Displays pressed keys on screen +keystrokes.textcolor=Text Color keystrokes.pressedcolor=Pressed Color -keystrokes.rounded=Rounded +keystrokes.round=Rounded Corners +keystrokes.backgroundcolor=Background Color +keystrokes.fontshadow=Font Shadow +keystrokes.betterfont=Clean Font +keystrokes.roundradius=Corner Radius +keystrokes.background=Show Background + +potiondisplay=Potion HUD +potiondisplay.desc=Displays active potion effects +potiondisplay.textcolor=Text Color +potiondisplay.round=Rounded Corners +potiondisplay.backgroundcolor=Background Color +potiondisplay.fontshadow=Font Shadow +potiondisplay.betterfont=Clean Font +potiondisplay.roundradius=Corner Radius +potiondisplay.background=Show Background + +pingdisplay=Ping Display +pingdisplay.desc=Shows your ping to the server +pingdisplay.textcolor=Text Color +pingdisplay.round=Rounded Corners +pingdisplay.backgroundcolor=Background Color +pingdisplay.fontshadow=Font Shadow +pingdisplay.betterfont=Clean Font +pingdisplay.roundradius=Corner Radius +pingdisplay.background=Show Background -potiondisplay=Potion Display -potiondisplay.desc=Display Current Potion Effects -potiondisplay.color=Background Color reachdisplay=Reach Display -reachdisplay.desc=Display Attack Distance +reachdisplay.desc=Displays hit distance on attack +reachdisplay.round=Rounded Corners +reachdisplay.backgroundcolor=Background Color +reachdisplay.fontshadow=Font Shadow +reachdisplay.betterfont=Clean Font +reachdisplay.roundradius=Corner Radius +reachdisplay.textcolor=Text Color +reachdisplay.background=Show Background + scoreboard=Scoreboard -scoreboard.desc=Improved Scoreboard -scoreboard.color=Color -scoreboard.score=Score in Red +scoreboard.desc=Customize the scoreboard +scoreboard.textcolor=Text Color +scoreboard.score=Score Color +scoreboard.round=Rounded Corners +scoreboard.backgroundcolor=Background Color +scoreboard.fontshadow=Font Shadow +scoreboard.betterfont=Clean Font +scoreboard.roundradius=Corner Radius +scoreboard.background=Show Background + performance=Performance -performance.desc=Optimize MC Frame Rate +performance.desc=Optimize FPS performance.entitiesoptimize=Entity Rendering Optimization -performance.fastcloud=Cloud Rendering Optimization -performance.fastrender=Use Fast Rendering -performance.fastload=Fast Load -performance.fpslimit=FPS Limit when Out of Focus +performance.fastcloud=Fast Clouds +performance.fastrender=Fast Render +performance.fastload=Fast World Loading +performance.fpslimit=Limit FPS When Unfocused performance.entitylimit=Entity Limit -performance.ignorestands=Ignore Armor Stand +performance.ignorestands=Ignore Armor Stands performance.particleslimit=Particle Limit performance.screenshot=Screenshot Method performance.screenshot.fast=Fast performance.screenshot.vanilla=Vanilla -fullbright=Keep Brightness -fullbright.desc=Keep Brightness +performance.blur=UI Gaussian Blur +performance.fontoptimize=Font Optimization +performance.staticparticlecolor=Static Particle Color +performance.limitchunks=Chunk Load Limit +performance.chunkupdatelimit=Chunk Update Limit + +fullbright=Fullbright +fullbright.desc=Keep brightness at max + itemphysics=Item Physics -itemphysics.desc=Add Physical Effects to Drop Items -moreparticles=More Particles -moreparticles.desc=Add More Attack Particles -moreparticles.sharpness=Sharp Particles -moreparticles.alwayssharpness=Always Show More Sharp Particles -moreparticles.crit=Critical Hit Particles -moreparticles.alwayscrit=Always Show More Critical Hit Particles +itemphysics.desc=Adds realistic item animations + +moreparticles=Extra Particles +moreparticles.desc=Add more hit particles +moreparticles.sharpness=Sharpness Particles +moreparticles.alwayssharpness=Always Show Sharpness +moreparticles.crit=Critical Particles +moreparticles.alwayscrit=Always Show Criticals moreparticles.special=Special Particles -moreparticles.special.none=No Effects -moreparticles.special.heart=Heart -moreparticles.special.flame=Flame +moreparticles.special.none=None +moreparticles.special.heart=Hearts +moreparticles.special.flame=Flames +moreparticles.special.blood=Blood moreparticles.special.damageindicator=Damage -moreparticles.killeffect.none=No Effects +moreparticles.killeffect.none=None moreparticles.killeffect.lightning=Lightning moreparticles.killeffect.explosion=Explosion moreparticles.killeffect=Kill Effect + motionblur=Motion Blur -motionblur.desc=Motion Blur -motionblur.multiplier=Motion Blur Multiplier -motionblur.mode=Motion Blur Mode -motionblur.mode.classic=Classic -motionblur.mode.new=New -motionblur.fastrender=Caution! MotionBlur is not compatible with FastRender, we has disabled it automatically. -sprint=Force Sprint -sprint.desc=Keep Sprinting -musicdisplay=Music Display -musicdisplay.desc=Display the Music you are Playing -musicdisplay.backgroundcolor=Song Display Background Color -musicdisplay.progresscolor=Song Display Progress Bar Color -musicdisplay.visual=Audio Visualization Color -musicdisplay.amplitude=Visual Amplitude +motionblur.desc=Adds motion blur +motionblur.strength=Blur Strength +motionblur.mode=Blur Mode +motionblur.mode.old=Classic +motionblur.mode.new=Modern +motionblur.fastrender=Warning! Motion Blur is not compatible with Fast Render. Fast Render has been disabled. + +sprint=Toggle Sprint +sprint.desc=Stay sprinting at all times +sprint.togglesprint=Toggle Sprint +sprint.betterfont=Clean Font + +musicdisplay=Music HUD +musicdisplay.desc=Displays current playing music +musicdisplay.backgroundcolor=Background Color +musicdisplay.progresscolor=Progress Bar Color +musicdisplay.visual=Visualizer Color +musicdisplay.amplitude=Visualizer Strength +musicdisplay.roundradius=Corner Radius +musicdisplay.round=Rounded Corners +musicdisplay.betterfont=Clean Font +musicdisplay.background=Show Background + oldanimations=Old Animations -oldanimations.desc=Old Animations -oldanimations.noshield=Do not Display Shield -oldanimations.oldrod=Old Fishing Rod +oldanimations.desc=Revert to old 1.7 animations +oldanimations.noshield=Hide Shield +oldanimations.oldrod=Old Rod oldanimations.oldbow=Old Bow oldanimations.oldswing=Old Swing -oldanimations.oldblock=Old Block -oldanimations.olddamage=Old Damage Animation -oldanimations.oldusing=Old Usage Animation -oldanimations.blockhit=Blocking Hand Swing +oldanimations.blockswing=Block Swing +oldanimations.oldblock=Old Blocking +oldanimations.olddamage=Old Damage Anim +oldanimations.oldusing=Old Use Anim +oldanimations.blockhit=Block Hit oldanimations.x=X oldanimations.y=Y oldanimations.z=Z -oldanimations.blockx=Blocking X -oldanimations.blocky=Blocking Y -oldanimations.blockz=Blocking Z +oldanimations.scale=Scale +oldanimations.blockx=Block X +oldanimations.blocky=Block Y +oldanimations.blockz=Block Z +oldanimations.animationmode=Blocking Animation +oldanimations.animationsneak=Sneak Animation +oldanimations.animationmode.1.7=1.7 +oldanimations.animationmode.lunar=Lunar +oldanimations.animationmode.swang=Swang +oldanimations.animationmode.sigma=Sigma +oldanimations.animationmode.swank=Swank +oldanimations.animationmode.swong=Swong +oldanimations.animationmode.debug=Debug +oldanimations.animationmode.luna=Luna +oldanimations.animationmode.jigsaw=Jigsaw +oldanimations.animationmode.jello=Jello +oldanimations.animationmode.push=Push + +irc=Client Chat +irc.desc=Chat with users using the same client +irc.enable=IRC enabled. Type %sirc to chat +irc.showmates=Show client users + hitcolor=Hit Color -hitcolor.desc=Hit Color +hitcolor.desc=Color on hit hitcolor.color=Color + hideindicator=Hide Attack Indicator -hideindicator.desc=Hide Attack Indicator +hideindicator.desc=Hides the attack cooldown bar + lyricsdisplay=Lyrics Display -lyricsdisplay.desc=Lyrics Display -lyricsdisplay.color=Lyrics Color -lyricsdisplay.bgcolor=Unplayed Lyrics Color -crosshair=Crosshair -crosshair.desc=Customized Crosshair -crosshair.dynamic=Dynamic Range +lyricsdisplay.desc=Show synced lyrics +lyricsdisplay.textcolor=Active Line Color +lyricsdisplay.textcolorbg=Inactive Line Color +lyricsdisplay.round=Rounded Corners +lyricsdisplay.backgroundcolor=Background Color +lyricsdisplay.fontshadow=Font Shadow +lyricsdisplay.betterfont=Clean Font +lyricsdisplay.roundradius=Corner Radius +lyricsdisplay.background=Show Background + +crosshair=Custom Crosshair +crosshair.desc=Replaces the default crosshair +crosshair.dynamic=Dynamic crosshair.outline=Outline -crosshair.outlinewidth=Outline Length +crosshair.outlinewidth=Outline Width crosshair.outlinecolor=Outline Color crosshair.length=Length crosshair.width=Thickness @@ -166,97 +289,212 @@ crosshair.color=Color crosshair.dot=Dot crosshair.enemy=Enemy Color crosshair.friend=Friend Color + firemodifier=Fire Modifier -firemodifier.desc=Fire Modifier +firemodifier.desc=Change vanilla fire overlay firemodifier.height=Height firemodifier.customcolor=Custom Color firemodifier.color=Color -freelook=Free Look -freelook.desc=Free Look -freelook.bind=Shortcut Key -blockoverlay=Block Highlight -blockoverlay.desc=Highlight the Block you are Aiming at + +freelook=Freelook +freelook.desc=Look around freely without rotating player +freelook.bind=Keybind + +blockoverlay=Block Overlay +blockoverlay.desc=Highlight targeted blocks blockoverlay.fill=Fill blockoverlay.fillcolor=Fill Color blockoverlay.outline=Outline blockoverlay.outlinecolor=Outline Color blockoverlay.throughblock=Through Block blockoverlay.width=Outline Width + timechanger=Time Changer -timechanger.desc=Change Time +timechanger.desc=Change world time timechanger.time=Time + tnttimer=TNT Timer -tnttimer.desc=Display TNT Explosion Time +tnttimer.desc=Displays time before TNT explodes +tnttimer.duration=TNT Duration + hitboxes=Hitboxes -hitboxes.desc=Display Hitboxes +hitboxes.desc=Show hitboxes hitboxes.color=Color -customfov=Field of View -customfov.desc=Customized Field of View + +customfov=Custom FOV +customfov.desc=Modify FOV for different actions customfov.nospeedfov=No Speed FOV Change -customfov.noflyfov=No Flying FOV Change +customfov.noflyfov=No Fly FOV Change customfov.nobowfov=No Bow FOV Change + nametags=Name Tags -nametags.desc=Customized Name Tags -nametags.showself=Display Your Own Name Tag -nametags.rankmode=Rank Mode -nametags.rankmode.none=Don't Display -nametags.rankmode.bedwars=Bed Wars -nametags.rankmode.bedwars-xp=Unlimited Firepower -nametags.rankmode.skywars=Sky Wars -nametags.rankmode.kit=Professional War -taboverlay=Tab Display -taboverlay.desc=Customized Tab Display -taboverlay.showping=Display Latency -preventbanning=Reduce False Positives in Huayueting -preventbanning.desc=Reduce the probability of false positives in Huayueting by cancelling some anti-hacking methods -preventbanning.mode=Mode -preventbanning.mode.falling=Falling -preventbanning.mode.air=Air -preventbanning.mode.all=All +nametags.desc=Custom name tag visuals +nametags.showself=Show Own Nametag +nametags.health=Show Health + +taboverlay=Tab Overlay +taboverlay.desc=Customize the tab list +taboverlay.showping=Show Ping + inventorydisplay=Inventory Display -inventorydisplay.desc=Display Inventory +inventorydisplay.desc=Show inventory items on screen +inventorydisplay.round=Rounded Corners +inventorydisplay.backgroundcolor=Background Color +inventorydisplay.roundradius=Corner Radius +inventorydisplay.background=Show Background + playerdisplay=Player Display -playerdisplay.desc=Display Nearby Players' Information -targetdisplay=Target Display -targetdisplay.desc=Display Target Information -targetdisplay.targetesp=Display Target ESP +playerdisplay.desc=Show nearby player info +playerdisplay.round=Rounded Corners +playerdisplay.backgroundcolor=Background Color +playerdisplay.fontshadow=Font Shadow +playerdisplay.betterfont=Clean Font +playerdisplay.roundradius=Corner Radius +playerdisplay.background=Show Background + +targetdisplay=Target HUD +targetdisplay.desc=Show information about target +targetdisplay.targetesp=Target ESP targetdisplay.targetesp.glow=Glow -targetdisplay.targetesp.none=No Display -targetdisplay.targethud=Target Display -targetdisplay.targethud.none=No Display +targetdisplay.targetesp.none=None +targetdisplay.targethud=Target HUD +targetdisplay.targethud.none=None targetdisplay.targethud.simple=Simple targetdisplay.espcolor=ESP Color -minimizedbobbing=Minimized Bobbing -minimizedbobbing.desc=Stop Global Bobbing +targetdisplay.roundradius=Corner Radius +targetdisplay.background=Show Background +targetdisplay.omitname=Omit Long Names + +minimizedbobbing=No Bobbing +minimizedbobbing.desc=Removes all screen shake + smoothzoom=Smooth Zoom -smoothzoom.desc=Make Zoom Process Smooth -smoothzoom.speed=Speed -smoothzoom.speed.desc=Smooth Speed of Zoom Process -protocol=Protocol -protocol.desc=Huayueting Communication Protocol -protocol.bypass=Bypass Open End Detection -protocol.chestfix=Chest Fix -skinchanger=Skin Modifier +smoothzoom.desc=Smooth zooming +smoothzoom.smoothzoom=Enable Smooth Zoom +smoothzoom.speed=Zoom Speed +smoothzoom.zoombind=Zoom Keybind +smoothzoom.smoothmouse=Smooth Mouse Input + +skinchanger=Skin Changer skinchanger.skin=Skin Name -skinchanger.desc=Skin Modifier -nohurtcam=No Hurt Cam -nohurtcam.desc=Remove Hurt View Shaking +skinchanger.desc=Change your client skin + +nohurtcam=No Hurtcam +nohurtcam.desc=Disable damage camera shake + nameprotect=Name Protect -nameprotect.desc=Not Showing Real Name +nameprotect.desc=Hide your real in-game name nameprotect.name=Fake Name +chatbot=Chat Bot +chatbot.desc=Use LLM for automated replies +chatbot.mode=Mode +chatbot.mode.internal=Built-in +chatbot.mode.custom=Custom +chatbot.maxcontext=Max Context +chatbot.apikey=API Key +chatbot.model=Model +chatbot.apiurl=API URL +chatbot.prompt=Prompt +chatbot.responddelay=Response Delay +chatbot.cooldown=Cooldown +chatbot.regex=Regex +chatbot.ignoreself=Ignore Self + +translator=Translator +translator.desc=Translate chat by typing "#lang message" + +nohitdelay=No Hit Delay +nohitdelay.desc=Remove click delay after a missed hit + +rawinput=Raw Input +rawinput.desc=Use raw mouse movement + +fixedinventory=Fixed Inventory +fixedinventory.desc=Prevent hotbar from moving with effects + +coordsdisplay=Coords HUD +coordsdisplay.desc=Display your coordinates +coordsdisplay.round=Rounded Corners +coordsdisplay.backgroundcolor=Background Color +coordsdisplay.textcolor=Text Color +coordsdisplay.fontshadow=Font Shadow +coordsdisplay.betterfont=Clean Font +coordsdisplay.limitdisplay=Y Limit Display +coordsdisplay.limitdisplayy=Y Limit +coordsdisplay.roundradius=Corner Radius +coordsdisplay.background=Show Background + +modslist=Mod List +modslist.desc=Show enabled modules +modslist.showtext=Show Custom Text +modslist.text=Custom Text +modslist.english=Use English Names +modslist.color=Mod List Color +modslist.rainbow=Rainbow Text +modslist.backgroundcolor=Background Color +modslist.betterfont=Clean Font +modslist.roundradius=Corner Radius +modslist.background=Show Background +betterscreen=Enhanced UI +betterscreen.desc=Improves vanilla UI visuals +betterscreen.background=Enable Background +betterscreen.backgroundanimation=Background Animation +betterscreen.noflickering=No Flickering -# Category -category.optimize=Optimization +clientcommand=Client Commands +clientcommand.desc=Use commands to control modules + +cheatersdetector=Cheater Detector +cheatersdetector.desc=Detect and tag cheaters +cheatersdetector.autohub=Auto Leave on Cheater +cheatersdetector.autoreport=Auto Report Cheater +cheatersdetector.cloud=Use Shared Hacker List + +clientsettings=Client Settings +clientsettings.desc=General client settings +clientsettings.clickguikey=GUI Hotkey +clientsettings.fixedscale=Fixed GUI Scale +clientsettings.blur=Blur UI Elements +clientsettings.command=Client Command +clientsettings.prefix=Command Prefix + +dragonwings=Dragon Wings +dragonwings.desc=Display dragon wings +dragonwings.colored=Colored Wings +dragonwings.color=Wing Color +dragonwings.scale=Scale +dragonwings.chroma=Chroma + +directiondisplay=Direction HUD +directiondisplay.desc=Display a compass +damageindicator=Damage Indicator +damageindicator.desc=Show damage numbers on hit + +# Categories +category.optimize=Performance category.render=Visual category.utility=Utility category.interface=Interface category.music=Music category.theme=Theme -category.ornament=Ornament +category.ornament=Cosmetics + +# Notifications +notification.module.enable=Module Enabled +notification.module.enable.desc=%s enabled +notification.module.disable=Module Disabled +notification.module.disable.desc=%s disabled +notification.music=Music +notification.music.next=Now Playing: %s -# Others -irc.not_login=§c[IRC] §r§cYou are not connected to IRC, please report this issue or check your network connection. -irc.disconnect=§c[IRC] §r§cYou are disconnected, please reconnect. -special.under_dev=Under development, please wait for version update \ No newline at end of file +# Other +irc.not_login=§c[IRC] §r§cYou're not connected to IRC. Check your connection or report the issue. +irc.disconnect=§c[IRC] §r§cDisconnected. Please reconnect. +special.under_dev=Under development. Wait for future updates. +translate.hover=Click to Translate +command.notfound=Command not found. If the client command affects your chat, disable ClientSettings -> Client Command. +blur.fast_render=UI blur is not compatible with Fast Render. Please disable Fast Render first. +blur.performance=Blur may reduce performance. Disable on low-end PCs! +motionblur.fast_render=Motion Blur is not compatible with Fast Render. Fast Render has been disabled. diff --git a/shared/resources/assets/minecraft/client/lang/zh_cn.lang b/shared/resources/assets/minecraft/client/lang/zh_cn.lang index 4df038af..360b5fb4 100644 --- a/shared/resources/assets/minecraft/client/lang/zh_cn.lang +++ b/shared/resources/assets/minecraft/client/lang/zh_cn.lang @@ -1,7 +1,6 @@ # 界面 mainmenu.single=单人游戏 mainmenu.multi=多人游戏 -mainmenu.proxy=网易代理 mainmenu.settings=设置 mainmenu.notlogin=您未登录,点此登录 mainmenu.welcome=欢迎您,%s @@ -11,7 +10,6 @@ mainmenu.notlatest=您使用的不是最新版本,点此更新! music.title=音乐 music.search=搜索 -music.disabled=音乐功能已关闭,详情查看 fpsmaster.top/faq/music music.name=搜索名称 music.list=搜索歌单ID music.daily=日推 @@ -24,8 +22,6 @@ music.loggedin=已登录 theme.title=主题 theme.dark=暗色 theme.light=亮色 -theme.free=免费 -theme.vip=赞助 oobe.welcome.title=欢迎 oobe.welcome.next=下一步 @@ -50,7 +46,7 @@ microsoft.login.title=正在登录微软账号 # 功能 armordisplay=护甲显示 -armordisplay.desc=显示护甲信息 +armordisplay.desc=显示玩家的护甲信息 armordisplay.round=背景圆角 armordisplay.backgroundcolor=背景颜色 armordisplay.fontshadow=字体阴影 @@ -63,7 +59,7 @@ armordisplay.roundradius=圆角半径 armordisplay.background=背景 betterchat=聊天框 -betterchat.desc=更好的聊天框 +betterchat.desc=修改聊天框的背景、字体,以及添加动画等 betterchat.color=颜色 betterchat.backgroundcolor=背景颜色 betterchat.fontshadow=字体阴影 @@ -82,7 +78,7 @@ combodisplay.roundradius=圆角半径 combodisplay.background=背景 cpsdisplay=点击速度显示 -cpsdisplay.desc=显示点击速度 +cpsdisplay.desc=显示点击速度(CPS) cpsdisplay.textcolor=文字颜色 cpsdisplay.round=背景圆角 cpsdisplay.backgroundcolor=背景颜色 @@ -92,7 +88,7 @@ cpsdisplay.roundradius=圆角半径 cpsdisplay.background=背景 fpsdisplay=帧数显示 -fpsdisplay.desc=显示帧数 +fpsdisplay.desc=显示帧数(FPS) fpsdisplay.textcolor=文字颜色 fpsdisplay.roundradius=圆角半径 fpsdisplay.background=背景 @@ -102,12 +98,13 @@ fpsdisplay.fontshadow=字体阴影 fpsdisplay.betterfont=更好的字体 minimap=小地图 -minimap.desc=显示小地图 +minimap.desc=小地图组件 hotbar=物品栏 hotbar.desc=更好的物品栏 + keystrokes=按键显示 -keystrokes.desc=显示按键 +keystrokes.desc=在屏幕上显示按键情况 keystrokes.textcolor=文字颜色 keystrokes.pressedcolor=按下颜色 keystrokes.round=背景圆角 @@ -118,7 +115,7 @@ keystrokes.roundradius=圆角半径 keystrokes.background=背景 potiondisplay=药水显示 -potiondisplay.desc=显示当前的药水效果 +potiondisplay.desc=显示玩家的药水效果 potiondisplay.textcolor=文字颜色 potiondisplay.round=背景圆角 potiondisplay.backgroundcolor=背景颜色 @@ -128,7 +125,7 @@ potiondisplay.roundradius=圆角半径 potiondisplay.background=背景 pingdisplay=延迟显示 -pingdisplay.desc=显示自己的延迟 +pingdisplay.desc=显示玩家到服务器的延迟(Ping) pingdisplay.textcolor=文字颜色 pingdisplay.round=背景圆角 pingdisplay.backgroundcolor=背景颜色 @@ -138,7 +135,7 @@ pingdisplay.roundradius=圆角半径 pingdisplay.background=背景 reachdisplay=攻击距离显示 -reachdisplay.desc=显示攻击的距离 +reachdisplay.desc=在每次攻击时显示攻击的距离 reachdisplay.round=背景圆角 reachdisplay.backgroundcolor=背景颜色 reachdisplay.fontshadow=字体阴影 @@ -149,7 +146,7 @@ reachdisplay.background=背景 scoreboard=计分板 -scoreboard.desc=更好的计分板 +scoreboard.desc=自定义计分板的样式 scoreboard.textcolor=文字颜色 scoreboard.score=红字 scoreboard.round=背景圆角 @@ -165,8 +162,8 @@ performance.desc=优化MC帧数 performance.entitiesoptimize=实体渲染优化 performance.fastcloud=云渲染优化 performance.fastrender=使用快速渲染 -performance.fastload=快速加载 -performance.fpslimit=失焦FPS限制 +performance.fastload=快速加载世界 +performance.fpslimit=限制客户端失去焦点时的帧数 performance.entitylimit=实体限制 performance.ignorestands=忽略盔甲架 performance.particleslimit=粒子限制 @@ -181,7 +178,7 @@ performance.chunkupdatelimit=区块更新限制 fullbright=保持亮度 -fullbright.desc=保持亮度 +fullbright.desc=保持视野明亮 itemphysics=物品物理 itemphysics.desc=给掉落物添加物理效果 @@ -283,28 +280,28 @@ lyricsdisplay.betterfont=更好的字体 lyricsdisplay.roundradius=圆角半径 lyricsdisplay.background=背景 -crosshair=准星 -crosshair.desc=自定义准心 -crosshair.dynamic=动态范围 -crosshair.outline=描边 +crosshair=自定义准心 +crosshair.desc=使用一个自定义的准星替代原版的准星 +crosshair.dynamic=动态变化 +crosshair.outline=是否描边 crosshair.outlinewidth=描边长度 crosshair.outlinecolor=描边颜色 crosshair.length=长度 crosshair.width=粗细 crosshair.gap=间隔 crosshair.color=颜色 -crosshair.dot=点 -crosshair.enemy=敌对颜色 -crosshair.friend=友好颜色 +crosshair.dot=中心点 +crosshair.enemy=敌对生物颜色 +crosshair.friend=友好生物颜色 firemodifier=火焰修改 -firemodifier.desc=火焰修改 +firemodifier.desc=修改原版的火焰效果 firemodifier.height=高度 firemodifier.customcolor=自定义颜色 firemodifier.color=颜色 freelook=自由视角 -freelook.desc=自由视角 +freelook.desc=可以在不改变玩家朝向的情况下自由移动视角 freelook.bind=快捷键 blockoverlay=方块高亮 @@ -317,7 +314,7 @@ blockoverlay.throughblock=穿透方块 blockoverlay.width=描边宽度 timechanger=时间修改 -timechanger.desc=修改时间 +timechanger.desc=修改世界时间 timechanger.time=时间 tnttimer=TNT时间显示 @@ -328,8 +325,8 @@ hitboxes=碰撞箱 hitboxes.desc=显示碰撞箱 hitboxes.color=颜色 -customfov=视场角 -customfov.desc=自定义视场角 +customfov=自定义视场角 +customfov.desc=修改各个情况下的视场角(FOV) customfov.nospeedfov=没有速度视角变化 customfov.noflyfov=没有飞行视角变化 customfov.nobowfov=没有弓箭视角变化 @@ -338,33 +335,20 @@ nametags=名字标签 nametags.desc=自定义名字标签 nametags.showself=显示自己的名字标签 nametags.health=显示血条 -nametags.rankmode=排名模式 -nametags.rankmode.none=不显示 -nametags.rankmode.bedwars=起床战争 -nametags.rankmode.bedwars-xp=无限火力 -nametags.rankmode.skywars=空岛战争 -nametags.rankmode.kit=职业战争 taboverlay=Tab显示 -taboverlay.desc=自定义Tab显示 -taboverlay.showping=显示延迟 - -preventbanning=减少花雨庭误封 -preventbanning.desc=通过取消一些防砍减少花雨庭误封的概率 -preventbanning.mode=模式 -preventbanning.mode.falling=下坠 -preventbanning.mode.air=空中 -preventbanning.mode.all=所有 +taboverlay.desc=自定义Tab界面 +taboverlay.showping=显示数字延迟 inventorydisplay=物品栏显示 -inventorydisplay.desc=显示物品栏 +inventorydisplay.desc=显示物品栏内物品 inventorydisplay.round=背景圆角 inventorydisplay.backgroundcolor=背景颜色 inventorydisplay.roundradius=圆角半径 inventorydisplay.background=背景 playerdisplay=玩家显示 -playerdisplay.desc=显示附近玩家信息 +playerdisplay.desc=显示附近玩家的信息 playerdisplay.round=背景圆角 playerdisplay.backgroundcolor=背景颜色 playerdisplay.fontshadow=字体阴影 @@ -395,11 +379,6 @@ smoothzoom.speed=速度 smoothzoom.zoombind=快捷键 smoothzoom.smoothmouse=鼠标平滑 -protocol=协议 -protocol.desc=花雨庭通信协议 -protocol.bypass=绕过开端检测 -protocol.chestfix=箱子修复 - skinchanger=皮肤修改器 skinchanger.skin=皮肤名称 skinchanger.desc=皮肤修改器 @@ -473,7 +452,6 @@ betterscreen.noflickering=防止闪烁 clientcommand=客户端命令 clientcommand.desc=使用命令执行客户端功能 - cheatersdetector=作弊者检测 cheatersdetector.desc=检测作弊者并特殊标记 cheatersdetector.autohub=检测到作弊者自动退出 @@ -485,6 +463,7 @@ clientsettings.desc=调整客户端各类设置 clientsettings.clickguikey=设置界面快捷键 clientsettings.fixedscale=固定界面缩放比例 clientsettings.blur=界面组件模糊 +clientsettings.command=客户端命令 clientsettings.prefix=命令前缀 dragonwings=龙翅膀 @@ -521,10 +500,7 @@ irc.not_login=§c[IRC] §r§c您未连接到IRC,请报告本问题或检查网 irc.disconnect=§c[IRC] §r§c您已断开连接,请重新连接。 special.under_dev=正在开发中,请等待版本更新 translate.hover=点此翻译 -command.notfound=未找到命令,如果客户端命令影响了您的消息,请关闭实用->客户端命令 功能。 +command.notfound=未找到命令,如果客户端命令影响了您的消息,请在客户端设置中关闭客户端命令功能。 blur.fast_render=组件模糊与快速渲染不兼容,如要使用模糊效果,请先在设置中关闭快速渲染。 blur.performance=组件模糊会极大影响性能,若您的配置较低则不建议开启! motionblur.fast_render=快速渲染与运动模糊不兼容,已为您自动关闭快速渲染。 - -# 插件 -plugin_manager.title=插件市场 \ No newline at end of file From a4dcc91afe987d701ac8e81cefb7328516bf2672 Mon Sep 17 00:00:00 2001 From: SuperSkidder Date: Mon, 14 Jul 2025 17:25:34 +0800 Subject: [PATCH 083/193] change: fixed scale is default of now --- .../top/fpsmaster/features/impl/interfaces/ClientSettings.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/shared/java/top/fpsmaster/features/impl/interfaces/ClientSettings.java b/shared/java/top/fpsmaster/features/impl/interfaces/ClientSettings.java index 23d2189b..76285315 100644 --- a/shared/java/top/fpsmaster/features/impl/interfaces/ClientSettings.java +++ b/shared/java/top/fpsmaster/features/impl/interfaces/ClientSettings.java @@ -16,7 +16,7 @@ public class ClientSettings extends InterfaceModule { public static BooleanSetting blur = new BooleanSetting("blur", false); public static BindSetting keyBind = new BindSetting("ClickGuiKey", Keyboard.KEY_RSHIFT); - public static BooleanSetting fixedScale = new BooleanSetting("FixedScale", true); + public static BooleanSetting fixedScale = new BooleanSetting("FixedScale", false); public static BooleanSetting clientCommand = new BooleanSetting("Command", true); public static final TextSetting prefix = new TextSetting("prefix", "#", () -> clientCommand.getValue()); From fcd1de05cce282b33f514b81e1ae860de51d819c Mon Sep 17 00:00:00 2001 From: SuperSkidder Date: Mon, 14 Jul 2025 17:28:03 +0800 Subject: [PATCH 084/193] change: remove old theme system feat: changed client configures format to proper json object --- shared/java/top/fpsmaster/FPSMaster.java | 11 -- .../modules/config/ConfigManager.java | 12 +- .../modules/music/IngameOverlay.java | 4 +- .../fpsmaster/ui/click/CategoryComponent.java | 2 +- .../top/fpsmaster/ui/click/MainPanel.java | 32 ++-- .../ui/click/modules/ModuleRenderer.java | 8 +- .../click/modules/impl/BindSettingRender.java | 4 +- .../modules/impl/BooleanSettingRender.java | 2 +- .../modules/impl/ColorSettingRender.java | 8 +- .../click/modules/impl/ModeSettingRender.java | 47 +++--- .../modules/impl/NumberSettingRender.java | 6 +- .../click/modules/impl/TextSettingRender.java | 6 +- .../fpsmaster/ui/click/music/MusicPanel.java | 42 ++--- .../fpsmaster/ui/click/music/SearchBox.java | 12 +- .../fpsmaster/ui/click/themes/DarkTheme.java | 155 ------------------ .../fpsmaster/ui/click/themes/LightTheme.java | 155 ------------------ .../top/fpsmaster/ui/click/themes/Theme.java | 65 -------- .../top/fpsmaster/ui/common/GuiButton.java | 2 +- .../ui/custom/impl/ModsListComponent.java | 2 +- .../ui/custom/impl/MusicComponent.java | 4 +- .../ui/screens/account/GuiWaiting.java | 4 +- .../ui/screens/mainmenu/MenuButton.java | 20 +-- .../ui/screens/oobe/impls/Login.java | 6 +- 23 files changed, 109 insertions(+), 500 deletions(-) delete mode 100644 shared/java/top/fpsmaster/ui/click/themes/DarkTheme.java delete mode 100644 shared/java/top/fpsmaster/ui/click/themes/LightTheme.java delete mode 100644 shared/java/top/fpsmaster/ui/click/themes/Theme.java diff --git a/shared/java/top/fpsmaster/FPSMaster.java b/shared/java/top/fpsmaster/FPSMaster.java index 8e02d68f..11db2504 100644 --- a/shared/java/top/fpsmaster/FPSMaster.java +++ b/shared/java/top/fpsmaster/FPSMaster.java @@ -16,9 +16,6 @@ import top.fpsmaster.modules.music.MusicPlayer; import top.fpsmaster.modules.music.netease.NeteaseApi; import top.fpsmaster.ui.click.music.MusicPanel; -import top.fpsmaster.ui.click.themes.DarkTheme; -import top.fpsmaster.ui.click.themes.LightTheme; -import top.fpsmaster.ui.click.themes.Theme; import top.fpsmaster.ui.custom.ComponentsManager; import top.fpsmaster.ui.screens.oobe.OOBEScreen; import top.fpsmaster.utils.GitInfo; @@ -48,9 +45,6 @@ public class FPSMaster { public static String CLIENT_NAME = "FPSMaster"; public static String CLIENT_VERSION = "v4"; - public static Theme theme = new DarkTheme(); - public static String themeSlot = "dark"; - public static ModuleManager moduleManager = new ModuleManager(); public static FontManager fontManager = new FontManager(); public static ConfigManager configManager = new ConfigManager(); @@ -101,11 +95,6 @@ private void initializeLang() throws FileException { private void initializeConfigures() throws Exception { ClientLogger.info("Initializing Config..."); configManager.loadConfig("default"); - if ("dark".equals(themeSlot)) { - theme = new DarkTheme(); - } else { - theme = new LightTheme(); - } MusicPlayer.setVolume(Float.parseFloat(configManager.configure.getOrCreate("volume", "1"))); NeteaseApi.cookies = FileUtils.readTempValue("cookies"); MusicPanel.nickname = FileUtils.readTempValue("nickname"); diff --git a/shared/java/top/fpsmaster/modules/config/ConfigManager.java b/shared/java/top/fpsmaster/modules/config/ConfigManager.java index 454788ef..8caf12a2 100644 --- a/shared/java/top/fpsmaster/modules/config/ConfigManager.java +++ b/shared/java/top/fpsmaster/modules/config/ConfigManager.java @@ -16,6 +16,7 @@ import top.fpsmaster.utils.os.FileUtils; import java.util.HashMap; +import java.util.Map; public class ConfigManager { @@ -68,8 +69,9 @@ private void readComponents() throws FileException { public void saveConfig(String name) throws FileException { saveComponents(); JsonObject json = new JsonObject(); - json.addProperty("theme", FPSMaster.themeSlot); - json.addProperty("clientConfigure", gson.toJson(configure.configures)); + JsonObject configures = new JsonObject(); + configure.configures.forEach(configures::addProperty); + json.add("clientConfigure", configures); for (Module module : FPSMaster.moduleManager.modules) { JsonObject moduleJson = new JsonObject(); @@ -103,7 +105,6 @@ public void loadConfig(String name) throws Exception { readComponents(); jsonStr = FileUtils.readFile(name + ".json"); JsonObject json = gson.fromJson(jsonStr, JsonObject.class); - FPSMaster.themeSlot = json.get("theme").getAsString(); for (Module module : FPSMaster.moduleManager.modules) { JsonObject moduleJson = json.getAsJsonObject(module.name); @@ -143,7 +144,10 @@ public void loadConfig(String name) throws Exception { } } - configure.configures = gson.fromJson(json.get("clientConfigure").getAsString(), HashMap.class); + JsonObject clientConfigure = json.get("clientConfigure").getAsJsonObject(); + for (Map.Entry element : clientConfigure.entrySet()) { + configure.configures.put(element.getKey(), element.getValue().getAsString()); + } } private void openDefaultModules() { diff --git a/shared/java/top/fpsmaster/modules/music/IngameOverlay.java b/shared/java/top/fpsmaster/modules/music/IngameOverlay.java index 2c5c3a98..cc81cc30 100644 --- a/shared/java/top/fpsmaster/modules/music/IngameOverlay.java +++ b/shared/java/top/fpsmaster/modules/music/IngameOverlay.java @@ -82,14 +82,14 @@ public static void drawSong(float x, float y, float width, float height) { current.name, x + 40, y + 6, - FPSMaster.theme.getTextColorTitle().getRGB() + new Color(234, 234, 234).getRGB() ); FPSMaster.fontManager.s16.drawString( current.author, x + 40, y + 18, - FPSMaster.theme.getTextColorDescription().getRGB() + new Color(162, 162, 162).getRGB() ); } } diff --git a/shared/java/top/fpsmaster/ui/click/CategoryComponent.java b/shared/java/top/fpsmaster/ui/click/CategoryComponent.java index e24550f5..566e4d32 100644 --- a/shared/java/top/fpsmaster/ui/click/CategoryComponent.java +++ b/shared/java/top/fpsmaster/ui/click/CategoryComponent.java @@ -17,7 +17,7 @@ public class CategoryComponent { public CategoryComponent(Category category) { this.category = category; - animationName.setColor(FPSMaster.theme.getCategoryText()); + animationName.setColor(new Color(234, 234, 234)); } public void render(float x, float y, float width, float height, float mouseX, float mouseY, boolean selected) { diff --git a/shared/java/top/fpsmaster/ui/click/MainPanel.java b/shared/java/top/fpsmaster/ui/click/MainPanel.java index 8731dc93..32033701 100644 --- a/shared/java/top/fpsmaster/ui/click/MainPanel.java +++ b/shared/java/top/fpsmaster/ui/click/MainPanel.java @@ -1,6 +1,5 @@ package top.fpsmaster.ui.click; -import net.minecraft.client.gui.ScaledResolution; import net.minecraft.client.renderer.GlStateManager; import net.minecraft.util.ResourceLocation; import org.lwjgl.input.Mouse; @@ -13,12 +12,8 @@ import top.fpsmaster.ui.click.component.ScrollContainer; import top.fpsmaster.ui.click.music.MusicPanel; import top.fpsmaster.ui.click.modules.ModuleRenderer; -import top.fpsmaster.ui.click.music.NewMusicPanel; -import top.fpsmaster.ui.click.themes.DarkTheme; -import top.fpsmaster.ui.click.themes.LightTheme; import top.fpsmaster.utils.math.animation.Animation; import top.fpsmaster.utils.math.animation.AnimationUtils; -import top.fpsmaster.utils.math.animation.ColorAnimation; import top.fpsmaster.utils.math.animation.Type; import top.fpsmaster.utils.render.Render2DUtils; import top.fpsmaster.utils.render.ScaledGuiScreen; @@ -110,7 +105,7 @@ public void render(int mouseX, int mouseY, float partialTicks) { GL11.glEnable(GL11.GL_SCISSOR_TEST); Render2DUtils.doGlScissor( - x, y+10, width, + x, y + 10, width, (height - 18), scaleFactor ); @@ -169,7 +164,7 @@ public void render(int mouseX, int mouseY, float partialTicks) { categoryAnimation, 140, 14, - new Color(0,0,0,200).getRGB() + new Color(0, 0, 0, 200).getRGB() ); float my = y + 60; @@ -226,9 +221,6 @@ public void updateScreen() { public void initGui() { super.initGui(); aiChatPanel.init(); - ScaledResolution sr = new ScaledResolution(mc); - int scaledWidth = sr.getScaledWidth(); - int scaledHeight = sr.getScaledHeight(); scaleAnimation.fstart(0.8, 1.0, 0.2f, Type.EASE_IN_OUT_QUAD); close = false; @@ -237,10 +229,8 @@ public void initGui() { // height = scaledHeight / 2f; // } - if (x == -1 || y == -1) { - x = (int) ((scaledWidth - width) / 2); - y = (int) ((scaledHeight - height) / 2); - } + x = (int) ((guiWidth - width) / 2); + y = (int) ((guiHeight - height) / 2); categories.clear(); for (Category c : Category.values()) { @@ -287,13 +277,13 @@ public void onClick(int mouseX, int mouseY, int mouseButton) { aiChatPanel.click(mouseX, mouseY, mouseButton); if (!Render2DUtils.isHoveredWithoutScale(x, y, width, height, mouseX, mouseY)) return; - if (mouseButton == 0 && Render2DUtils.isHoveredWithoutScale( - x + leftWidth, y, width - leftWidth, 20f, mouseX, mouseY - )) { - drag = true; - dragX = mouseX - x; - dragY = mouseY - y; - } +// if (mouseButton == 0 && Render2DUtils.isHoveredWithoutScale( +// x + leftWidth, y, width - leftWidth, 20f, mouseX, mouseY +// )) { +// drag = true; +// dragX = mouseX - x; +// dragY = mouseY - y; +// } // if (mouseButton == 0 && Render2DUtils.isHoveredWithoutScale( // x + width - 20, y + height - 20, 20f, 20f, mouseX, mouseY diff --git a/shared/java/top/fpsmaster/ui/click/modules/ModuleRenderer.java b/shared/java/top/fpsmaster/ui/click/modules/ModuleRenderer.java index 86d9c7fc..98ad7cc0 100644 --- a/shared/java/top/fpsmaster/ui/click/modules/ModuleRenderer.java +++ b/shared/java/top/fpsmaster/ui/click/modules/ModuleRenderer.java @@ -37,7 +37,7 @@ public class ModuleRenderer extends ValueRender { public ModuleRenderer(Module mod) { this.mod = mod; - content = new ColorAnimation(mod.isEnabled() ? FPSMaster.theme.getModuleEnabled() : FPSMaster.theme.getModuleDisabled()); + content = new ColorAnimation(mod.isEnabled() ? new Color(66, 66, 66) : new Color(40, 40, 40)); mod.settings.forEach(new Consumer>() { @Override public void accept(Setting setting) { @@ -68,11 +68,11 @@ public void render(float x, float y, float width, float height, float mouseX, fl option.update(); if (mod.isEnabled()) { - content.start(content.getColor(), FPSMaster.theme.getModuleTextEnabled(), 0.2f, Type.EASE_IN_OUT_QUAD); + content.start(content.getColor(), new Color(255, 255, 255), 0.2f, Type.EASE_IN_OUT_QUAD); option.start(option.getColor(), new Color(89, 101, 241), 0.2f, Type.EASE_IN_OUT_QUAD); optionX = (float) AnimationUtils.base(optionX, 10, 0.2f); } else { - content.start(content.getColor(), FPSMaster.theme.getModuleTextDisabled(), 0.2f, Type.EASE_IN_OUT_QUAD); + content.start(content.getColor(), new Color(156, 156, 156), 0.2f, Type.EASE_IN_OUT_QUAD); option.start(option.getColor(), new Color(255, 255, 255), 0.2f, Type.EASE_IN_OUT_QUAD); optionX = (float) AnimationUtils.base(optionX, 0, 0.2f); } @@ -159,7 +159,7 @@ public void render(float x, float y, float width, float height, float mouseX, fl FPSMaster.i18n.get(mod.name.toLowerCase(Locale.getDefault()) + ".desc"), x + 40, y + 20, - FPSMaster.theme.getTextColorDescription().getRGB() + new Color(162, 162, 162).getRGB() ); float settingsHeight = 0f; diff --git a/shared/java/top/fpsmaster/ui/click/modules/impl/BindSettingRender.java b/shared/java/top/fpsmaster/ui/click/modules/impl/BindSettingRender.java index a44e3016..54411816 100644 --- a/shared/java/top/fpsmaster/ui/click/modules/impl/BindSettingRender.java +++ b/shared/java/top/fpsmaster/ui/click/modules/impl/BindSettingRender.java @@ -26,7 +26,7 @@ public BindSettingRender(Module module, BindSetting setting) { public void render(float x, float y, float width, float height, float mouseX, float mouseY, boolean custom) { float fw = FPSMaster.fontManager.s16.drawString( FPSMaster.i18n.get((mod.name + "." + setting.name).toLowerCase(Locale.getDefault())), - x + 10, y + 2, FPSMaster.theme.getTextColorTitle().getRGB() + x + 10, y + 2, new Color(234, 234, 234).getRGB() ); String keyName = Keyboard.getKeyName(setting.getValue()); UFontRenderer s16b = FPSMaster.fontManager.s16; @@ -41,7 +41,7 @@ public void render(float x, float y, float width, float height, float mouseX, fl ); } Render2DUtils.drawOptimizedRoundedRect(x + 15 + fw, y, width1, 12f, colorAnimation.getColor()); - s16b.drawString(keyName, x + 18 + fw, y + 2, FPSMaster.theme.getTextColorTitle().getRGB()); + s16b.drawString(keyName, x + 18 + fw, y + 2, new Color(234, 234, 234).getRGB()); if (MainPanel.bindLock.equals(setting.name)) { colorAnimation.base(new Color(255,255,255,80)); } else { diff --git a/shared/java/top/fpsmaster/ui/click/modules/impl/BooleanSettingRender.java b/shared/java/top/fpsmaster/ui/click/modules/impl/BooleanSettingRender.java index 3c865a0a..42283836 100644 --- a/shared/java/top/fpsmaster/ui/click/modules/impl/BooleanSettingRender.java +++ b/shared/java/top/fpsmaster/ui/click/modules/impl/BooleanSettingRender.java @@ -32,7 +32,7 @@ public void render(float x, float y, float width, float height, float mouseX, fl Render2DUtils.drawOptimizedRoundedRect(x + 14, y + 3, 6f, 6f, 3, box.getColor().getRGB()); FPSMaster.fontManager.s16.drawString( FPSMaster.i18n.get((mod.name + "." + setting.name).toLowerCase(Locale.getDefault())), - x + 26, y + 1, FPSMaster.theme.getTextColorDescription().getRGB() + x + 26, y + 1, new Color(162, 162, 162).getRGB() ); this.height = 12f; } diff --git a/shared/java/top/fpsmaster/ui/click/modules/impl/ColorSettingRender.java b/shared/java/top/fpsmaster/ui/click/modules/impl/ColorSettingRender.java index 269f04b7..6cf51324 100644 --- a/shared/java/top/fpsmaster/ui/click/modules/impl/ColorSettingRender.java +++ b/shared/java/top/fpsmaster/ui/click/modules/impl/ColorSettingRender.java @@ -35,16 +35,16 @@ public void render( ) { float tW = FPSMaster.fontManager.s16.drawString( FPSMaster.i18n.get((mod.name + "." + setting.name).toLowerCase(Locale.getDefault())), - x + 10, y + 3, FPSMaster.theme.getTextColorDescription().getRGB() + x + 10, y + 3, new Color(162, 162, 162).getRGB() ); - Render2DUtils.drawOptimizedRoundedRect(x + tW + 26, y + 1, 80f, 14f, FPSMaster.theme.getBackground()); + Render2DUtils.drawOptimizedRoundedRect(x + tW + 26, y + 1, 80f, 14f, new Color(39, 39, 39)); CustomColor customColor = setting.getValue(); Render2DUtils.drawOptimizedRoundedRect(x + tW + 27, y + 2, 12f, 12f, customColor.getRGB()); FPSMaster.fontManager.s16.drawString( "#" + Integer.toHexString(setting.getRGB()).toUpperCase(Locale.getDefault()), - x + tW + 44, y + 2, FPSMaster.theme.getTextColorTitle().getRGB() + x + tW + 44, y + 2, new Color(234, 234, 234).getRGB() ); if (aHeight > 1) { @@ -155,7 +155,7 @@ public void mouseClick( ) { float tW = FPSMaster.fontManager.s16.drawString( FPSMaster.i18n.get((mod.name + "." + setting.name).toLowerCase(Locale.getDefault())), - x + 10, y + 2, FPSMaster.theme.getTextColorDescription().getRGB() + x + 10, y + 2, new Color(162, 162, 162).getRGB() ); if (Render2DUtils.isHovered(x + tW + 26, y + 1, 80f, 14f, (int) mouseX, (int) mouseY) && btn == 0) { expand = !expand; diff --git a/shared/java/top/fpsmaster/ui/click/modules/impl/ModeSettingRender.java b/shared/java/top/fpsmaster/ui/click/modules/impl/ModeSettingRender.java index 678998f9..7a433646 100644 --- a/shared/java/top/fpsmaster/ui/click/modules/impl/ModeSettingRender.java +++ b/shared/java/top/fpsmaster/ui/click/modules/impl/ModeSettingRender.java @@ -9,6 +9,7 @@ import top.fpsmaster.utils.math.animation.AnimationUtils; import top.fpsmaster.utils.render.Render2DUtils; +import java.awt.*; import java.util.Locale; public class ModeSettingRender extends SettingRender { @@ -23,22 +24,22 @@ public ModeSettingRender(Module mod, ModeSetting setting) { @Override public void render(float x, float y, float width, float height, float mouseX, float mouseY, boolean custom) { float fw = FPSMaster.fontManager.s16.drawString( - FPSMaster.i18n.get((mod.name + "." + setting.name).toLowerCase(Locale.getDefault())), - x + 10, y + 8, FPSMaster.theme.getTextColorDescription().getRGB() + FPSMaster.i18n.get((mod.name + "." + setting.name).toLowerCase(Locale.getDefault())), + x + 10, y + 8, new Color(162, 162, 162).getRGB() ); float maxWidth = 80f; Render2DUtils.drawOptimizedRoundedBorderRect( - x + 16 + fw, - y + 4, - maxWidth, - 16 + expandH, - 0.5f, - FPSMaster.theme.getModeBox(), - FPSMaster.theme.getModeBoxBorder() + x + 16 + fw, + y + 4, + maxWidth, + 16 + expandH, + 0.5f, + new Color(52, 52, 52), + new Color(255, 255, 255, 50) ); FPSMaster.fontManager.s18.drawString( - FPSMaster.i18n.get((mod.name + "." + setting.name + "." + setting.getModeName()).toLowerCase(Locale.getDefault())), - x + 20 + fw, y + 7, FPSMaster.theme.getTextColorTitle().getRGB() + FPSMaster.i18n.get((mod.name + "." + setting.name + "." + setting.getModeName()).toLowerCase(Locale.getDefault())), + x + 20 + fw, y + 7, new Color(234, 234, 234).getRGB() ); // Rotate this icon @@ -48,12 +49,12 @@ public void render(float x, float y, float width, float height, float mouseX, fl GL11.glRotatef(rotatePercent * 180, 0f, 0f, 1f); GL11.glTranslatef(-(x + 16 + fw + maxWidth - 12), -(y + 12), 0f); Render2DUtils.drawImage( - new ResourceLocation("client/gui/settings/icons/arrow.png"), - x + 16 + fw + maxWidth - 16, - y + 8, - 8f, - 8f, - FPSMaster.theme.getTextColorTitle() + new ResourceLocation("client/gui/settings/icons/arrow.png"), + x + 16 + fw + maxWidth - 16, + y + 8, + 8f, + 8f, + new Color(234, 234, 234) ); GL11.glPopMatrix(); if (expand) { @@ -61,13 +62,13 @@ public void render(float x, float y, float width, float height, float mouseX, fl for (int i = 1; i <= setting.getModesSize(); i++) { if (Render2DUtils.isHovered(x + 20 + fw, y + 4 + i * 14, maxWidth, 16f, (int) mouseX, (int) mouseY)) { FPSMaster.fontManager.s16.drawString( - FPSMaster.i18n.get((mod.name + "." + setting.name + "." + setting.getMode(i)).toLowerCase(Locale.getDefault())), - x + 20 + fw, y + 7 + i * 14, FPSMaster.theme.getTextColorDescriptionHover().getRGB() + FPSMaster.i18n.get((mod.name + "." + setting.name + "." + setting.getMode(i)).toLowerCase(Locale.getDefault())), + x + 20 + fw, y + 7 + i * 14, new Color(182, 182, 182).getRGB() ); } else { FPSMaster.fontManager.s16.drawString( - FPSMaster.i18n.get((mod.name + "." + setting.name + "." + setting.getMode(i)).toLowerCase(Locale.getDefault())), - x + 20 + fw, y + 7 + i * 14, FPSMaster.theme.getTextColorDescription().getRGB() + FPSMaster.i18n.get((mod.name + "." + setting.name + "." + setting.getMode(i)).toLowerCase(Locale.getDefault())), + x + 20 + fw, y + 7 + i * 14, new Color(162, 162, 162).getRGB() ); } } @@ -80,8 +81,8 @@ public void render(float x, float y, float width, float height, float mouseX, fl @Override public void mouseClick(float x, float y, float width, float height, float mouseX, float mouseY, int btn) { float fw = FPSMaster.fontManager.s16.drawString( - FPSMaster.i18n.get((mod.name + "." + setting.name).toLowerCase(Locale.getDefault())), - x + 10, y + 8, FPSMaster.theme.getTextColorDescription().getRGB() + FPSMaster.i18n.get((mod.name + "." + setting.name).toLowerCase(Locale.getDefault())), + x + 10, y + 8, new Color(162, 162, 162).getRGB() ); float maxWidth = 80f; if (Render2DUtils.isHovered(x + 16 + fw, y + 4, maxWidth, 16f, (int) mouseX, (int) mouseY)) { diff --git a/shared/java/top/fpsmaster/ui/click/modules/impl/NumberSettingRender.java b/shared/java/top/fpsmaster/ui/click/modules/impl/NumberSettingRender.java index a3dffa9b..c0169daa 100644 --- a/shared/java/top/fpsmaster/ui/click/modules/impl/NumberSettingRender.java +++ b/shared/java/top/fpsmaster/ui/click/modules/impl/NumberSettingRender.java @@ -26,7 +26,7 @@ public NumberSettingRender(Module mod, NumberSetting setting) { public void render(float x, float y, float width, float height, float mouseX, float mouseY, boolean custom) { float fw = FPSMaster.fontManager.s16.drawString( FPSMaster.i18n.get((mod.name + "." + setting.name).toLowerCase(Locale.getDefault())), - x + 10, y + 2, FPSMaster.theme.getTextColorDescription().getRGB() + x + 10, y + 2, new Color(162, 162, 162).getRGB() ); Render2DUtils.drawOptimizedRoundedRect(x + 16 + fw, y + 3, 160f, 6f, new Color(0,0,0,80)); float percent = (setting.getValue().floatValue() - setting.min.floatValue()) / (setting.max.floatValue() - setting.min.floatValue()); @@ -36,7 +36,7 @@ public void render(float x, float y, float width, float height, float mouseX, fl setting.getValue().toString(), x + fw + 20 + 160, y + 2, - FPSMaster.theme.getTextNumber().getRGB() + new Color(128, 128, 128).getRGB() ); if (!Mouse.isButtonDown(0)) MainPanel.dragLock = "null"; if (MainPanel.dragLock.equals(mod.name + setting.name + 4)) { @@ -54,7 +54,7 @@ public void render(float x, float y, float width, float height, float mouseX, fl public void mouseClick(float x, float y, float width, float height, float mouseX, float mouseY, int btn) { float fw = FPSMaster.fontManager.s16.drawString( FPSMaster.i18n.get((mod.name + "." + setting.name).toLowerCase(Locale.getDefault())), - x + 10, y + 2, FPSMaster.theme.getTextColorDescription().getRGB() + x + 10, y + 2, new Color(182, 182, 182).getRGB() ); if (Render2DUtils.isHovered(x + 16 + fw, y, 160f, height, (int) mouseX, (int) mouseY) && Mouse.isButtonDown(0)) { if (btn == 0 && MainPanel.dragLock.equals("null")) { diff --git a/shared/java/top/fpsmaster/ui/click/modules/impl/TextSettingRender.java b/shared/java/top/fpsmaster/ui/click/modules/impl/TextSettingRender.java index 861c7099..ef5319ac 100644 --- a/shared/java/top/fpsmaster/ui/click/modules/impl/TextSettingRender.java +++ b/shared/java/top/fpsmaster/ui/click/modules/impl/TextSettingRender.java @@ -22,10 +22,10 @@ public TextSettingRender(Module mod, TextSetting setting) { @Override public void render(float x, float y, float width, float height, float mouseX, float mouseY, boolean custom) { - inputBox.backGroundColor = FPSMaster.theme.getTextboxEnabled().getRGB(); - inputBox.fontColor = FPSMaster.theme.getTextColorTitle().getRGB(); + inputBox.backGroundColor = new Color(58, 58, 58).getRGB(); + inputBox.fontColor = new Color(234, 234, 234).getRGB(); String text = FPSMaster.i18n.get((mod.name + "." + setting.name).toLowerCase(Locale.getDefault())); - FPSMaster.fontManager.s16.drawString(text, x + 18, y + 6, FPSMaster.theme.getTextColorDescription().getRGB()); + FPSMaster.fontManager.s16.drawString(text, x + 18, y + 6, new Color(162, 162, 162).getRGB()); inputBox.drawTextBox( x + Math.max(FPSMaster.fontManager.s16.getStringWidth(inputBox.placeHolder), FPSMaster.fontManager.s16.getStringWidth(text)) + 20, y + 2, diff --git a/shared/java/top/fpsmaster/ui/click/music/MusicPanel.java b/shared/java/top/fpsmaster/ui/click/music/MusicPanel.java index f2be6a39..5d12fe88 100644 --- a/shared/java/top/fpsmaster/ui/click/music/MusicPanel.java +++ b/shared/java/top/fpsmaster/ui/click/music/MusicPanel.java @@ -156,7 +156,7 @@ public static void keyTyped(char c, int keyCode) { public static void draw(float x, float y, float width, float height, int mouseX, int mouseY, int scaleFactor) { if (isWaitingLogin) { - FPSMaster.fontManager.s18.drawCenteredString("<", x + 20, y + 20, FPSMaster.theme.getTextColorTitle().getRGB()); + FPSMaster.fontManager.s18.drawCenteredString("<", x + 20, y + 20, new Color(234, 234, 234).getRGB()); if (Render2DUtils.isHovered(x + 20, y + 20, 20f, 20f, mouseX, mouseY) && Mouse.isButtonDown(0)) { isWaitingLogin = false; } @@ -182,7 +182,7 @@ public static void draw(float x, float y, float width, float height, int mouseX, isWaitingLogin = false; break; } - FPSMaster.fontManager.s18.drawCenteredString(FPSMaster.i18n.get(scan), x + width / 2, y + height / 2 + 60, FPSMaster.theme.getTextColorTitle().getRGB()); + FPSMaster.fontManager.s18.drawCenteredString(FPSMaster.i18n.get(scan), x + width / 2, y + height / 2 + 60, new Color(234, 234, 234).getRGB()); return; } MusicPanel.x = x; @@ -201,8 +201,8 @@ public static void draw(float x, float y, float width, float height, int mouseX, AtomicReference musicHeight = new AtomicReference<>(0f); Render2DUtils.drawRect(x, dY.get() - 6, width - 10, 0.5f, new Color(100, 100, 100, 50)); - FPSMaster.fontManager.s16.drawString("#", x + 12, dY.get() - 20, FPSMaster.theme.getTextColorTitle().getRGB()); - FPSMaster.fontManager.s16.drawString("标题", x + 30, dY.get() - 20, FPSMaster.theme.getTextColorTitle().getRGB()); + FPSMaster.fontManager.s16.drawString("#", x + 12, dY.get() - 20, new Color(234, 234, 234).getRGB()); + FPSMaster.fontManager.s16.drawString("标题", x + 30, dY.get() - 20, new Color(234, 234, 234).getRGB()); // music list container.draw(x, y + 50, width - 5, height - 80, mouseX, mouseY, () -> { @@ -211,20 +211,20 @@ public static void draw(float x, float y, float width, float height, int mouseX, if (Render2DUtils.isHovered(x, dY.get(), width - 10f, 40f, mouseX, mouseY) && mouseY > y + 50 && mouseY < y + height - 34) { Render2DUtils.drawOptimizedRoundedRect(x, dY.get(), width - 10, 40f, new Color(200, 200, 200, 50)); } - FPSMaster.fontManager.s16.drawCenteredString("" + i, x + 15, dY.get() + 15, FPSMaster.theme.getTextColorTitle().getRGB()); + FPSMaster.fontManager.s16.drawCenteredString("" + i, x + 15, dY.get() + 15, new Color(234, 234, 234).getRGB()); if (dY.get() > y && dY.get() < y + height - 10) { if (music.isLoadedImage) { Render2DUtils.drawImage(new ResourceLocation("music/netease/" + music.id), x + 30, dY.get() + 10, 20f, 20f, -1); } else { - Render2DUtils.drawOptimizedRoundedRect(x + 30, dY.get() + 10, 20f, 20f, FPSMaster.theme.getMusicBlank()); + Render2DUtils.drawOptimizedRoundedRect(x + 30, dY.get() + 10, 20f, 20f, new Color(200, 200, 200, 255)); } } if (MusicPlayer.playList.current == i) { - FPSMaster.fontManager.s16.drawString(music.name + " " + music.author, x + 60, dY.get() + 10, FPSMaster.theme.getTextColorTitle().getRGB()); - FPSMaster.fontManager.s16.drawString(music.author, x + 60, dY.get() + 20, FPSMaster.theme.getTextColorDescription().getRGB()); + FPSMaster.fontManager.s16.drawString(music.name + " " + music.author, x + 60, dY.get() + 10, new Color(234, 234, 234).getRGB()); + FPSMaster.fontManager.s16.drawString(music.author, x + 60, dY.get() + 20, new Color(162, 162, 162).getRGB()); } else { - FPSMaster.fontManager.s16.drawString(music.name + " " + music.author, x + 60, dY.get() + 10, FPSMaster.theme.getTextColorTitle().getRGB()); - FPSMaster.fontManager.s16.drawString(music.author, x + 60, dY.get() + 20, FPSMaster.theme.getTextColorDescription().getRGB()); + FPSMaster.fontManager.s16.drawString(music.name + " " + music.author, x + 60, dY.get() + 10, new Color(234, 234, 234).getRGB()); + FPSMaster.fontManager.s16.drawString(music.author, x + 60, dY.get() + 20, new Color(162, 162, 162).getRGB()); } dY.updateAndGet(v -> new Float((float) (v + 40f))); musicHeight.updateAndGet(v -> new Float((float) (v + 40f))); @@ -233,7 +233,7 @@ public static void draw(float x, float y, float width, float height, int mouseX, }); } else { - FPSMaster.fontManager.s18.drawCenteredString("...", x + width / 2, y + 60, FPSMaster.theme.getTextColorTitle().getRGB()); + FPSMaster.fontManager.s18.drawCenteredString("...", x + width / 2, y + 60, new Color(234, 234, 234).getRGB()); } GL11.glDisable(GL11.GL_SCISSOR_TEST); @@ -265,14 +265,14 @@ public static void draw(float x, float y, float width, float height, int mouseX, } int stringWidth = FPSMaster.fontManager.s16.getStringWidth(FPSMaster.i18n.get("music.notLoggedIn")); if (Render2DUtils.isHovered(x + width - stringWidth - 5, y + 10, stringWidth, 16f, mouseX, mouseY)) { - FPSMaster.fontManager.s16.drawString(FPSMaster.i18n.get("music.notloggedin"), x + width - stringWidth - 5, y + 10, FPSMaster.theme.getTextColorTitle().getRGB()); + FPSMaster.fontManager.s16.drawString(FPSMaster.i18n.get("music.notloggedin"), x + width - stringWidth - 5, y + 10, new Color(234, 234, 234).getRGB()); if (Mouse.isButtonDown(0)) { isWaitingLogin = true; reloadImg(); code = 801; } } else { - FPSMaster.fontManager.s16.drawString(FPSMaster.i18n.get("music.notloggedin"), x + width - stringWidth - 5, y + 10, FPSMaster.theme.getTextColorDescription().getRGB()); + FPSMaster.fontManager.s16.drawString(FPSMaster.i18n.get("music.notloggedin"), x + width - stringWidth - 5, y + 10, new Color(162, 162, 162).getRGB()); } } else { int stringWidth = FPSMaster.fontManager.s16.getStringWidth(nickname); @@ -288,7 +288,7 @@ public static void draw(float x, float y, float width, float height, int mouseX, // 操作栏 AbstractMusic current = MusicPlayer.playList.current(); - Render2DUtils.drawRect(x, y + height - 30, width, 2f, FPSMaster.theme.getFrontBackground().getRGB()); + Render2DUtils.drawRect(x, y + height - 30, width, 2f, new Color(58, 58, 58).getRGB()); Render2DUtils.drawRect(x, y + height - 30, width * MusicPlayer.getPlayProgress(), 2f, -1); if (Render2DUtils.isHovered(x, y + height - 32, width, 4f, mouseX, mouseY)) { Render2DUtils.drawRect(x, y + height - 31f, width * MusicPlayer.getPlayProgress(), 4f, -1); @@ -296,7 +296,7 @@ public static void draw(float x, float y, float width, float height, int mouseX, // 音量 Render2DUtils.drawImage(new ResourceLocation("client/textures/ui/volume.png"), x + width - 50, y + height - 16, 7f, 7f, -1); - Render2DUtils.drawRect(x + width - 40, y + height - 14, 30f, 2f, FPSMaster.theme.getFrontBackground().getRGB()); + Render2DUtils.drawRect(x + width - 40, y + height - 14, 30f, 2f, new Color(58, 58, 58).getRGB()); Render2DUtils.drawRect(x + width - 40, y + height - 14, 30 * MusicPlayer.getVolume(), 2f, -1); if (Render2DUtils.isHovered(x + width - 40, y + height - 14, 30f, 2f, mouseX, mouseY)) { Render2DUtils.drawRect(x + width - 40, y + height - 14.5f, 30 * MusicPlayer.getVolume(), 3f, -1); @@ -308,7 +308,7 @@ public static void draw(float x, float y, float width, float height, int mouseX, int trimWidth = (int) (width / 2 - 100); if (!MusicPlayer.playList.musics.isEmpty() && current != null) { String name = FPSMaster.fontManager.s18.trimString(current.name + " - " + current.author, trimWidth, false); - FPSMaster.fontManager.s18.drawString(name, x + 30, y + height - 23, FPSMaster.theme.getTextColorTitle().getRGB()); + FPSMaster.fontManager.s18.drawString(name, x + 30, y + height - 23, new Color(234, 234, 234).getRGB()); String progress = "0:00/0:00"; if (JLayerHelper.clip != null) { double duration = JLayerHelper.getDuration(); @@ -316,11 +316,11 @@ public static void draw(float x, float y, float width, float height, int mouseX, int seconds = (int) ((duration * MusicPlayer.getPlayProgress() - minutes) * 60); progress = minutes + ":" + seconds + "/" + (int) duration + ":" + (int) ((duration - (int) duration) * 60); } - FPSMaster.fontManager.s16.drawString(progress, x + 30, y + height - 14, FPSMaster.theme.getTextColorDescription().getRGB()); + FPSMaster.fontManager.s16.drawString(progress, x + 30, y + height - 14, new Color(162, 162, 162).getRGB()); if (MusicPlayer.playList.current() != null && ((Music) MusicPlayer.playList.current()).isLoadedImage) { Render2DUtils.drawImage(new ResourceLocation("music/netease/" + ((Music) MusicPlayer.playList.current()).id), x + 5, y + height - 24, 20f, 20f, -1); } else { - Render2DUtils.drawOptimizedRoundedRect(x + 5, y + height - 24, 20f, 20f, FPSMaster.theme.getMusicBlank()); + Render2DUtils.drawOptimizedRoundedRect(x + 5, y + height - 24, 20f, 20f, new Color(200, 200, 200, 255)); } } ResourceLocation res = new ResourceLocation("client/gui/settings/music/loop.png"); @@ -335,10 +335,10 @@ public static void draw(float x, float y, float width, float height, int mouseX, res = new ResourceLocation("client/gui/settings/music/loop.png"); break; } - Render2DUtils.drawImage(res, x + width / 2 - 55, y + height - 21, 12f, 12f, FPSMaster.theme.getTextColorTitle()); - Render2DUtils.drawImage(new ResourceLocation("client/gui/settings/music/previous.png"), x + width / 2 - 35, y + height - 23, 16f, 16f, FPSMaster.theme.getTextColorTitle()); + Render2DUtils.drawImage(res, x + width / 2 - 55, y + height - 21, 12f, 12f, new Color(234, 234, 234)); + Render2DUtils.drawImage(new ResourceLocation("client/gui/settings/music/previous.png"), x + width / 2 - 35, y + height - 23, 16f, 16f, new Color(234, 234, 234)); Render2DUtils.drawImage(MusicPlayer.isPlaying ? new ResourceLocation("client/gui/settings/music/pause.png") : new ResourceLocation("client/gui/settings/music/play.png"), x + width / 2 - 15, y + height - 23, 35 / 2f, 35 / 2f, -1); - Render2DUtils.drawImage(new ResourceLocation("client/gui/settings/music/next.png"), x + width / 2 + 5, y + height - 23, 16f, 16f, FPSMaster.theme.getTextColorTitle()); + Render2DUtils.drawImage(new ResourceLocation("client/gui/settings/music/next.png"), x + width / 2 + 5, y + height - 23, 16f, 16f, new Color(234, 234, 234)); } private static String extractMiddleContent(String input, String prefix, String suffix) { diff --git a/shared/java/top/fpsmaster/ui/click/music/SearchBox.java b/shared/java/top/fpsmaster/ui/click/music/SearchBox.java index 0eb88bd1..fe1f8252 100644 --- a/shared/java/top/fpsmaster/ui/click/music/SearchBox.java +++ b/shared/java/top/fpsmaster/ui/click/music/SearchBox.java @@ -51,23 +51,23 @@ public SearchBox(String placeholder, UFontRenderer fontrendererObj, Runnable run this.font = fontrendererObj; this.runnable = runnable; this.placeholder = placeholder; - this.enabledColor = FPSMaster.theme.getTextboxEnabled(); - this.disabledColor = FPSMaster.theme.getTextboxDisabled(); + this.enabledColor = new Color(58, 58, 58); + this.disabledColor = new Color(30, 30, 30); } public SearchBox(String placeholder) { this.font = FPSMaster.fontManager.s18; this.placeholder = placeholder; - this.enabledColor = FPSMaster.theme.getTextboxEnabled(); - this.disabledColor = FPSMaster.theme.getTextboxDisabled(); + this.enabledColor = new Color(58, 58, 58); + this.disabledColor = new Color(30, 30, 30); } public SearchBox(String s, Runnable runnable) { this.font = FPSMaster.fontManager.s18; this.placeholder = s; this.runnable = runnable; - this.enabledColor = FPSMaster.theme.getTextboxEnabled(); - this.disabledColor = FPSMaster.theme.getTextboxDisabled(); + this.enabledColor = new Color(58, 58, 58); + this.disabledColor = new Color(30, 30, 30); } public void updateCursorCounter() { diff --git a/shared/java/top/fpsmaster/ui/click/themes/DarkTheme.java b/shared/java/top/fpsmaster/ui/click/themes/DarkTheme.java deleted file mode 100644 index c896591d..00000000 --- a/shared/java/top/fpsmaster/ui/click/themes/DarkTheme.java +++ /dev/null @@ -1,155 +0,0 @@ -package top.fpsmaster.ui.click.themes; - -import java.awt.Color; - -public class DarkTheme implements Theme { - @Override - public Color getBackground() { - return new Color(39, 39, 39); - } - - @Override - public Color getFrontBackground() { - return new Color(58, 58, 58); - } - - @Override - public Color getTypeSelectionBackground() { - return new Color(70, 70, 70); - } - - @Override - public Color getPrimary() { - return new Color(113, 127, 254); - } - - @Override - public Color getPrimaryGradientLT() { - return new Color(77, 100, 255); - } - - @Override - public Color getPrimaryGradientRB() { - return new Color(108, 113, 255); - } - - @Override - public Color getTextColorTitle() { - return new Color(234, 234, 234); - } - - @Override - public Color getTextColorDescription() { - return new Color(162, 162, 162); - } - - @Override - public Color getCategoryTextSelected() { - return new Color(234, 234, 234); - } - - @Override - public Color getCategoryText() { - return new Color(173, 173, 173); - } - - @Override - public Color getLogo() { - return new Color(255, 255, 255); - } - - @Override - public Color getDrag() { - return new Color(200, 200, 200); - } - - @Override - public Color getDragHovered() { - return new Color(255, 255, 255); - } - - @Override - public Color getModuleEnabled() { - return new Color(66, 66, 66); - } - - @Override - public Color getModuleDisabled() { - return new Color(40, 40, 40); - } - - @Override - public Color getModuleBorder() { - return new Color(200, 200, 200); - } - - @Override - public Color getModuleTextEnabled() { - return new Color(255, 255, 255); - } - - @Override - public Color getModuleTextDisabled() { - return new Color(156, 156, 156); - } - - @Override - public Color getCheckboxBox() { - return new Color(71, 71, 71); - } - - @Override - public Color getCheckboxHover() { - return new Color(129, 132, 255); - } - - @Override - public Color getTextNumber() { - return new Color(128, 128, 128); - } - - @Override - public Color getModeBox() { - return new Color(52, 52, 52); - } - - @Override - public Color getModeBoxBorder() { - return new Color(255, 255, 255, 50); - } - - @Override - public Color getTextboxEnabled() { - return new Color(58, 58, 58); - } - - @Override - public Color getTextboxDisabled() { - return new Color(30, 30, 30); - } - - @Override - public Color getTextboxFocus() { - return new Color(70, 70, 70); - } - - @Override - public Color getTextboxHover() { - return new Color(64, 64, 64); - } - - @Override - public Color getTextColorDescriptionHover() { - return new Color(182, 182, 182); - } - - @Override - public Color getMusicBlank() { - return new Color(200, 200, 200, 255); - } - - @Override - public Color getButtonText() { - return new Color(255, 255, 255); - } -} diff --git a/shared/java/top/fpsmaster/ui/click/themes/LightTheme.java b/shared/java/top/fpsmaster/ui/click/themes/LightTheme.java deleted file mode 100644 index b1647f7a..00000000 --- a/shared/java/top/fpsmaster/ui/click/themes/LightTheme.java +++ /dev/null @@ -1,155 +0,0 @@ -package top.fpsmaster.ui.click.themes; - -import java.awt.Color; - -public class LightTheme implements Theme { - @Override - public Color getBackground() { - return new Color(252, 252, 252); - } - - @Override - public Color getFrontBackground() { - return new Color(240, 240, 240); - } - - @Override - public Color getTypeSelectionBackground() { - return new Color(202, 202, 202); - } - - @Override - public Color getPrimary() { - return new Color(113, 127, 254); - } - - @Override - public Color getPrimaryGradientLT() { - return new Color(77, 100, 255); - } - - @Override - public Color getPrimaryGradientRB() { - return new Color(108, 113, 255); - } - - @Override - public Color getTextColorTitle() { - return new Color(61, 61, 61); - } - - @Override - public Color getTextColorDescription() { - return new Color(156, 156, 156); - } - - @Override - public Color getCategoryTextSelected() { - return new Color(255, 255, 255); - } - - @Override - public Color getCategoryText() { - return new Color(61, 61, 61); - } - - @Override - public Color getLogo() { - return new Color(101, 109, 255); - } - - @Override - public Color getDrag() { - return new Color(192, 192, 192); - } - - @Override - public Color getDragHovered() { - return new Color(172, 172, 172); - } - - @Override - public Color getModuleEnabled() { - return new Color(255, 255, 255); - } - - @Override - public Color getModuleDisabled() { - return new Color(240, 240, 240); - } - - @Override - public Color getModuleBorder() { - return new Color(192, 192, 192); - } - - @Override - public Color getModuleTextEnabled() { - return new Color(61, 61, 61); - } - - @Override - public Color getModuleTextDisabled() { - return new Color(61, 61, 61); - } - - @Override - public Color getCheckboxBox() { - return new Color(235, 235, 235); - } - - @Override - public Color getCheckboxHover() { - return new Color(109, 112, 255); - } - - @Override - public Color getTextNumber() { - return new Color(161, 161, 161); - } - - @Override - public Color getModeBox() { - return new Color(242, 242, 242); - } - - @Override - public Color getModeBoxBorder() { - return new Color(223, 223, 223); - } - - @Override - public Color getTextboxEnabled() { - return new Color(237, 237, 237); - } - - @Override - public Color getTextboxDisabled() { - return new Color(147, 147, 147); - } - - @Override - public Color getTextboxFocus() { - return new Color(247, 247, 247); - } - - @Override - public Color getTextboxHover() { - return new Color(255, 255, 255); - } - - @Override - public Color getTextColorDescriptionHover() { - return new Color(73, 73, 73); - } - - @Override - public Color getMusicBlank() { - return new Color(100, 100, 100, 255); - } - - @Override - public Color getButtonText() { - return new Color(255, 255, 255); - } -} diff --git a/shared/java/top/fpsmaster/ui/click/themes/Theme.java b/shared/java/top/fpsmaster/ui/click/themes/Theme.java deleted file mode 100644 index 04596095..00000000 --- a/shared/java/top/fpsmaster/ui/click/themes/Theme.java +++ /dev/null @@ -1,65 +0,0 @@ -package top.fpsmaster.ui.click.themes; - -import java.awt.Color; - -public interface Theme { - Color getBackground(); - - Color getFrontBackground(); - - Color getTypeSelectionBackground(); - - Color getPrimary(); - - Color getPrimaryGradientLT(); - - Color getPrimaryGradientRB(); - - Color getTextColorTitle(); - - Color getTextColorDescription(); - - Color getCategoryTextSelected(); - - Color getCategoryText(); - - Color getLogo(); - - Color getDrag(); - - Color getDragHovered(); - - Color getModuleEnabled(); - - Color getModuleDisabled(); - - Color getModuleBorder(); - - Color getModuleTextEnabled(); - - Color getModuleTextDisabled(); - - Color getCheckboxBox(); - - Color getCheckboxHover(); - - Color getTextNumber(); - - Color getModeBox(); - - Color getModeBoxBorder(); - - Color getTextboxEnabled(); - - Color getTextboxDisabled(); - - Color getTextboxFocus(); - - Color getTextboxHover(); - - Color getTextColorDescriptionHover(); - - Color getMusicBlank(); - - Color getButtonText(); -} diff --git a/shared/java/top/fpsmaster/ui/common/GuiButton.java b/shared/java/top/fpsmaster/ui/common/GuiButton.java index 6bd27ce5..13707409 100644 --- a/shared/java/top/fpsmaster/ui/common/GuiButton.java +++ b/shared/java/top/fpsmaster/ui/common/GuiButton.java @@ -48,7 +48,7 @@ public void render(float x, float y, float width, float height, float mouseX, fl FPSMaster.i18n.get(text), x + width / 2, y + height / 2 - 4, - FPSMaster.theme.getButtonText().getRGB() + new Color(255, 255, 255).getRGB() ); } diff --git a/shared/java/top/fpsmaster/ui/custom/impl/ModsListComponent.java b/shared/java/top/fpsmaster/ui/custom/impl/ModsListComponent.java index 491df9a9..d36ccbea 100644 --- a/shared/java/top/fpsmaster/ui/custom/impl/ModsListComponent.java +++ b/shared/java/top/fpsmaster/ui/custom/impl/ModsListComponent.java @@ -36,7 +36,7 @@ public void draw(float x, float y) { if (modlist.showLogo.getValue()) { float stringWidth = getStringWidth(36, modlist.text.getValue()); drawString(36, modlist.text.getValue(), (float) (x + 0.5 + width - stringWidth), y + 0.5f, new Color(0, 0, 0, 100).getRGB()); - drawString(36, modlist.text.getValue(), x + width - stringWidth, y, FPSMaster.theme.getPrimary().getRGB()); + drawString(36, modlist.text.getValue(), x + width - stringWidth, y, new Color(113, 127, 254).getRGB()); modY = 20f; } diff --git a/shared/java/top/fpsmaster/ui/custom/impl/MusicComponent.java b/shared/java/top/fpsmaster/ui/custom/impl/MusicComponent.java index 65b3100b..4b49c8db 100644 --- a/shared/java/top/fpsmaster/ui/custom/impl/MusicComponent.java +++ b/shared/java/top/fpsmaster/ui/custom/impl/MusicComponent.java @@ -42,8 +42,8 @@ private void drawSong(float x, float y, float width, float height) { -1 ); - drawString(18, current.name, x + 40, y + 6, FPSMaster.theme.getTextColorTitle().getRGB()); - drawString(16, current.author, x + 40, y + 18, FPSMaster.theme.getTextColorDescription().getRGB()); + drawString(18, current.name, x + 40, y + 6, new Color(234, 234, 234).getRGB()); + drawString(16, current.author, x + 40, y + 18, new Color(162, 162, 162).getRGB()); } @Override diff --git a/shared/java/top/fpsmaster/ui/screens/account/GuiWaiting.java b/shared/java/top/fpsmaster/ui/screens/account/GuiWaiting.java index 66a57ffb..4ad40c5f 100644 --- a/shared/java/top/fpsmaster/ui/screens/account/GuiWaiting.java +++ b/shared/java/top/fpsmaster/ui/screens/account/GuiWaiting.java @@ -38,14 +38,14 @@ public void drawScreen(int mouseX, int mouseY, float partialTicks) { MicrosoftLogin.loginProgressMessage, sr.getScaledWidth() / 2f, sr.getScaledHeight() / 2f - 30, - FPSMaster.theme.getTextColorDescription().getRGB() + new Color(162, 162, 162).getRGB() ); FPSMaster.fontManager.s40.drawCenteredString( FPSMaster.i18n.get("microsoft.login.title"), sr.getScaledWidth() / 2f, sr.getScaledHeight() / 2f + 10, - FPSMaster.theme.getPrimary().getRGB() + new Color(113, 127, 254).getRGB() ); // Check if logged in and switch to the main menu diff --git a/shared/java/top/fpsmaster/ui/screens/mainmenu/MenuButton.java b/shared/java/top/fpsmaster/ui/screens/mainmenu/MenuButton.java index bc981e57..32e38af9 100644 --- a/shared/java/top/fpsmaster/ui/screens/mainmenu/MenuButton.java +++ b/shared/java/top/fpsmaster/ui/screens/mainmenu/MenuButton.java @@ -45,19 +45,19 @@ public void render(float x, float y, float width, float height, float mouseX, fl // Draw text or icon if (!text.equals("settings")) { FPSMaster.fontManager.s18.drawCenteredString( - FPSMaster.i18n.get(text), - x + width / 2, - y + height / 2 - 6, - FPSMaster.theme.getButtonText().getRGB() + FPSMaster.i18n.get(text), + x + width / 2, + y + height / 2 - 6, + new Color(255, 255, 255).getRGB() ); } else { Render2DUtils.drawImage( - new ResourceLocation("client/gui/screen/settings.png"), - x + width / 2 - 6, - y + height / 2 - 6, - 12f, - 12f, - FPSMaster.theme.getTextColorTitle().getRGB() + new ResourceLocation("client/gui/screen/settings.png"), + x + width / 2 - 6, + y + height / 2 - 6, + 12f, + 12f, + new Color(255, 255, 255).getRGB() ); } } diff --git a/shared/java/top/fpsmaster/ui/screens/oobe/impls/Login.java b/shared/java/top/fpsmaster/ui/screens/oobe/impls/Login.java index af8b182a..04a2714b 100644 --- a/shared/java/top/fpsmaster/ui/screens/oobe/impls/Login.java +++ b/shared/java/top/fpsmaster/ui/screens/oobe/impls/Login.java @@ -87,9 +87,9 @@ public void drawScreen(int mouseX, int mouseY, float partialTicks) { Render2DUtils.drawRect(0f, 0f, sr.getScaledWidth(), sr.getScaledHeight(), new Color(235, 242, 255).getRGB()); - FPSMaster.fontManager.s24.drawCenteredString(FPSMaster.i18n.get("oobe.login.desc"), sr.getScaledWidth() / 2f, sr.getScaledHeight() / 2f - 90, FPSMaster.theme.getTextColorDescription().getRGB()); - FPSMaster.fontManager.s18.drawString(FPSMaster.i18n.get("oobe.login.register"), sr.getScaledWidth() / 2f - 90, sr.getScaledHeight() / 2f + 15, FPSMaster.theme.getPrimary().getRGB()); - FPSMaster.fontManager.s40.drawCenteredString(FPSMaster.i18n.get("oobe.login.title"), sr.getScaledWidth() / 2f, sr.getScaledHeight() / 2f - 75, FPSMaster.theme.getPrimary().getRGB()); + FPSMaster.fontManager.s24.drawCenteredString(FPSMaster.i18n.get("oobe.login.desc"), sr.getScaledWidth() / 2f, sr.getScaledHeight() / 2f - 90, new Color(162, 162, 162).getRGB()); + FPSMaster.fontManager.s18.drawString(FPSMaster.i18n.get("oobe.login.register"), sr.getScaledWidth() / 2f - 90, sr.getScaledHeight() / 2f + 15, new Color(113, 127, 254).getRGB()); + FPSMaster.fontManager.s40.drawCenteredString(FPSMaster.i18n.get("oobe.login.title"), sr.getScaledWidth() / 2f, sr.getScaledHeight() / 2f - 75, new Color(113, 127, 254).getRGB()); btn.render(sr.getScaledWidth() / 2f - 70, sr.getScaledHeight() / 2f + 40, 60f, 24f, mouseX, mouseY); btn2.render(sr.getScaledWidth() / 2f + 5, sr.getScaledHeight() / 2f + 40, 60f, 24f, mouseX, mouseY); From 1380afcb39b68f81984a59e7e3d0ee18533fbe8b Mon Sep 17 00:00:00 2001 From: SuperSkidder Date: Mon, 14 Jul 2025 17:28:40 +0800 Subject: [PATCH 085/193] optimize imports --- shared/java/top/fpsmaster/FPSMaster.java | 3 +-- .../java/top/fpsmaster/event/EventDispatcher.java | 1 + .../fpsmaster/event/events/EventAnimation.java | 1 - .../fpsmaster/event/events/EventJoinServer.java | 1 - .../event/events/EventSendChatMessage.java | 1 - .../fpsmaster/event/events/EventValueChange.java | 1 - .../top/fpsmaster/exception/ExceptionHandler.java | 3 --- .../top/fpsmaster/features/GlobalSubmitter.java | 2 -- .../features/command/CommandManager.java | 1 - .../top/fpsmaster/features/command/impl/AI.java | 3 --- .../top/fpsmaster/features/command/impl/Dev.java | 3 --- .../fpsmaster/features/command/impl/IRCChat.java | 3 --- .../fpsmaster/features/impl/InterfaceModule.java | 2 +- .../features/impl/interfaces/ArmorDisplay.java | 3 --- .../features/impl/interfaces/CPSDisplay.java | 2 +- .../features/impl/interfaces/ComboDisplay.java | 2 +- .../features/impl/interfaces/FPSDisplay.java | 2 +- .../features/impl/interfaces/Keystrokes.java | 3 ++- .../features/impl/interfaces/ModsList.java | 2 +- .../features/impl/interfaces/MusicOverlay.java | 2 +- .../features/impl/interfaces/PingDisplay.java | 2 +- .../features/impl/interfaces/ReachDisplay.java | 3 +-- .../features/impl/interfaces/TargetDisplay.java | 3 +-- .../features/impl/optimizes/OldAnimations.java | 2 -- .../features/impl/optimizes/Performance.java | 4 ---- .../fpsmaster/features/impl/render/Crosshair.java | 4 ++-- .../features/impl/render/DamageIndicator.java | 4 ---- .../features/impl/render/FireModifier.java | 2 +- .../fpsmaster/features/impl/render/HitColor.java | 2 +- .../fpsmaster/features/impl/utility/ChatBot.java | 7 ++----- .../top/fpsmaster/features/impl/utility/IRC.java | 11 ----------- .../fpsmaster/features/impl/utility/Sprint.java | 4 ---- .../fpsmaster/features/impl/utility/TNTTimer.java | 2 +- .../top/fpsmaster/features/manager/Module.java | 7 +------ .../fpsmaster/features/manager/ModuleManager.java | 3 +-- .../features/settings/impl/ColorSetting.java | 3 ++- .../features/settings/impl/utils/CustomColor.java | 3 ++- shared/java/top/fpsmaster/font/FontManager.java | 1 - .../java/top/fpsmaster/font/impl/GlyphCache.java | 3 ++- .../top/fpsmaster/font/impl/UFontRenderer.java | 5 +---- .../interfaces/game/IMinecraftProvider.java | 1 + .../fpsmaster/modules/config/ConfigManager.java | 6 ++++-- .../java/top/fpsmaster/modules/i18n/Language.java | 3 --- .../top/fpsmaster/modules/lua/LuaManager.java | 7 ------- .../java/top/fpsmaster/modules/lua/LuaModule.java | 1 - .../fpsmaster/modules/lua/parser/Statement.java | 2 -- .../fpsmaster/modules/music/IngameOverlay.java | 3 +-- .../top/fpsmaster/modules/music/JLayerHelper.java | 1 + .../fpsmaster/modules/music/netease/Music.java | 2 -- .../modules/music/netease/NeteaseApi.java | 2 -- .../music/netease/deserialize/MusicWrapper.java | 1 - shared/java/top/fpsmaster/ui/Compass.java | 1 - shared/java/top/fpsmaster/ui/click/MainPanel.java | 5 ++--- .../java/top/fpsmaster/ui/click/TestScreen.java | 3 --- .../ui/click/component/ScrollContainer.java | 2 +- .../ui/click/modules/ModuleRenderer.java | 5 ----- .../ui/click/modules/impl/BindSettingRender.java | 1 - .../click/modules/impl/BooleanSettingRender.java | 3 +-- .../ui/click/modules/impl/ColorSettingRender.java | 4 ++-- .../ui/click/modules/impl/TextSettingRender.java | 4 ++-- .../top/fpsmaster/ui/click/music/MusicPanel.java | 3 +-- .../top/fpsmaster/ui/click/music/SearchBox.java | 4 ++-- .../java/top/fpsmaster/ui/common/GuiButton.java | 2 +- .../java/top/fpsmaster/ui/custom/Component.java | 6 +++--- .../fpsmaster/ui/custom/ComponentsManager.java | 1 - .../ui/custom/impl/ArmorDisplayComponent.java | 6 ++---- .../ui/custom/impl/CPSDisplayComponent.java | 1 - .../ui/custom/impl/ComboDisplayComponent.java | 1 - .../ui/custom/impl/CoordsDisplayComponent.java | 3 +-- .../ui/custom/impl/FPSDisplayComponent.java | 1 - .../ui/custom/impl/InventoryDisplayComponent.java | 3 +-- .../ui/custom/impl/KeystrokesComponent.java | 2 +- .../fpsmaster/ui/custom/impl/LyricsComponent.java | 4 ---- .../ui/custom/impl/MiniMapComponent.java | 1 - .../ui/custom/impl/ModsListComponent.java | 6 ++---- .../fpsmaster/ui/custom/impl/MusicComponent.java | 3 +-- .../ui/custom/impl/PingDisplayComponent.java | 3 +-- .../ui/custom/impl/PlayerDisplayComponent.java | 4 ++-- .../ui/custom/impl/PotionDisplayComponent.java | 6 ++---- .../ui/custom/impl/ReachDisplayComponent.java | 1 - .../fpsmaster/ui/custom/impl/SprintComponent.java | 1 - .../ui/custom/impl/TargetHUDComponent.java | 4 ++-- .../java/top/fpsmaster/ui/devspace/AIPanel.java | 2 -- .../FunctionCallExpressionComponent.java | 1 - .../java/top/fpsmaster/ui/mc/GuiMultiplayer.java | 10 +++------- .../java/top/fpsmaster/ui/mc/ServerListEntry.java | 15 ++++++--------- .../top/fpsmaster/ui/minimap/XaeroMinimap.java | 1 - .../ui/minimap/interfaces/InterfaceHandler.java | 4 +--- .../fpsmaster/ui/notification/Notification.java | 2 +- .../fpsmaster/ui/screens/account/GuiWaiting.java | 2 +- .../fpsmaster/ui/screens/mainmenu/MainMenu.java | 3 +-- .../top/fpsmaster/ui/screens/oobe/OOBEScreen.java | 2 +- .../fpsmaster/ui/screens/oobe/impls/Login.java | 7 +++---- shared/java/top/fpsmaster/utils/awt/AWTUtils.java | 1 - shared/java/top/fpsmaster/utils/awt/GifUtil.java | 15 +++++++++------ .../utils/math/animation/AnimationUtils.java | 2 -- .../utils/math/animation/ColorAnimation.java | 3 ++- .../java/top/fpsmaster/utils/os/CryptUtils.java | 4 ++-- .../java/top/fpsmaster/utils/os/HttpRequest.java | 6 +++--- .../top/fpsmaster/utils/render/Render2DUtils.java | 2 -- .../fpsmaster/utils/render/ScaledGuiScreen.java | 2 -- .../utils/render/shader/KawaseBloom.java | 1 - .../fpsmaster/utils/render/shader/KawaseBlur.java | 1 - .../utils/render/shader/RoundedUtil.java | 2 +- .../utils/thirdparty/github/UpdateChecker.java | 4 ---- .../thirdparty/microsoft/MicrosoftLogin.java | 4 ---- .../fpsmaster/utils/thirdparty/openai/OpenAI.java | 1 - .../utils/thirdparty/openai/OpenAIClient.java | 6 +++--- .../top/fpsmaster/websocket/client/WsClient.java | 3 --- 109 files changed, 103 insertions(+), 242 deletions(-) diff --git a/shared/java/top/fpsmaster/FPSMaster.java b/shared/java/top/fpsmaster/FPSMaster.java index 11db2504..c774a1a5 100644 --- a/shared/java/top/fpsmaster/FPSMaster.java +++ b/shared/java/top/fpsmaster/FPSMaster.java @@ -1,6 +1,5 @@ package top.fpsmaster; -import net.minecraftforge.fml.common.FMLCommonHandler; import top.fpsmaster.exception.ExceptionHandler; import top.fpsmaster.exception.FileException; import top.fpsmaster.features.GlobalSubmitter; @@ -11,6 +10,7 @@ import top.fpsmaster.modules.client.AsyncTask; import top.fpsmaster.modules.client.ClientUsersManager; import top.fpsmaster.modules.config.ConfigManager; +import top.fpsmaster.modules.i18n.Language; import top.fpsmaster.modules.logger.ClientLogger; import top.fpsmaster.modules.lua.LuaManager; import top.fpsmaster.modules.music.MusicPlayer; @@ -20,7 +20,6 @@ import top.fpsmaster.ui.screens.oobe.OOBEScreen; import top.fpsmaster.utils.GitInfo; import top.fpsmaster.utils.os.FileUtils; -import top.fpsmaster.modules.i18n.Language; import top.fpsmaster.utils.os.HttpRequest; import top.fpsmaster.utils.thirdparty.github.UpdateChecker; import top.fpsmaster.websocket.client.WsClient; diff --git a/shared/java/top/fpsmaster/event/EventDispatcher.java b/shared/java/top/fpsmaster/event/EventDispatcher.java index a3a023db..d68b7fa6 100644 --- a/shared/java/top/fpsmaster/event/EventDispatcher.java +++ b/shared/java/top/fpsmaster/event/EventDispatcher.java @@ -2,6 +2,7 @@ import top.fpsmaster.exception.ExceptionHandler; import top.fpsmaster.modules.logger.ClientLogger; + import java.lang.reflect.Method; import java.util.HashMap; import java.util.List; diff --git a/shared/java/top/fpsmaster/event/events/EventAnimation.java b/shared/java/top/fpsmaster/event/events/EventAnimation.java index 53850551..e97585ec 100644 --- a/shared/java/top/fpsmaster/event/events/EventAnimation.java +++ b/shared/java/top/fpsmaster/event/events/EventAnimation.java @@ -2,7 +2,6 @@ import top.fpsmaster.event.CancelableEvent; -import top.fpsmaster.event.Event; public class EventAnimation extends CancelableEvent { Type type; diff --git a/shared/java/top/fpsmaster/event/events/EventJoinServer.java b/shared/java/top/fpsmaster/event/events/EventJoinServer.java index 7b9ddea4..88983271 100644 --- a/shared/java/top/fpsmaster/event/events/EventJoinServer.java +++ b/shared/java/top/fpsmaster/event/events/EventJoinServer.java @@ -1,7 +1,6 @@ package top.fpsmaster.event.events; import top.fpsmaster.event.CancelableEvent; -import top.fpsmaster.event.Event; public class EventJoinServer extends CancelableEvent { } diff --git a/shared/java/top/fpsmaster/event/events/EventSendChatMessage.java b/shared/java/top/fpsmaster/event/events/EventSendChatMessage.java index 1d2593e2..956b1bb6 100644 --- a/shared/java/top/fpsmaster/event/events/EventSendChatMessage.java +++ b/shared/java/top/fpsmaster/event/events/EventSendChatMessage.java @@ -1,7 +1,6 @@ package top.fpsmaster.event.events; import top.fpsmaster.event.CancelableEvent; -import top.fpsmaster.event.Event; public class EventSendChatMessage extends CancelableEvent { public String msg; diff --git a/shared/java/top/fpsmaster/event/events/EventValueChange.java b/shared/java/top/fpsmaster/event/events/EventValueChange.java index 0e2ecce7..0f9a94fa 100644 --- a/shared/java/top/fpsmaster/event/events/EventValueChange.java +++ b/shared/java/top/fpsmaster/event/events/EventValueChange.java @@ -1,7 +1,6 @@ package top.fpsmaster.event.events; import top.fpsmaster.event.CancelableEvent; -import top.fpsmaster.event.Event; import top.fpsmaster.features.settings.Setting; public class EventValueChange extends CancelableEvent { diff --git a/shared/java/top/fpsmaster/exception/ExceptionHandler.java b/shared/java/top/fpsmaster/exception/ExceptionHandler.java index f4871b9d..6d7b1049 100644 --- a/shared/java/top/fpsmaster/exception/ExceptionHandler.java +++ b/shared/java/top/fpsmaster/exception/ExceptionHandler.java @@ -2,9 +2,6 @@ import top.fpsmaster.modules.logger.ClientLogger; -import java.io.PrintWriter; -import java.io.StringWriter; - /** * Centralized exception handler for the FPSMaster application. * This class provides methods to handle different types of exceptions in a consistent way. diff --git a/shared/java/top/fpsmaster/features/GlobalSubmitter.java b/shared/java/top/fpsmaster/features/GlobalSubmitter.java index eb2c1dd9..7943ef91 100644 --- a/shared/java/top/fpsmaster/features/GlobalSubmitter.java +++ b/shared/java/top/fpsmaster/features/GlobalSubmitter.java @@ -11,12 +11,10 @@ import top.fpsmaster.interfaces.ProviderManager; import top.fpsmaster.modules.music.MusicPlayer; import top.fpsmaster.ui.notification.NotificationManager; -import top.fpsmaster.utils.OptifineUtil; import top.fpsmaster.utils.Utility; import top.fpsmaster.utils.math.MathTimer; import top.fpsmaster.utils.render.StencilUtil; import top.fpsmaster.utils.render.shader.KawaseBlur; -import top.fpsmaster.utils.render.shader.RoundedUtil; import top.fpsmaster.websocket.client.WsClient; import java.net.URISyntaxException; diff --git a/shared/java/top/fpsmaster/features/command/CommandManager.java b/shared/java/top/fpsmaster/features/command/CommandManager.java index 0786b79f..422ebf23 100644 --- a/shared/java/top/fpsmaster/features/command/CommandManager.java +++ b/shared/java/top/fpsmaster/features/command/CommandManager.java @@ -4,7 +4,6 @@ import top.fpsmaster.event.EventDispatcher; import top.fpsmaster.event.Subscribe; import top.fpsmaster.event.events.EventSendChatMessage; -import top.fpsmaster.exception.FileException; import top.fpsmaster.features.command.impl.AI; import top.fpsmaster.features.command.impl.Dev; import top.fpsmaster.features.command.impl.IRCChat; diff --git a/shared/java/top/fpsmaster/features/command/impl/AI.java b/shared/java/top/fpsmaster/features/command/impl/AI.java index 7ea0d1fd..e23f401f 100644 --- a/shared/java/top/fpsmaster/features/command/impl/AI.java +++ b/shared/java/top/fpsmaster/features/command/impl/AI.java @@ -1,16 +1,13 @@ package top.fpsmaster.features.command.impl; -import com.google.gson.JsonArray; import top.fpsmaster.FPSMaster; import top.fpsmaster.exception.FileException; import top.fpsmaster.features.command.Command; -import top.fpsmaster.modules.client.AsyncTask; import top.fpsmaster.modules.lua.LuaManager; import top.fpsmaster.modules.lua.LuaScript; import top.fpsmaster.modules.lua.RawLua; import top.fpsmaster.utils.Utility; import top.fpsmaster.utils.os.FileUtils; -import top.fpsmaster.utils.thirdparty.openai.OpenAI; import top.fpsmaster.utils.thirdparty.openai.OpenAIClient; import java.io.IOException; diff --git a/shared/java/top/fpsmaster/features/command/impl/Dev.java b/shared/java/top/fpsmaster/features/command/impl/Dev.java index 70741caf..71fa0645 100644 --- a/shared/java/top/fpsmaster/features/command/impl/Dev.java +++ b/shared/java/top/fpsmaster/features/command/impl/Dev.java @@ -1,10 +1,7 @@ package top.fpsmaster.features.command.impl; import net.minecraft.client.Minecraft; -import top.fpsmaster.FPSMaster; -import top.fpsmaster.exception.FileException; import top.fpsmaster.features.command.Command; -import top.fpsmaster.interfaces.ProviderManager; import top.fpsmaster.modules.dev.DevMode; import top.fpsmaster.modules.lua.LuaManager; import top.fpsmaster.ui.devspace.DevSpace; diff --git a/shared/java/top/fpsmaster/features/command/impl/IRCChat.java b/shared/java/top/fpsmaster/features/command/impl/IRCChat.java index f06bb23f..5c82cadc 100644 --- a/shared/java/top/fpsmaster/features/command/impl/IRCChat.java +++ b/shared/java/top/fpsmaster/features/command/impl/IRCChat.java @@ -3,13 +3,10 @@ import top.fpsmaster.FPSMaster; import top.fpsmaster.features.command.Command; import top.fpsmaster.features.impl.utility.IRC; -import top.fpsmaster.features.impl.utility.SkinChanger; import top.fpsmaster.interfaces.ProviderManager; import top.fpsmaster.modules.account.AccountManager; import top.fpsmaster.utils.Utility; -import static top.fpsmaster.utils.Utility.mc; - public class IRCChat extends Command { public IRCChat() { diff --git a/shared/java/top/fpsmaster/features/impl/InterfaceModule.java b/shared/java/top/fpsmaster/features/impl/InterfaceModule.java index a4beab2b..7c7594a0 100644 --- a/shared/java/top/fpsmaster/features/impl/InterfaceModule.java +++ b/shared/java/top/fpsmaster/features/impl/InterfaceModule.java @@ -6,7 +6,7 @@ import top.fpsmaster.features.settings.impl.ColorSetting; import top.fpsmaster.features.settings.impl.NumberSetting; -import java.awt.Color; +import java.awt.*; public class InterfaceModule extends Module { diff --git a/shared/java/top/fpsmaster/features/impl/interfaces/ArmorDisplay.java b/shared/java/top/fpsmaster/features/impl/interfaces/ArmorDisplay.java index 8aba6c1a..7d540d83 100644 --- a/shared/java/top/fpsmaster/features/impl/interfaces/ArmorDisplay.java +++ b/shared/java/top/fpsmaster/features/impl/interfaces/ArmorDisplay.java @@ -2,11 +2,8 @@ import top.fpsmaster.features.impl.InterfaceModule; import top.fpsmaster.features.manager.Category; -import top.fpsmaster.features.settings.impl.ColorSetting; import top.fpsmaster.features.settings.impl.ModeSetting; -import java.awt.Color; - public class ArmorDisplay extends InterfaceModule { public static ModeSetting mode = new ModeSetting("Mode", 0, "SimpleHoriz", "SimpleVertical", "Vertical"); diff --git a/shared/java/top/fpsmaster/features/impl/interfaces/CPSDisplay.java b/shared/java/top/fpsmaster/features/impl/interfaces/CPSDisplay.java index 39b984a1..9b32a6c3 100644 --- a/shared/java/top/fpsmaster/features/impl/interfaces/CPSDisplay.java +++ b/shared/java/top/fpsmaster/features/impl/interfaces/CPSDisplay.java @@ -7,7 +7,7 @@ import top.fpsmaster.features.manager.Category; import top.fpsmaster.features.settings.impl.ColorSetting; -import java.awt.Color; +import java.awt.*; import java.util.LinkedList; public class CPSDisplay extends InterfaceModule { diff --git a/shared/java/top/fpsmaster/features/impl/interfaces/ComboDisplay.java b/shared/java/top/fpsmaster/features/impl/interfaces/ComboDisplay.java index 602e7ded..af0527da 100644 --- a/shared/java/top/fpsmaster/features/impl/interfaces/ComboDisplay.java +++ b/shared/java/top/fpsmaster/features/impl/interfaces/ComboDisplay.java @@ -9,7 +9,7 @@ import top.fpsmaster.features.settings.impl.ColorSetting; import top.fpsmaster.interfaces.ProviderManager; -import java.awt.Color; +import java.awt.*; public class ComboDisplay extends InterfaceModule { diff --git a/shared/java/top/fpsmaster/features/impl/interfaces/FPSDisplay.java b/shared/java/top/fpsmaster/features/impl/interfaces/FPSDisplay.java index 1930c7e4..ea793e57 100644 --- a/shared/java/top/fpsmaster/features/impl/interfaces/FPSDisplay.java +++ b/shared/java/top/fpsmaster/features/impl/interfaces/FPSDisplay.java @@ -4,7 +4,7 @@ import top.fpsmaster.features.manager.Category; import top.fpsmaster.features.settings.impl.ColorSetting; -import java.awt.Color; +import java.awt.*; public class FPSDisplay extends InterfaceModule { diff --git a/shared/java/top/fpsmaster/features/impl/interfaces/Keystrokes.java b/shared/java/top/fpsmaster/features/impl/interfaces/Keystrokes.java index 14a0a3a0..2a12adc8 100644 --- a/shared/java/top/fpsmaster/features/impl/interfaces/Keystrokes.java +++ b/shared/java/top/fpsmaster/features/impl/interfaces/Keystrokes.java @@ -3,7 +3,8 @@ import top.fpsmaster.features.impl.InterfaceModule; import top.fpsmaster.features.manager.Category; import top.fpsmaster.features.settings.impl.ColorSetting; -import java.awt.Color; + +import java.awt.*; public class Keystrokes extends InterfaceModule { public static ColorSetting pressedColor = new ColorSetting("PressedColor", new Color(255, 255, 255, 120)); diff --git a/shared/java/top/fpsmaster/features/impl/interfaces/ModsList.java b/shared/java/top/fpsmaster/features/impl/interfaces/ModsList.java index 0b3aa785..d862d8b9 100644 --- a/shared/java/top/fpsmaster/features/impl/interfaces/ModsList.java +++ b/shared/java/top/fpsmaster/features/impl/interfaces/ModsList.java @@ -6,7 +6,7 @@ import top.fpsmaster.features.settings.impl.ColorSetting; import top.fpsmaster.features.settings.impl.TextSetting; -import java.awt.Color; +import java.awt.*; public class ModsList extends InterfaceModule { diff --git a/shared/java/top/fpsmaster/features/impl/interfaces/MusicOverlay.java b/shared/java/top/fpsmaster/features/impl/interfaces/MusicOverlay.java index 08ca7f7b..194192c9 100644 --- a/shared/java/top/fpsmaster/features/impl/interfaces/MusicOverlay.java +++ b/shared/java/top/fpsmaster/features/impl/interfaces/MusicOverlay.java @@ -11,7 +11,7 @@ import top.fpsmaster.modules.music.JLayerHelper; import top.fpsmaster.utils.math.MathTimer; -import java.awt.Color; +import java.awt.*; public class MusicOverlay extends InterfaceModule { public static final NumberSetting amplitude = new NumberSetting("Amplitude", 10, 0, 10, 0.1); diff --git a/shared/java/top/fpsmaster/features/impl/interfaces/PingDisplay.java b/shared/java/top/fpsmaster/features/impl/interfaces/PingDisplay.java index f4ba04ad..c156a313 100644 --- a/shared/java/top/fpsmaster/features/impl/interfaces/PingDisplay.java +++ b/shared/java/top/fpsmaster/features/impl/interfaces/PingDisplay.java @@ -4,7 +4,7 @@ import top.fpsmaster.features.manager.Category; import top.fpsmaster.features.settings.impl.ColorSetting; -import java.awt.Color; +import java.awt.*; public class PingDisplay extends InterfaceModule { public PingDisplay() { diff --git a/shared/java/top/fpsmaster/features/impl/interfaces/ReachDisplay.java b/shared/java/top/fpsmaster/features/impl/interfaces/ReachDisplay.java index 25affbb7..e2cc5d11 100644 --- a/shared/java/top/fpsmaster/features/impl/interfaces/ReachDisplay.java +++ b/shared/java/top/fpsmaster/features/impl/interfaces/ReachDisplay.java @@ -6,7 +6,6 @@ import net.minecraft.util.EntitySelectors; import net.minecraft.util.MovingObjectPosition; import net.minecraft.util.Vec3; -import org.jetbrains.annotations.NotNull; import top.fpsmaster.event.Subscribe; import top.fpsmaster.event.events.EventAttack; import top.fpsmaster.features.impl.InterfaceModule; @@ -16,7 +15,7 @@ import top.fpsmaster.wrapper.util.WrapperAxisAlignedBB; import top.fpsmaster.wrapper.util.WrapperVec3; -import java.awt.Color; +import java.awt.*; import java.util.List; import static top.fpsmaster.utils.Utility.mc; diff --git a/shared/java/top/fpsmaster/features/impl/interfaces/TargetDisplay.java b/shared/java/top/fpsmaster/features/impl/interfaces/TargetDisplay.java index 11544245..3d36126f 100644 --- a/shared/java/top/fpsmaster/features/impl/interfaces/TargetDisplay.java +++ b/shared/java/top/fpsmaster/features/impl/interfaces/TargetDisplay.java @@ -14,8 +14,7 @@ import top.fpsmaster.features.settings.impl.ModeSetting; import top.fpsmaster.interfaces.ProviderManager; -import java.awt.Color; -import java.util.List; +import java.awt.*; public class TargetDisplay extends InterfaceModule { private ModeSetting targetESP = new ModeSetting("TargetESP", 0, "glow", "none"); diff --git a/shared/java/top/fpsmaster/features/impl/optimizes/OldAnimations.java b/shared/java/top/fpsmaster/features/impl/optimizes/OldAnimations.java index 4c43dbbb..426c5bb9 100644 --- a/shared/java/top/fpsmaster/features/impl/optimizes/OldAnimations.java +++ b/shared/java/top/fpsmaster/features/impl/optimizes/OldAnimations.java @@ -2,7 +2,6 @@ import net.minecraft.client.Minecraft; import net.minecraft.client.entity.EntityPlayerSP; -import net.minecraft.entity.EntityLivingBase; import net.minecraft.item.ItemStack; import net.minecraft.network.play.server.S0BPacketAnimation; import net.minecraft.potion.Potion; @@ -14,7 +13,6 @@ import top.fpsmaster.features.settings.impl.BooleanSetting; import top.fpsmaster.features.settings.impl.ModeSetting; import top.fpsmaster.features.settings.impl.NumberSetting; -import top.fpsmaster.interfaces.ProviderManager; import static top.fpsmaster.utils.Utility.mc; diff --git a/shared/java/top/fpsmaster/features/impl/optimizes/Performance.java b/shared/java/top/fpsmaster/features/impl/optimizes/Performance.java index ede29ca0..e82d8c1a 100644 --- a/shared/java/top/fpsmaster/features/impl/optimizes/Performance.java +++ b/shared/java/top/fpsmaster/features/impl/optimizes/Performance.java @@ -1,10 +1,7 @@ package top.fpsmaster.features.impl.optimizes; -import jdk.jfr.events.ActiveSettingEvent; import net.minecraft.entity.Entity; import net.minecraft.world.World; -import net.minecraftforge.fml.common.gameevent.TickEvent; -import top.fpsmaster.event.Subscribe; import top.fpsmaster.features.manager.Category; import top.fpsmaster.features.manager.Module; import top.fpsmaster.features.settings.impl.BooleanSetting; @@ -12,7 +9,6 @@ import top.fpsmaster.wrapper.mods.WrapperPerformance; import java.util.ArrayList; -import java.util.HashMap; public class Performance extends Module { diff --git a/shared/java/top/fpsmaster/features/impl/render/Crosshair.java b/shared/java/top/fpsmaster/features/impl/render/Crosshair.java index a7fdcba0..b3a1974b 100644 --- a/shared/java/top/fpsmaster/features/impl/render/Crosshair.java +++ b/shared/java/top/fpsmaster/features/impl/render/Crosshair.java @@ -13,11 +13,11 @@ import top.fpsmaster.features.settings.impl.BooleanSetting; import top.fpsmaster.features.settings.impl.ColorSetting; import top.fpsmaster.features.settings.impl.NumberSetting; +import top.fpsmaster.interfaces.ProviderManager; import top.fpsmaster.utils.math.animation.AnimationUtils; import top.fpsmaster.utils.render.Render2DUtils; -import top.fpsmaster.interfaces.ProviderManager; -import java.awt.Color; +import java.awt.*; public class Crosshair extends Module { private final NumberSetting dynamic = new NumberSetting("Dynamic", 4, 0, 10, 0.1); diff --git a/shared/java/top/fpsmaster/features/impl/render/DamageIndicator.java b/shared/java/top/fpsmaster/features/impl/render/DamageIndicator.java index 64ce9dbc..c64aca30 100644 --- a/shared/java/top/fpsmaster/features/impl/render/DamageIndicator.java +++ b/shared/java/top/fpsmaster/features/impl/render/DamageIndicator.java @@ -2,9 +2,7 @@ import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.GlStateManager; -import net.minecraft.entity.Entity; import net.minecraft.entity.EntityLivingBase; -import net.minecraft.entity.item.EntityTNTPrimed; import org.lwjgl.opengl.GL11; import top.fpsmaster.event.Subscribe; import top.fpsmaster.event.events.EventAttack; @@ -14,12 +12,10 @@ import top.fpsmaster.features.manager.Module; import top.fpsmaster.interfaces.ProviderManager; import top.fpsmaster.utils.math.MathTimer; -import top.fpsmaster.wrapper.entities.EntityTNTPrimedUtil; import java.awt.*; import java.text.DecimalFormat; import java.util.ArrayList; -import java.util.HashMap; public class DamageIndicator extends Module { private EntityLivingBase lastAttack; diff --git a/shared/java/top/fpsmaster/features/impl/render/FireModifier.java b/shared/java/top/fpsmaster/features/impl/render/FireModifier.java index f30ef102..fc59ea52 100644 --- a/shared/java/top/fpsmaster/features/impl/render/FireModifier.java +++ b/shared/java/top/fpsmaster/features/impl/render/FireModifier.java @@ -6,7 +6,7 @@ import top.fpsmaster.features.settings.impl.ColorSetting; import top.fpsmaster.features.settings.impl.NumberSetting; -import java.awt.Color; +import java.awt.*; public class FireModifier extends Module { diff --git a/shared/java/top/fpsmaster/features/impl/render/HitColor.java b/shared/java/top/fpsmaster/features/impl/render/HitColor.java index c24709fb..6e758e42 100644 --- a/shared/java/top/fpsmaster/features/impl/render/HitColor.java +++ b/shared/java/top/fpsmaster/features/impl/render/HitColor.java @@ -4,7 +4,7 @@ import top.fpsmaster.features.manager.Module; import top.fpsmaster.features.settings.impl.ColorSetting; -import java.awt.Color; +import java.awt.*; public class HitColor extends Module { diff --git a/shared/java/top/fpsmaster/features/impl/utility/ChatBot.java b/shared/java/top/fpsmaster/features/impl/utility/ChatBot.java index 1c02fbd7..2b1b3dee 100644 --- a/shared/java/top/fpsmaster/features/impl/utility/ChatBot.java +++ b/shared/java/top/fpsmaster/features/impl/utility/ChatBot.java @@ -1,25 +1,22 @@ package top.fpsmaster.features.impl.utility; -import com.google.gson.Gson; import com.google.gson.JsonArray; import com.google.gson.JsonObject; -import com.google.gson.JsonParser; import top.fpsmaster.FPSMaster; import top.fpsmaster.event.Subscribe; import top.fpsmaster.event.events.EventPacket; import top.fpsmaster.event.events.EventSendChatMessage; import top.fpsmaster.features.manager.Category; import top.fpsmaster.features.manager.Module; -import top.fpsmaster.features.settings.Setting; import top.fpsmaster.features.settings.impl.BooleanSetting; import top.fpsmaster.features.settings.impl.ModeSetting; import top.fpsmaster.features.settings.impl.NumberSetting; import top.fpsmaster.features.settings.impl.TextSetting; +import top.fpsmaster.interfaces.ProviderManager; +import top.fpsmaster.ui.notification.NotificationManager; import top.fpsmaster.utils.Utility; import top.fpsmaster.utils.math.MathTimer; import top.fpsmaster.utils.thirdparty.openai.OpenAI; -import top.fpsmaster.interfaces.ProviderManager; -import top.fpsmaster.ui.notification.NotificationManager; import java.util.ArrayList; import java.util.regex.Pattern; diff --git a/shared/java/top/fpsmaster/features/impl/utility/IRC.java b/shared/java/top/fpsmaster/features/impl/utility/IRC.java index 8c4a1c83..281f1ee3 100644 --- a/shared/java/top/fpsmaster/features/impl/utility/IRC.java +++ b/shared/java/top/fpsmaster/features/impl/utility/IRC.java @@ -1,19 +1,8 @@ package top.fpsmaster.features.impl.utility; -import top.fpsmaster.FPSMaster; -import top.fpsmaster.event.Subscribe; -import top.fpsmaster.event.events.EventTick; -import top.fpsmaster.features.impl.interfaces.ClientSettings; import top.fpsmaster.features.manager.Category; import top.fpsmaster.features.manager.Module; import top.fpsmaster.features.settings.impl.BooleanSetting; -import top.fpsmaster.utils.Utility; -import top.fpsmaster.utils.math.MathTimer; -import top.fpsmaster.websocket.client.WsClient; -import top.fpsmaster.interfaces.ProviderManager; -import top.fpsmaster.modules.dev.DevMode; - -import java.net.URISyntaxException; public class IRC extends Module { public static boolean using = false; diff --git a/shared/java/top/fpsmaster/features/impl/utility/Sprint.java b/shared/java/top/fpsmaster/features/impl/utility/Sprint.java index 8e0d98e3..1e4c4cf8 100644 --- a/shared/java/top/fpsmaster/features/impl/utility/Sprint.java +++ b/shared/java/top/fpsmaster/features/impl/utility/Sprint.java @@ -1,16 +1,12 @@ package top.fpsmaster.features.impl.utility; -import net.minecraft.potion.Potion; import top.fpsmaster.event.Subscribe; import top.fpsmaster.event.events.EventKey; import top.fpsmaster.event.events.EventUpdate; import top.fpsmaster.features.impl.InterfaceModule; import top.fpsmaster.features.manager.Category; -import top.fpsmaster.features.manager.Module; import top.fpsmaster.features.settings.impl.BooleanSetting; import top.fpsmaster.interfaces.ProviderManager; -import top.fpsmaster.utils.Utility; -import top.fpsmaster.wrapper.MinecraftProvider; import static top.fpsmaster.utils.Utility.mc; diff --git a/shared/java/top/fpsmaster/features/impl/utility/TNTTimer.java b/shared/java/top/fpsmaster/features/impl/utility/TNTTimer.java index e2c063ac..50c90d86 100644 --- a/shared/java/top/fpsmaster/features/impl/utility/TNTTimer.java +++ b/shared/java/top/fpsmaster/features/impl/utility/TNTTimer.java @@ -10,7 +10,7 @@ import top.fpsmaster.interfaces.ProviderManager; import top.fpsmaster.wrapper.entities.EntityTNTPrimedUtil; -import java.awt.Color; +import java.awt.*; import java.text.DecimalFormat; public class TNTTimer extends Module { diff --git a/shared/java/top/fpsmaster/features/manager/Module.java b/shared/java/top/fpsmaster/features/manager/Module.java index 5c768908..769b6e23 100644 --- a/shared/java/top/fpsmaster/features/manager/Module.java +++ b/shared/java/top/fpsmaster/features/manager/Module.java @@ -4,12 +4,7 @@ import top.fpsmaster.FPSMaster; import top.fpsmaster.event.EventDispatcher; import top.fpsmaster.features.settings.Setting; -import top.fpsmaster.features.settings.impl.BooleanSetting; -import top.fpsmaster.features.settings.impl.BindSetting; -import top.fpsmaster.features.settings.impl.ModeSetting; -import top.fpsmaster.features.settings.impl.NumberSetting; -import top.fpsmaster.features.settings.impl.TextSetting; -import top.fpsmaster.features.settings.impl.ColorSetting; +import top.fpsmaster.features.settings.impl.*; import top.fpsmaster.interfaces.ProviderManager; import top.fpsmaster.ui.notification.NotificationManager; diff --git a/shared/java/top/fpsmaster/features/manager/ModuleManager.java b/shared/java/top/fpsmaster/features/manager/ModuleManager.java index d5fdec70..31821327 100644 --- a/shared/java/top/fpsmaster/features/manager/ModuleManager.java +++ b/shared/java/top/fpsmaster/features/manager/ModuleManager.java @@ -6,16 +6,15 @@ import top.fpsmaster.event.EventDispatcher; import top.fpsmaster.event.Subscribe; import top.fpsmaster.event.events.EventKey; -import top.fpsmaster.modules.logger.ClientLogger; import top.fpsmaster.features.impl.interfaces.*; import top.fpsmaster.features.impl.optimizes.*; import top.fpsmaster.features.impl.render.*; import top.fpsmaster.features.impl.utility.*; import top.fpsmaster.interfaces.ProviderManager; +import top.fpsmaster.modules.logger.ClientLogger; import top.fpsmaster.ui.click.MainPanel; import top.fpsmaster.ui.click.modules.ModuleRenderer; import top.fpsmaster.ui.devspace.DevSpace; -import top.fpsmaster.utils.Utility; import java.util.ArrayList; import java.util.List; diff --git a/shared/java/top/fpsmaster/features/settings/impl/ColorSetting.java b/shared/java/top/fpsmaster/features/settings/impl/ColorSetting.java index b090ad51..608ef5ad 100644 --- a/shared/java/top/fpsmaster/features/settings/impl/ColorSetting.java +++ b/shared/java/top/fpsmaster/features/settings/impl/ColorSetting.java @@ -2,7 +2,8 @@ import top.fpsmaster.features.settings.Setting; import top.fpsmaster.features.settings.impl.utils.CustomColor; -import java.awt.Color; + +import java.awt.*; public class ColorSetting extends Setting { diff --git a/shared/java/top/fpsmaster/features/settings/impl/utils/CustomColor.java b/shared/java/top/fpsmaster/features/settings/impl/utils/CustomColor.java index a13e3e11..6f741a67 100644 --- a/shared/java/top/fpsmaster/features/settings/impl/utils/CustomColor.java +++ b/shared/java/top/fpsmaster/features/settings/impl/utils/CustomColor.java @@ -1,7 +1,8 @@ package top.fpsmaster.features.settings.impl.utils; import top.fpsmaster.utils.render.Render2DUtils; -import java.awt.Color; + +import java.awt.*; public class CustomColor { diff --git a/shared/java/top/fpsmaster/font/FontManager.java b/shared/java/top/fpsmaster/font/FontManager.java index 46ef9d63..b71a8996 100644 --- a/shared/java/top/fpsmaster/font/FontManager.java +++ b/shared/java/top/fpsmaster/font/FontManager.java @@ -1,6 +1,5 @@ package top.fpsmaster.font; -import top.fpsmaster.font.impl.StringCache; import top.fpsmaster.font.impl.UFontRenderer; import java.util.HashMap; diff --git a/shared/java/top/fpsmaster/font/impl/GlyphCache.java b/shared/java/top/fpsmaster/font/impl/GlyphCache.java index 5fdb11ff..1f9efcc6 100644 --- a/shared/java/top/fpsmaster/font/impl/GlyphCache.java +++ b/shared/java/top/fpsmaster/font/impl/GlyphCache.java @@ -3,6 +3,7 @@ import net.minecraft.client.renderer.GLAllocation; import net.minecraft.client.renderer.GlStateManager; import org.lwjgl.opengl.GL11; + import java.awt.*; import java.awt.font.FontRenderContext; import java.awt.font.GlyphVector; @@ -11,8 +12,8 @@ import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.nio.IntBuffer; -import java.util.List; import java.util.*; +import java.util.List; /** * The GlyphCache class is responsible for caching pre-rendered images of every glyph using OpenGL textures. This class is also diff --git a/shared/java/top/fpsmaster/font/impl/UFontRenderer.java b/shared/java/top/fpsmaster/font/impl/UFontRenderer.java index efb358ce..caec5aa1 100644 --- a/shared/java/top/fpsmaster/font/impl/UFontRenderer.java +++ b/shared/java/top/fpsmaster/font/impl/UFontRenderer.java @@ -5,14 +5,11 @@ import net.minecraft.util.ResourceLocation; import top.fpsmaster.interfaces.ProviderManager; import top.fpsmaster.modules.client.GlobalTextFilter; -import top.fpsmaster.font.FontManager; import top.fpsmaster.modules.logger.ClientLogger; import top.fpsmaster.utils.os.FileUtils; -import java.awt.Color; -import java.awt.Font; +import java.awt.*; import java.io.File; -import java.io.FileInputStream; import java.io.InputStream; import java.nio.file.Files; diff --git a/shared/java/top/fpsmaster/interfaces/game/IMinecraftProvider.java b/shared/java/top/fpsmaster/interfaces/game/IMinecraftProvider.java index ae182b21..629aa416 100644 --- a/shared/java/top/fpsmaster/interfaces/game/IMinecraftProvider.java +++ b/shared/java/top/fpsmaster/interfaces/game/IMinecraftProvider.java @@ -7,6 +7,7 @@ import net.minecraft.item.ItemStack; import net.minecraft.util.Session; import top.fpsmaster.interfaces.IProvider; + import java.io.File; import java.util.Collection; diff --git a/shared/java/top/fpsmaster/modules/config/ConfigManager.java b/shared/java/top/fpsmaster/modules/config/ConfigManager.java index 8caf12a2..4b87f40d 100644 --- a/shared/java/top/fpsmaster/modules/config/ConfigManager.java +++ b/shared/java/top/fpsmaster/modules/config/ConfigManager.java @@ -1,6 +1,9 @@ package top.fpsmaster.modules.config; -import com.google.gson.*; +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; import top.fpsmaster.FPSMaster; import top.fpsmaster.exception.FileException; import top.fpsmaster.features.impl.optimizes.OldAnimations; @@ -15,7 +18,6 @@ import top.fpsmaster.ui.custom.Position; import top.fpsmaster.utils.os.FileUtils; -import java.util.HashMap; import java.util.Map; public class ConfigManager { diff --git a/shared/java/top/fpsmaster/modules/i18n/Language.java b/shared/java/top/fpsmaster/modules/i18n/Language.java index 808504f5..5ee75c6c 100644 --- a/shared/java/top/fpsmaster/modules/i18n/Language.java +++ b/shared/java/top/fpsmaster/modules/i18n/Language.java @@ -3,9 +3,6 @@ import top.fpsmaster.exception.FileException; import top.fpsmaster.utils.os.FileUtils; -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Paths; import java.util.HashMap; import java.util.Map; diff --git a/shared/java/top/fpsmaster/modules/lua/LuaManager.java b/shared/java/top/fpsmaster/modules/lua/LuaManager.java index 2cbc8364..5351b251 100644 --- a/shared/java/top/fpsmaster/modules/lua/LuaManager.java +++ b/shared/java/top/fpsmaster/modules/lua/LuaManager.java @@ -9,22 +9,15 @@ import top.fpsmaster.exception.FileException; import top.fpsmaster.features.manager.Module; import top.fpsmaster.interfaces.ProviderManager; -import top.fpsmaster.modules.dev.DevMode; -import top.fpsmaster.modules.i18n.Language; import top.fpsmaster.modules.lua.parser.LuaParser; -import top.fpsmaster.modules.lua.parser.ParseError; import top.fpsmaster.utils.Utility; import top.fpsmaster.utils.os.FileUtils; import top.fpsmaster.utils.render.Render2DUtils; -import top.fpsmaster.wrapper.MinecraftProvider; -import top.fpsmaster.wrapper.blockpos.WrapperBlockPos; import java.awt.*; import java.io.File; import java.util.ArrayList; -import java.util.HashMap; import java.util.Map; -import java.util.Scanner; import java.util.stream.Collectors; public class LuaManager { diff --git a/shared/java/top/fpsmaster/modules/lua/LuaModule.java b/shared/java/top/fpsmaster/modules/lua/LuaModule.java index f7d5349f..06280bd8 100644 --- a/shared/java/top/fpsmaster/modules/lua/LuaModule.java +++ b/shared/java/top/fpsmaster/modules/lua/LuaModule.java @@ -5,7 +5,6 @@ import top.fpsmaster.event.Subscribe; import top.fpsmaster.event.events.*; import top.fpsmaster.features.manager.Category; -import top.fpsmaster.features.manager.Module; import java.util.HashMap; import java.util.Map; diff --git a/shared/java/top/fpsmaster/modules/lua/parser/Statement.java b/shared/java/top/fpsmaster/modules/lua/parser/Statement.java index 85df408d..6eb27887 100644 --- a/shared/java/top/fpsmaster/modules/lua/parser/Statement.java +++ b/shared/java/top/fpsmaster/modules/lua/parser/Statement.java @@ -1,8 +1,6 @@ package top.fpsmaster.modules.lua.parser; -import java.util.Arrays; import java.util.List; -import java.util.Map; public abstract class Statement { public static class ExpressionStatement extends Statement { diff --git a/shared/java/top/fpsmaster/modules/music/IngameOverlay.java b/shared/java/top/fpsmaster/modules/music/IngameOverlay.java index cc81cc30..97a552c9 100644 --- a/shared/java/top/fpsmaster/modules/music/IngameOverlay.java +++ b/shared/java/top/fpsmaster/modules/music/IngameOverlay.java @@ -5,13 +5,12 @@ import top.fpsmaster.FPSMaster; import top.fpsmaster.features.impl.interfaces.MusicOverlay; import top.fpsmaster.font.impl.UFontRenderer; -import top.fpsmaster.modules.music.MusicPlayer; import top.fpsmaster.modules.music.netease.Music; import top.fpsmaster.utils.Utility; import top.fpsmaster.utils.math.animation.AnimationUtils; import top.fpsmaster.utils.render.Render2DUtils; -import java.awt.Color; +import java.awt.*; public class IngameOverlay { private static float songProgress = 0f; diff --git a/shared/java/top/fpsmaster/modules/music/JLayerHelper.java b/shared/java/top/fpsmaster/modules/music/JLayerHelper.java index d3d7369a..486fdbe9 100644 --- a/shared/java/top/fpsmaster/modules/music/JLayerHelper.java +++ b/shared/java/top/fpsmaster/modules/music/JLayerHelper.java @@ -8,6 +8,7 @@ import java.io.File; import java.io.IOException; import java.util.Arrays; + import static java.lang.Math.min; import static java.lang.Math.sqrt; diff --git a/shared/java/top/fpsmaster/modules/music/netease/Music.java b/shared/java/top/fpsmaster/modules/music/netease/Music.java index 891cd673..ab26f875 100644 --- a/shared/java/top/fpsmaster/modules/music/netease/Music.java +++ b/shared/java/top/fpsmaster/modules/music/netease/Music.java @@ -7,10 +7,8 @@ import top.fpsmaster.modules.logger.ClientLogger; import top.fpsmaster.modules.music.AbstractMusic; import top.fpsmaster.modules.music.MusicPlayer; -import top.fpsmaster.modules.music.MusicPlayer; import top.fpsmaster.modules.music.netease.deserialize.MusicWrapper; import top.fpsmaster.utils.os.FileUtils; -import top.fpsmaster.utils.os.FileUtils; import top.fpsmaster.utils.os.HttpRequest; import java.io.File; diff --git a/shared/java/top/fpsmaster/modules/music/netease/NeteaseApi.java b/shared/java/top/fpsmaster/modules/music/netease/NeteaseApi.java index 24f2029a..16afa015 100644 --- a/shared/java/top/fpsmaster/modules/music/netease/NeteaseApi.java +++ b/shared/java/top/fpsmaster/modules/music/netease/NeteaseApi.java @@ -2,8 +2,6 @@ import top.fpsmaster.utils.os.HttpRequest; -import java.io.IOException; - public class NeteaseApi { private static final String BASE_URL = "https://music.skidder.top/"; diff --git a/shared/java/top/fpsmaster/modules/music/netease/deserialize/MusicWrapper.java b/shared/java/top/fpsmaster/modules/music/netease/deserialize/MusicWrapper.java index 4bf87fe0..1062a390 100644 --- a/shared/java/top/fpsmaster/modules/music/netease/deserialize/MusicWrapper.java +++ b/shared/java/top/fpsmaster/modules/music/netease/deserialize/MusicWrapper.java @@ -12,7 +12,6 @@ import top.fpsmaster.modules.music.netease.Music; import top.fpsmaster.modules.music.netease.NeteaseApi; -import java.io.IOException; import java.net.URLEncoder; import java.util.Iterator; diff --git a/shared/java/top/fpsmaster/ui/Compass.java b/shared/java/top/fpsmaster/ui/Compass.java index 3b3d56f7..bc1a5646 100644 --- a/shared/java/top/fpsmaster/ui/Compass.java +++ b/shared/java/top/fpsmaster/ui/Compass.java @@ -6,7 +6,6 @@ import net.minecraft.client.renderer.GlStateManager; import org.lwjgl.opengl.GL11; import top.fpsmaster.FPSMaster; -import top.fpsmaster.features.impl.interfaces.ClientSettings; import top.fpsmaster.interfaces.ProviderManager; import top.fpsmaster.utils.render.Render2DUtils; diff --git a/shared/java/top/fpsmaster/ui/click/MainPanel.java b/shared/java/top/fpsmaster/ui/click/MainPanel.java index 32033701..f50168c9 100644 --- a/shared/java/top/fpsmaster/ui/click/MainPanel.java +++ b/shared/java/top/fpsmaster/ui/click/MainPanel.java @@ -10,18 +10,17 @@ import top.fpsmaster.features.manager.Module; import top.fpsmaster.ui.ai.AIChatPanel; import top.fpsmaster.ui.click.component.ScrollContainer; -import top.fpsmaster.ui.click.music.MusicPanel; import top.fpsmaster.ui.click.modules.ModuleRenderer; +import top.fpsmaster.ui.click.music.MusicPanel; import top.fpsmaster.utils.math.animation.Animation; import top.fpsmaster.utils.math.animation.AnimationUtils; import top.fpsmaster.utils.math.animation.Type; import top.fpsmaster.utils.render.Render2DUtils; import top.fpsmaster.utils.render.ScaledGuiScreen; -import java.awt.Color; +import java.awt.*; import java.io.IOException; import java.util.LinkedList; -import java.util.Locale; public class MainPanel extends ScaledGuiScreen { boolean drag = false; diff --git a/shared/java/top/fpsmaster/ui/click/TestScreen.java b/shared/java/top/fpsmaster/ui/click/TestScreen.java index 595e41a8..2538d2ff 100644 --- a/shared/java/top/fpsmaster/ui/click/TestScreen.java +++ b/shared/java/top/fpsmaster/ui/click/TestScreen.java @@ -1,9 +1,6 @@ package top.fpsmaster.ui.click; -import net.minecraft.client.gui.GuiScreen; import net.minecraft.client.gui.ScaledResolution; -import net.minecraft.client.renderer.GlStateManager; -import org.lwjgl.opengl.GL11; import top.fpsmaster.utils.Utility; import top.fpsmaster.utils.render.Render2DUtils; import top.fpsmaster.utils.render.ScaledGuiScreen; diff --git a/shared/java/top/fpsmaster/ui/click/component/ScrollContainer.java b/shared/java/top/fpsmaster/ui/click/component/ScrollContainer.java index d399de8a..c220e0a5 100644 --- a/shared/java/top/fpsmaster/ui/click/component/ScrollContainer.java +++ b/shared/java/top/fpsmaster/ui/click/component/ScrollContainer.java @@ -5,7 +5,7 @@ import top.fpsmaster.utils.math.animation.AnimationUtils; import top.fpsmaster.utils.render.Render2DUtils; -import java.awt.Color; +import java.awt.*; public class ScrollContainer { private float wheel = 0f; diff --git a/shared/java/top/fpsmaster/ui/click/modules/ModuleRenderer.java b/shared/java/top/fpsmaster/ui/click/modules/ModuleRenderer.java index 98ad7cc0..ce890806 100644 --- a/shared/java/top/fpsmaster/ui/click/modules/ModuleRenderer.java +++ b/shared/java/top/fpsmaster/ui/click/modules/ModuleRenderer.java @@ -10,7 +10,6 @@ import top.fpsmaster.modules.lua.LuaModule; import top.fpsmaster.ui.click.MainPanel; import top.fpsmaster.ui.click.modules.impl.*; -import top.fpsmaster.utils.Utility; import top.fpsmaster.utils.math.animation.AnimationUtils; import top.fpsmaster.utils.math.animation.ColorAnimation; import top.fpsmaster.utils.math.animation.Type; @@ -21,10 +20,6 @@ import java.util.Locale; import java.util.function.Consumer; -import static org.lwjgl.opengl.GL11.*; -import static org.lwjgl.opengl.GL11.GL_DEPTH_TEST; -import static org.lwjgl.opengl.GL11.glEnable; - public class ModuleRenderer extends ValueRender { ArrayList> settingsRenderers = new ArrayList<>(); private float settingHeight = 0f; diff --git a/shared/java/top/fpsmaster/ui/click/modules/impl/BindSettingRender.java b/shared/java/top/fpsmaster/ui/click/modules/impl/BindSettingRender.java index 54411816..2b19f1ea 100644 --- a/shared/java/top/fpsmaster/ui/click/modules/impl/BindSettingRender.java +++ b/shared/java/top/fpsmaster/ui/click/modules/impl/BindSettingRender.java @@ -7,7 +7,6 @@ import top.fpsmaster.font.impl.UFontRenderer; import top.fpsmaster.ui.click.MainPanel; import top.fpsmaster.ui.click.modules.SettingRender; -import top.fpsmaster.utils.Utility; import top.fpsmaster.utils.math.animation.ColorAnimation; import top.fpsmaster.utils.render.Render2DUtils; diff --git a/shared/java/top/fpsmaster/ui/click/modules/impl/BooleanSettingRender.java b/shared/java/top/fpsmaster/ui/click/modules/impl/BooleanSettingRender.java index 42283836..03904eba 100644 --- a/shared/java/top/fpsmaster/ui/click/modules/impl/BooleanSettingRender.java +++ b/shared/java/top/fpsmaster/ui/click/modules/impl/BooleanSettingRender.java @@ -4,12 +4,11 @@ import top.fpsmaster.features.manager.Module; import top.fpsmaster.features.settings.impl.BooleanSetting; import top.fpsmaster.ui.click.modules.SettingRender; -import top.fpsmaster.utils.Utility; import top.fpsmaster.utils.math.animation.ColorAnimation; import top.fpsmaster.utils.math.animation.Type; import top.fpsmaster.utils.render.Render2DUtils; -import java.awt.Color; +import java.awt.*; import java.util.Locale; public class BooleanSettingRender extends SettingRender { diff --git a/shared/java/top/fpsmaster/ui/click/modules/impl/ColorSettingRender.java b/shared/java/top/fpsmaster/ui/click/modules/impl/ColorSettingRender.java index 6cf51324..fdc6ee27 100644 --- a/shared/java/top/fpsmaster/ui/click/modules/impl/ColorSettingRender.java +++ b/shared/java/top/fpsmaster/ui/click/modules/impl/ColorSettingRender.java @@ -10,10 +10,10 @@ import top.fpsmaster.ui.click.modules.SettingRender; import top.fpsmaster.utils.math.animation.AnimationUtils; import top.fpsmaster.utils.os.OSUtil; -import top.fpsmaster.utils.render.shader.GradientUtils; import top.fpsmaster.utils.render.Render2DUtils; +import top.fpsmaster.utils.render.shader.GradientUtils; -import java.awt.Color; +import java.awt.*; import java.util.Locale; import static java.lang.Math.max; diff --git a/shared/java/top/fpsmaster/ui/click/modules/impl/TextSettingRender.java b/shared/java/top/fpsmaster/ui/click/modules/impl/TextSettingRender.java index ef5319ac..342a08b0 100644 --- a/shared/java/top/fpsmaster/ui/click/modules/impl/TextSettingRender.java +++ b/shared/java/top/fpsmaster/ui/click/modules/impl/TextSettingRender.java @@ -3,11 +3,11 @@ import top.fpsmaster.FPSMaster; import top.fpsmaster.features.manager.Module; import top.fpsmaster.features.settings.impl.TextSetting; -import top.fpsmaster.ui.common.TextField; import top.fpsmaster.ui.click.modules.SettingRender; +import top.fpsmaster.ui.common.TextField; import top.fpsmaster.utils.render.Render2DUtils; -import java.awt.Color; +import java.awt.*; import java.util.Locale; public class TextSettingRender extends SettingRender { diff --git a/shared/java/top/fpsmaster/ui/click/music/MusicPanel.java b/shared/java/top/fpsmaster/ui/click/music/MusicPanel.java index 5d12fe88..50dc5714 100644 --- a/shared/java/top/fpsmaster/ui/click/music/MusicPanel.java +++ b/shared/java/top/fpsmaster/ui/click/music/MusicPanel.java @@ -20,10 +20,9 @@ import top.fpsmaster.utils.os.FileUtils; import top.fpsmaster.utils.render.Render2DUtils; -import java.awt.Color; +import java.awt.*; import java.io.File; import java.util.Base64; -import java.util.Map; import java.util.concurrent.atomic.AtomicReference; public class MusicPanel { diff --git a/shared/java/top/fpsmaster/ui/click/music/SearchBox.java b/shared/java/top/fpsmaster/ui/click/music/SearchBox.java index fe1f8252..d42d740f 100644 --- a/shared/java/top/fpsmaster/ui/click/music/SearchBox.java +++ b/shared/java/top/fpsmaster/ui/click/music/SearchBox.java @@ -7,10 +7,10 @@ import net.minecraft.util.ChatAllowedCharacters; import top.fpsmaster.FPSMaster; import top.fpsmaster.font.impl.UFontRenderer; -import top.fpsmaster.utils.math.MathUtils; import top.fpsmaster.utils.math.animation.ColorAnimation; import top.fpsmaster.utils.render.Render2DUtils; -import java.awt.Color; + +import java.awt.*; public class SearchBox extends Gui { private UFontRenderer font; diff --git a/shared/java/top/fpsmaster/ui/common/GuiButton.java b/shared/java/top/fpsmaster/ui/common/GuiButton.java index 13707409..171ff2af 100644 --- a/shared/java/top/fpsmaster/ui/common/GuiButton.java +++ b/shared/java/top/fpsmaster/ui/common/GuiButton.java @@ -4,7 +4,7 @@ import top.fpsmaster.utils.math.animation.ColorAnimation; import top.fpsmaster.utils.render.Render2DUtils; -import java.awt.Color; +import java.awt.*; public class GuiButton { diff --git a/shared/java/top/fpsmaster/ui/custom/Component.java b/shared/java/top/fpsmaster/ui/custom/Component.java index 859b61bf..9d76bf8b 100644 --- a/shared/java/top/fpsmaster/ui/custom/Component.java +++ b/shared/java/top/fpsmaster/ui/custom/Component.java @@ -6,16 +6,16 @@ import org.lwjgl.input.Mouse; import org.lwjgl.opengl.GL11; import top.fpsmaster.FPSMaster; -import top.fpsmaster.font.impl.UFontRenderer; import top.fpsmaster.features.impl.InterfaceModule; import top.fpsmaster.features.impl.interfaces.ClientSettings; +import top.fpsmaster.font.impl.UFontRenderer; +import top.fpsmaster.interfaces.ProviderManager; import top.fpsmaster.ui.click.MainPanel; import top.fpsmaster.utils.Utility; import top.fpsmaster.utils.math.animation.AnimationUtils; import top.fpsmaster.utils.render.Render2DUtils; -import top.fpsmaster.interfaces.ProviderManager; -import java.awt.Color; +import java.awt.*; public class Component { private float dragX = 0f; diff --git a/shared/java/top/fpsmaster/ui/custom/ComponentsManager.java b/shared/java/top/fpsmaster/ui/custom/ComponentsManager.java index 86cdf859..7a9cb3bf 100644 --- a/shared/java/top/fpsmaster/ui/custom/ComponentsManager.java +++ b/shared/java/top/fpsmaster/ui/custom/ComponentsManager.java @@ -9,7 +9,6 @@ import top.fpsmaster.utils.render.Render2DUtils; import java.util.ArrayList; -import java.util.function.Consumer; public class ComponentsManager { // List to hold all components diff --git a/shared/java/top/fpsmaster/ui/custom/impl/ArmorDisplayComponent.java b/shared/java/top/fpsmaster/ui/custom/impl/ArmorDisplayComponent.java index a0355e58..5ad85e3e 100644 --- a/shared/java/top/fpsmaster/ui/custom/impl/ArmorDisplayComponent.java +++ b/shared/java/top/fpsmaster/ui/custom/impl/ArmorDisplayComponent.java @@ -3,13 +3,11 @@ import net.minecraft.client.renderer.GlStateManager; import net.minecraft.client.renderer.RenderHelper; import net.minecraft.item.ItemStack; -import top.fpsmaster.FPSMaster; import top.fpsmaster.features.impl.interfaces.ArmorDisplay; -import top.fpsmaster.ui.custom.Component; -import top.fpsmaster.utils.Utility; import top.fpsmaster.interfaces.ProviderManager; +import top.fpsmaster.ui.custom.Component; -import java.awt.Color; +import java.awt.*; import java.util.Arrays; import java.util.List; diff --git a/shared/java/top/fpsmaster/ui/custom/impl/CPSDisplayComponent.java b/shared/java/top/fpsmaster/ui/custom/impl/CPSDisplayComponent.java index 42e49c9d..ff63fdcc 100644 --- a/shared/java/top/fpsmaster/ui/custom/impl/CPSDisplayComponent.java +++ b/shared/java/top/fpsmaster/ui/custom/impl/CPSDisplayComponent.java @@ -1,6 +1,5 @@ package top.fpsmaster.ui.custom.impl; -import top.fpsmaster.FPSMaster; import top.fpsmaster.features.impl.interfaces.CPSDisplay; import top.fpsmaster.ui.custom.Component; import top.fpsmaster.wrapper.TextFormattingProvider; diff --git a/shared/java/top/fpsmaster/ui/custom/impl/ComboDisplayComponent.java b/shared/java/top/fpsmaster/ui/custom/impl/ComboDisplayComponent.java index d0332165..ef0cc945 100644 --- a/shared/java/top/fpsmaster/ui/custom/impl/ComboDisplayComponent.java +++ b/shared/java/top/fpsmaster/ui/custom/impl/ComboDisplayComponent.java @@ -1,6 +1,5 @@ package top.fpsmaster.ui.custom.impl; -import top.fpsmaster.FPSMaster; import top.fpsmaster.features.impl.interfaces.ComboDisplay; import top.fpsmaster.ui.custom.Component; diff --git a/shared/java/top/fpsmaster/ui/custom/impl/CoordsDisplayComponent.java b/shared/java/top/fpsmaster/ui/custom/impl/CoordsDisplayComponent.java index 150d4a70..8a8fae44 100644 --- a/shared/java/top/fpsmaster/ui/custom/impl/CoordsDisplayComponent.java +++ b/shared/java/top/fpsmaster/ui/custom/impl/CoordsDisplayComponent.java @@ -1,11 +1,10 @@ package top.fpsmaster.ui.custom.impl; import org.jetbrains.annotations.NotNull; -import top.fpsmaster.FPSMaster; import top.fpsmaster.features.impl.interfaces.CoordsDisplay; import top.fpsmaster.features.impl.interfaces.FPSDisplay; -import top.fpsmaster.ui.custom.Component; import top.fpsmaster.interfaces.ProviderManager; +import top.fpsmaster.ui.custom.Component; import top.fpsmaster.wrapper.TextFormattingProvider; public class CoordsDisplayComponent extends Component { diff --git a/shared/java/top/fpsmaster/ui/custom/impl/FPSDisplayComponent.java b/shared/java/top/fpsmaster/ui/custom/impl/FPSDisplayComponent.java index 9ef0ad87..fc647b7a 100644 --- a/shared/java/top/fpsmaster/ui/custom/impl/FPSDisplayComponent.java +++ b/shared/java/top/fpsmaster/ui/custom/impl/FPSDisplayComponent.java @@ -1,7 +1,6 @@ package top.fpsmaster.ui.custom.impl; import net.minecraft.client.Minecraft; -import top.fpsmaster.FPSMaster; import top.fpsmaster.features.impl.interfaces.FPSDisplay; import top.fpsmaster.ui.custom.Component; diff --git a/shared/java/top/fpsmaster/ui/custom/impl/InventoryDisplayComponent.java b/shared/java/top/fpsmaster/ui/custom/impl/InventoryDisplayComponent.java index e674a56f..6d3d9142 100644 --- a/shared/java/top/fpsmaster/ui/custom/impl/InventoryDisplayComponent.java +++ b/shared/java/top/fpsmaster/ui/custom/impl/InventoryDisplayComponent.java @@ -5,9 +5,8 @@ import net.minecraft.inventory.Slot; import net.minecraft.item.ItemStack; import top.fpsmaster.features.impl.interfaces.InventoryDisplay; -import top.fpsmaster.ui.custom.Component; -import top.fpsmaster.utils.Utility; import top.fpsmaster.interfaces.ProviderManager; +import top.fpsmaster.ui.custom.Component; import static top.fpsmaster.utils.Utility.mc; diff --git a/shared/java/top/fpsmaster/ui/custom/impl/KeystrokesComponent.java b/shared/java/top/fpsmaster/ui/custom/impl/KeystrokesComponent.java index 5d9523de..dadead51 100644 --- a/shared/java/top/fpsmaster/ui/custom/impl/KeystrokesComponent.java +++ b/shared/java/top/fpsmaster/ui/custom/impl/KeystrokesComponent.java @@ -8,7 +8,7 @@ import top.fpsmaster.ui.custom.Component; import top.fpsmaster.utils.math.animation.ColorAnimation; -import java.awt.Color; +import java.awt.*; import java.util.ArrayList; public class KeystrokesComponent extends Component { diff --git a/shared/java/top/fpsmaster/ui/custom/impl/LyricsComponent.java b/shared/java/top/fpsmaster/ui/custom/impl/LyricsComponent.java index 723cf98d..beb0fa91 100644 --- a/shared/java/top/fpsmaster/ui/custom/impl/LyricsComponent.java +++ b/shared/java/top/fpsmaster/ui/custom/impl/LyricsComponent.java @@ -1,8 +1,5 @@ package top.fpsmaster.ui.custom.impl; -import org.jetbrains.annotations.Nullable; -import top.fpsmaster.FPSMaster; -import top.fpsmaster.font.impl.UFontRenderer; import top.fpsmaster.features.impl.interfaces.LyricsDisplay; import top.fpsmaster.modules.music.*; import top.fpsmaster.ui.custom.Component; @@ -10,7 +7,6 @@ import top.fpsmaster.utils.math.animation.AnimationUtils; import top.fpsmaster.utils.render.Render2DUtils; -import java.awt.*; import java.util.List; public class LyricsComponent extends Component { diff --git a/shared/java/top/fpsmaster/ui/custom/impl/MiniMapComponent.java b/shared/java/top/fpsmaster/ui/custom/impl/MiniMapComponent.java index b0fbcf44..9d53447b 100644 --- a/shared/java/top/fpsmaster/ui/custom/impl/MiniMapComponent.java +++ b/shared/java/top/fpsmaster/ui/custom/impl/MiniMapComponent.java @@ -1,7 +1,6 @@ package top.fpsmaster.ui.custom.impl; import net.minecraft.client.Minecraft; -import net.minecraft.client.renderer.GlStateManager; import net.minecraft.util.ResourceLocation; import org.lwjgl.opengl.GL11; import top.fpsmaster.features.impl.interfaces.MiniMap; diff --git a/shared/java/top/fpsmaster/ui/custom/impl/ModsListComponent.java b/shared/java/top/fpsmaster/ui/custom/impl/ModsListComponent.java index d36ccbea..a8489861 100644 --- a/shared/java/top/fpsmaster/ui/custom/impl/ModsListComponent.java +++ b/shared/java/top/fpsmaster/ui/custom/impl/ModsListComponent.java @@ -4,15 +4,13 @@ import top.fpsmaster.features.impl.interfaces.ModsList; import top.fpsmaster.features.manager.Category; import top.fpsmaster.features.manager.Module; -import top.fpsmaster.features.settings.impl.TextSetting; import top.fpsmaster.font.impl.UFontRenderer; +import top.fpsmaster.interfaces.ProviderManager; import top.fpsmaster.ui.custom.Component; import top.fpsmaster.utils.render.Render2DUtils; -import top.fpsmaster.interfaces.ProviderManager; -import java.awt.Color; +import java.awt.*; import java.util.ArrayList; -import java.util.Arrays; import java.util.List; import java.util.stream.Collectors; diff --git a/shared/java/top/fpsmaster/ui/custom/impl/MusicComponent.java b/shared/java/top/fpsmaster/ui/custom/impl/MusicComponent.java index 4b49c8db..0d36828e 100644 --- a/shared/java/top/fpsmaster/ui/custom/impl/MusicComponent.java +++ b/shared/java/top/fpsmaster/ui/custom/impl/MusicComponent.java @@ -1,7 +1,6 @@ package top.fpsmaster.ui.custom.impl; import net.minecraft.util.ResourceLocation; -import top.fpsmaster.FPSMaster; import top.fpsmaster.features.impl.interfaces.MusicOverlay; import top.fpsmaster.modules.music.AbstractMusic; import top.fpsmaster.modules.music.MusicPlayer; @@ -11,7 +10,7 @@ import top.fpsmaster.utils.math.animation.AnimationUtils; import top.fpsmaster.utils.render.Render2DUtils; -import java.awt.Color; +import java.awt.*; public class MusicComponent extends Component { diff --git a/shared/java/top/fpsmaster/ui/custom/impl/PingDisplayComponent.java b/shared/java/top/fpsmaster/ui/custom/impl/PingDisplayComponent.java index 9ff57b5d..2f195352 100644 --- a/shared/java/top/fpsmaster/ui/custom/impl/PingDisplayComponent.java +++ b/shared/java/top/fpsmaster/ui/custom/impl/PingDisplayComponent.java @@ -1,9 +1,8 @@ package top.fpsmaster.ui.custom.impl; -import top.fpsmaster.FPSMaster; import top.fpsmaster.features.impl.interfaces.PingDisplay; -import top.fpsmaster.ui.custom.Component; import top.fpsmaster.interfaces.ProviderManager; +import top.fpsmaster.ui.custom.Component; public class PingDisplayComponent extends Component { diff --git a/shared/java/top/fpsmaster/ui/custom/impl/PlayerDisplayComponent.java b/shared/java/top/fpsmaster/ui/custom/impl/PlayerDisplayComponent.java index 1c18fb86..71616c4e 100644 --- a/shared/java/top/fpsmaster/ui/custom/impl/PlayerDisplayComponent.java +++ b/shared/java/top/fpsmaster/ui/custom/impl/PlayerDisplayComponent.java @@ -5,11 +5,11 @@ import top.fpsmaster.FPSMaster; import top.fpsmaster.features.impl.interfaces.PlayerDisplay; import top.fpsmaster.font.impl.UFontRenderer; +import top.fpsmaster.interfaces.ProviderManager; import top.fpsmaster.ui.custom.Component; import top.fpsmaster.utils.render.Render2DUtils; -import top.fpsmaster.interfaces.ProviderManager; -import java.awt.Color; +import java.awt.*; public class PlayerDisplayComponent extends Component { diff --git a/shared/java/top/fpsmaster/ui/custom/impl/PotionDisplayComponent.java b/shared/java/top/fpsmaster/ui/custom/impl/PotionDisplayComponent.java index 678426b9..64ab4199 100644 --- a/shared/java/top/fpsmaster/ui/custom/impl/PotionDisplayComponent.java +++ b/shared/java/top/fpsmaster/ui/custom/impl/PotionDisplayComponent.java @@ -4,14 +4,12 @@ import net.minecraft.client.renderer.GlStateManager; import net.minecraft.client.resources.I18n; import net.minecraft.util.ResourceLocation; -import top.fpsmaster.FPSMaster; import top.fpsmaster.features.impl.interfaces.PotionDisplay; -import top.fpsmaster.font.impl.UFontRenderer; +import top.fpsmaster.interfaces.ProviderManager; import top.fpsmaster.ui.custom.Component; import top.fpsmaster.utils.Utility; -import top.fpsmaster.interfaces.ProviderManager; -import java.awt.Color; +import java.awt.*; public class PotionDisplayComponent extends Component { diff --git a/shared/java/top/fpsmaster/ui/custom/impl/ReachDisplayComponent.java b/shared/java/top/fpsmaster/ui/custom/impl/ReachDisplayComponent.java index 87d75bf6..b929be6a 100644 --- a/shared/java/top/fpsmaster/ui/custom/impl/ReachDisplayComponent.java +++ b/shared/java/top/fpsmaster/ui/custom/impl/ReachDisplayComponent.java @@ -1,6 +1,5 @@ package top.fpsmaster.ui.custom.impl; -import top.fpsmaster.FPSMaster; import top.fpsmaster.features.impl.interfaces.ReachDisplay; import top.fpsmaster.ui.custom.Component; diff --git a/shared/java/top/fpsmaster/ui/custom/impl/SprintComponent.java b/shared/java/top/fpsmaster/ui/custom/impl/SprintComponent.java index b9098366..8afe7b79 100644 --- a/shared/java/top/fpsmaster/ui/custom/impl/SprintComponent.java +++ b/shared/java/top/fpsmaster/ui/custom/impl/SprintComponent.java @@ -1,6 +1,5 @@ package top.fpsmaster.ui.custom.impl; -import top.fpsmaster.FPSMaster; import top.fpsmaster.features.impl.utility.Sprint; import top.fpsmaster.ui.custom.Component; diff --git a/shared/java/top/fpsmaster/ui/custom/impl/TargetHUDComponent.java b/shared/java/top/fpsmaster/ui/custom/impl/TargetHUDComponent.java index e385fe03..00ea9b1d 100644 --- a/shared/java/top/fpsmaster/ui/custom/impl/TargetHUDComponent.java +++ b/shared/java/top/fpsmaster/ui/custom/impl/TargetHUDComponent.java @@ -4,14 +4,14 @@ import net.minecraft.entity.player.EntityPlayer; import top.fpsmaster.FPSMaster; import top.fpsmaster.features.impl.interfaces.TargetDisplay; +import top.fpsmaster.interfaces.ProviderManager; import top.fpsmaster.ui.custom.Component; import top.fpsmaster.utils.Utility; import top.fpsmaster.utils.math.animation.AnimationUtils; import top.fpsmaster.utils.math.animation.ColorAnimation; import top.fpsmaster.utils.render.Render2DUtils; -import top.fpsmaster.interfaces.ProviderManager; -import java.awt.Color; +import java.awt.*; public class TargetHUDComponent extends Component { diff --git a/shared/java/top/fpsmaster/ui/devspace/AIPanel.java b/shared/java/top/fpsmaster/ui/devspace/AIPanel.java index 429f3264..7402afef 100644 --- a/shared/java/top/fpsmaster/ui/devspace/AIPanel.java +++ b/shared/java/top/fpsmaster/ui/devspace/AIPanel.java @@ -1,9 +1,7 @@ package top.fpsmaster.ui.devspace; import net.minecraft.client.gui.ScaledResolution; -import net.minecraft.util.ResourceLocation; import org.lwjgl.input.Mouse; -import top.fpsmaster.FPSMaster; import top.fpsmaster.utils.render.Render2DUtils; import java.awt.*; diff --git a/shared/java/top/fpsmaster/ui/devspace/map/expressions/FunctionCallExpressionComponent.java b/shared/java/top/fpsmaster/ui/devspace/map/expressions/FunctionCallExpressionComponent.java index 11df1291..616907bd 100644 --- a/shared/java/top/fpsmaster/ui/devspace/map/expressions/FunctionCallExpressionComponent.java +++ b/shared/java/top/fpsmaster/ui/devspace/map/expressions/FunctionCallExpressionComponent.java @@ -6,7 +6,6 @@ import top.fpsmaster.utils.render.Render2DUtils; import java.awt.*; -import java.util.ArrayList; import java.util.List; public class FunctionCallExpressionComponent extends ExpressionComponent { diff --git a/shared/java/top/fpsmaster/ui/mc/GuiMultiplayer.java b/shared/java/top/fpsmaster/ui/mc/GuiMultiplayer.java index fd54e717..0c08b282 100644 --- a/shared/java/top/fpsmaster/ui/mc/GuiMultiplayer.java +++ b/shared/java/top/fpsmaster/ui/mc/GuiMultiplayer.java @@ -4,11 +4,10 @@ import com.google.gson.Gson; import com.google.gson.GsonBuilder; import com.google.gson.JsonObject; -import com.google.gson.JsonParser; -import net.minecraft.client.gui.*; +import net.minecraft.client.gui.GuiScreenAddServer; +import net.minecraft.client.gui.GuiScreenServerList; +import net.minecraft.client.gui.GuiYesNo; import net.minecraft.client.multiplayer.ServerData; -import net.minecraft.client.multiplayer.ServerList; -import net.minecraft.client.network.LanServerDetector; import net.minecraft.client.network.OldServerPinger; import net.minecraft.client.resources.I18n; import net.minecraft.nbt.CompressedStreamTools; @@ -20,7 +19,6 @@ import org.lwjgl.opengl.GL11; import top.fpsmaster.FPSMaster; import top.fpsmaster.font.impl.UFontRenderer; -import top.fpsmaster.interfaces.ProviderManager; import top.fpsmaster.modules.client.AsyncTask; import top.fpsmaster.ui.click.component.ScrollContainer; import top.fpsmaster.ui.common.GuiButton; @@ -29,8 +27,6 @@ import top.fpsmaster.utils.os.HttpRequest; import top.fpsmaster.utils.render.Render2DUtils; import top.fpsmaster.utils.render.ScaledGuiScreen; -import top.fpsmaster.utils.thirdparty.github.UpdateChecker; -import top.fpsmaster.wrapper.ChatFormattingProvider; import java.awt.*; import java.io.File; diff --git a/shared/java/top/fpsmaster/ui/mc/ServerListEntry.java b/shared/java/top/fpsmaster/ui/mc/ServerListEntry.java index daa507a9..1711dce6 100644 --- a/shared/java/top/fpsmaster/ui/mc/ServerListEntry.java +++ b/shared/java/top/fpsmaster/ui/mc/ServerListEntry.java @@ -11,18 +11,9 @@ import io.netty.buffer.ByteBufInputStream; import io.netty.buffer.Unpooled; import io.netty.handler.codec.base64.Base64; - -import java.awt.*; -import java.awt.image.BufferedImage; -import java.net.UnknownHostException; -import java.util.List; -import java.util.concurrent.ScheduledThreadPoolExecutor; -import java.util.concurrent.ThreadPoolExecutor; - import net.minecraft.client.Minecraft; import net.minecraft.client.gui.Gui; import net.minecraft.client.multiplayer.ServerData; -import net.minecraft.client.network.OldServerPinger; import net.minecraft.client.renderer.GlStateManager; import net.minecraft.client.renderer.texture.DynamicTexture; import net.minecraft.client.renderer.texture.TextureUtil; @@ -38,6 +29,12 @@ import top.fpsmaster.font.impl.UFontRenderer; import top.fpsmaster.utils.render.Render2DUtils; +import java.awt.image.BufferedImage; +import java.net.UnknownHostException; +import java.util.List; +import java.util.concurrent.ScheduledThreadPoolExecutor; +import java.util.concurrent.ThreadPoolExecutor; + @SideOnly(Side.CLIENT) public class ServerListEntry { private static final Logger logger = LogManager.getLogger(); diff --git a/shared/java/top/fpsmaster/ui/minimap/XaeroMinimap.java b/shared/java/top/fpsmaster/ui/minimap/XaeroMinimap.java index 030e699a..4af9175b 100644 --- a/shared/java/top/fpsmaster/ui/minimap/XaeroMinimap.java +++ b/shared/java/top/fpsmaster/ui/minimap/XaeroMinimap.java @@ -1,6 +1,5 @@ package top.fpsmaster.ui.minimap; -import net.minecraft.client.Minecraft; import top.fpsmaster.ui.minimap.interfaces.InterfaceHandler; import java.io.IOException; diff --git a/shared/java/top/fpsmaster/ui/minimap/interfaces/InterfaceHandler.java b/shared/java/top/fpsmaster/ui/minimap/interfaces/InterfaceHandler.java index 555a5b07..9d63e6c8 100644 --- a/shared/java/top/fpsmaster/ui/minimap/interfaces/InterfaceHandler.java +++ b/shared/java/top/fpsmaster/ui/minimap/interfaces/InterfaceHandler.java @@ -1,7 +1,6 @@ package top.fpsmaster.ui.minimap.interfaces; import net.minecraft.client.Minecraft; -import net.minecraft.client.gui.ScaledResolution; import net.minecraft.client.renderer.GlStateManager; import net.minecraft.client.renderer.OpenGlHelper; import net.minecraft.client.renderer.RenderHelper; @@ -9,9 +8,8 @@ import org.lwjgl.opengl.GL11; import top.fpsmaster.FPSMaster; import top.fpsmaster.features.impl.interfaces.MiniMap; -import top.fpsmaster.ui.custom.Component; -import top.fpsmaster.ui.minimap.XaeroMinimap; import top.fpsmaster.minimap.Minimap; +import top.fpsmaster.ui.custom.Component; import java.util.ArrayList; diff --git a/shared/java/top/fpsmaster/ui/notification/Notification.java b/shared/java/top/fpsmaster/ui/notification/Notification.java index 21b8cfee..c956fb65 100644 --- a/shared/java/top/fpsmaster/ui/notification/Notification.java +++ b/shared/java/top/fpsmaster/ui/notification/Notification.java @@ -6,7 +6,7 @@ import top.fpsmaster.utils.math.animation.AnimationUtils; import top.fpsmaster.utils.render.Render2DUtils; -import java.awt.Color; +import java.awt.*; public class Notification { private final String title; diff --git a/shared/java/top/fpsmaster/ui/screens/account/GuiWaiting.java b/shared/java/top/fpsmaster/ui/screens/account/GuiWaiting.java index 4ad40c5f..1e3aaf6a 100644 --- a/shared/java/top/fpsmaster/ui/screens/account/GuiWaiting.java +++ b/shared/java/top/fpsmaster/ui/screens/account/GuiWaiting.java @@ -5,8 +5,8 @@ import net.minecraft.client.gui.GuiScreen; import net.minecraft.client.gui.ScaledResolution; import top.fpsmaster.FPSMaster; -import top.fpsmaster.utils.thirdparty.microsoft.MicrosoftLogin; import top.fpsmaster.utils.render.Render2DUtils; +import top.fpsmaster.utils.thirdparty.microsoft.MicrosoftLogin; import java.awt.*; import java.io.IOException; diff --git a/shared/java/top/fpsmaster/ui/screens/mainmenu/MainMenu.java b/shared/java/top/fpsmaster/ui/screens/mainmenu/MainMenu.java index 12a00635..d2951fac 100644 --- a/shared/java/top/fpsmaster/ui/screens/mainmenu/MainMenu.java +++ b/shared/java/top/fpsmaster/ui/screens/mainmenu/MainMenu.java @@ -16,8 +16,7 @@ import top.fpsmaster.utils.render.ScaledGuiScreen; import top.fpsmaster.wrapper.TextFormattingProvider; -import java.awt.Color; -import java.awt.Desktop; +import java.awt.*; import java.net.URI; public class MainMenu extends ScaledGuiScreen { diff --git a/shared/java/top/fpsmaster/ui/screens/oobe/OOBEScreen.java b/shared/java/top/fpsmaster/ui/screens/oobe/OOBEScreen.java index 3b22bf8c..8e8a7eac 100644 --- a/shared/java/top/fpsmaster/ui/screens/oobe/OOBEScreen.java +++ b/shared/java/top/fpsmaster/ui/screens/oobe/OOBEScreen.java @@ -9,7 +9,7 @@ import top.fpsmaster.utils.math.animation.Type; import top.fpsmaster.utils.render.Render2DUtils; -import java.awt.Color; +import java.awt.*; import java.io.IOException; import java.util.ArrayList; diff --git a/shared/java/top/fpsmaster/ui/screens/oobe/impls/Login.java b/shared/java/top/fpsmaster/ui/screens/oobe/impls/Login.java index 04a2714b..d682fb60 100644 --- a/shared/java/top/fpsmaster/ui/screens/oobe/impls/Login.java +++ b/shared/java/top/fpsmaster/ui/screens/oobe/impls/Login.java @@ -8,17 +8,16 @@ import top.fpsmaster.exception.FileException; import top.fpsmaster.exception.NetworkException; import top.fpsmaster.modules.account.AccountManager; -import top.fpsmaster.ui.common.TextField; -import top.fpsmaster.ui.screens.oobe.Scene; import top.fpsmaster.ui.common.GuiButton; +import top.fpsmaster.ui.common.TextField; import top.fpsmaster.ui.screens.mainmenu.MainMenu; +import top.fpsmaster.ui.screens.oobe.Scene; import top.fpsmaster.utils.math.animation.ColorAnimation; import top.fpsmaster.utils.math.animation.Type; import top.fpsmaster.utils.os.FileUtils; import top.fpsmaster.utils.render.Render2DUtils; -import java.awt.Color; -import java.awt.Desktop; +import java.awt.*; import java.net.URI; public class Login extends Scene { diff --git a/shared/java/top/fpsmaster/utils/awt/AWTUtils.java b/shared/java/top/fpsmaster/utils/awt/AWTUtils.java index 03eae52c..57c3ea74 100644 --- a/shared/java/top/fpsmaster/utils/awt/AWTUtils.java +++ b/shared/java/top/fpsmaster/utils/awt/AWTUtils.java @@ -7,7 +7,6 @@ import java.awt.*; import java.awt.geom.RoundRectangle2D; import java.awt.image.BufferedImage; -import java.io.File; import java.util.HashMap; public class AWTUtils { diff --git a/shared/java/top/fpsmaster/utils/awt/GifUtil.java b/shared/java/top/fpsmaster/utils/awt/GifUtil.java index fcbc8391..6aa86344 100644 --- a/shared/java/top/fpsmaster/utils/awt/GifUtil.java +++ b/shared/java/top/fpsmaster/utils/awt/GifUtil.java @@ -4,13 +4,16 @@ import org.w3c.dom.Node; import org.w3c.dom.NodeList; -import javax.imageio.*; -import javax.imageio.metadata.*; -import javax.imageio.stream.*; +import javax.imageio.ImageIO; +import javax.imageio.ImageReader; +import javax.imageio.metadata.IIOMetadata; +import javax.imageio.metadata.IIOMetadataNode; +import javax.imageio.stream.ImageInputStream; import java.awt.*; -import java.awt.image.*; -import java.io.*; -import java.util.*; +import java.awt.image.BufferedImage; +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; import java.util.List; public class GifUtil { diff --git a/shared/java/top/fpsmaster/utils/math/animation/AnimationUtils.java b/shared/java/top/fpsmaster/utils/math/animation/AnimationUtils.java index 9298a52e..372eec23 100644 --- a/shared/java/top/fpsmaster/utils/math/animation/AnimationUtils.java +++ b/shared/java/top/fpsmaster/utils/math/animation/AnimationUtils.java @@ -3,8 +3,6 @@ import net.minecraft.client.Minecraft; import top.fpsmaster.utils.Utility; -import java.util.Arrays; - public class AnimationUtils extends Utility { private static float debugFPS() { diff --git a/shared/java/top/fpsmaster/utils/math/animation/ColorAnimation.java b/shared/java/top/fpsmaster/utils/math/animation/ColorAnimation.java index 4a1e5d9e..cb7a89e9 100644 --- a/shared/java/top/fpsmaster/utils/math/animation/ColorAnimation.java +++ b/shared/java/top/fpsmaster/utils/math/animation/ColorAnimation.java @@ -1,7 +1,8 @@ package top.fpsmaster.utils.math.animation; import top.fpsmaster.utils.render.Render2DUtils; -import java.awt.Color; + +import java.awt.*; public class ColorAnimation { private Animation r = new Animation(); diff --git a/shared/java/top/fpsmaster/utils/os/CryptUtils.java b/shared/java/top/fpsmaster/utils/os/CryptUtils.java index 6b752a3b..9ab9a2c3 100644 --- a/shared/java/top/fpsmaster/utils/os/CryptUtils.java +++ b/shared/java/top/fpsmaster/utils/os/CryptUtils.java @@ -1,12 +1,12 @@ package top.fpsmaster.utils.os; +import javax.crypto.Cipher; +import javax.crypto.spec.SecretKeySpec; import java.nio.charset.StandardCharsets; import java.security.Key; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.util.Base64; -import javax.crypto.Cipher; -import javax.crypto.spec.SecretKeySpec; public class CryptUtils { private static final String ALGORITHM = "AES"; diff --git a/shared/java/top/fpsmaster/utils/os/HttpRequest.java b/shared/java/top/fpsmaster/utils/os/HttpRequest.java index bd14dc96..2bd76039 100644 --- a/shared/java/top/fpsmaster/utils/os/HttpRequest.java +++ b/shared/java/top/fpsmaster/utils/os/HttpRequest.java @@ -6,7 +6,6 @@ import org.apache.http.HttpEntity; import org.apache.http.HttpResponse; import org.apache.http.NameValuePair; -import org.apache.http.client.HttpClient; import org.apache.http.client.config.RequestConfig; import org.apache.http.client.entity.UrlEncodedFormEntity; import org.apache.http.client.methods.CloseableHttpResponse; @@ -20,10 +19,11 @@ import org.apache.http.util.EntityUtils; import top.fpsmaster.modules.logger.ClientLogger; -import java.io.*; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; import java.nio.charset.StandardCharsets; import java.util.ArrayList; -import java.util.HashMap; import java.util.List; import java.util.Map; diff --git a/shared/java/top/fpsmaster/utils/render/Render2DUtils.java b/shared/java/top/fpsmaster/utils/render/Render2DUtils.java index cee28e99..1a9cac0b 100644 --- a/shared/java/top/fpsmaster/utils/render/Render2DUtils.java +++ b/shared/java/top/fpsmaster/utils/render/Render2DUtils.java @@ -15,7 +15,6 @@ import org.lwjgl.opengl.GL14; import org.lwjgl.opengl.GL20; import top.fpsmaster.features.impl.interfaces.ClientSettings; -import top.fpsmaster.features.impl.render.MotionBlur; import top.fpsmaster.interfaces.ProviderManager; import top.fpsmaster.ui.screens.mainmenu.MainMenu; import top.fpsmaster.utils.Utility; @@ -30,7 +29,6 @@ import java.awt.*; import java.io.File; -import java.io.IOException; import static org.lwjgl.opengl.GL11.*; diff --git a/shared/java/top/fpsmaster/utils/render/ScaledGuiScreen.java b/shared/java/top/fpsmaster/utils/render/ScaledGuiScreen.java index 37eb3bb5..4aaf8d2c 100644 --- a/shared/java/top/fpsmaster/utils/render/ScaledGuiScreen.java +++ b/shared/java/top/fpsmaster/utils/render/ScaledGuiScreen.java @@ -3,9 +3,7 @@ import net.minecraft.client.gui.GuiScreen; import net.minecraft.client.gui.ScaledResolution; import org.lwjgl.opengl.GL11; -import top.fpsmaster.features.impl.interfaces.ClientSettings; -import java.awt.*; import java.io.IOException; public class ScaledGuiScreen extends GuiScreen { diff --git a/shared/java/top/fpsmaster/utils/render/shader/KawaseBloom.java b/shared/java/top/fpsmaster/utils/render/shader/KawaseBloom.java index 8a99818a..d6e9310a 100644 --- a/shared/java/top/fpsmaster/utils/render/shader/KawaseBloom.java +++ b/shared/java/top/fpsmaster/utils/render/shader/KawaseBloom.java @@ -11,7 +11,6 @@ import java.util.List; import static org.lwjgl.opengl.GL11.*; -import static org.lwjgl.opengl.GL11.GL_TEXTURE_2D; import static top.fpsmaster.utils.Utility.mc; public class KawaseBloom { diff --git a/shared/java/top/fpsmaster/utils/render/shader/KawaseBlur.java b/shared/java/top/fpsmaster/utils/render/shader/KawaseBlur.java index 4181cd91..f68263e8 100644 --- a/shared/java/top/fpsmaster/utils/render/shader/KawaseBlur.java +++ b/shared/java/top/fpsmaster/utils/render/shader/KawaseBlur.java @@ -3,7 +3,6 @@ import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.GlStateManager; import net.minecraft.client.shader.Framebuffer; -import org.lwjgl.opengl.GL11; import java.util.ArrayList; import java.util.List; diff --git a/shared/java/top/fpsmaster/utils/render/shader/RoundedUtil.java b/shared/java/top/fpsmaster/utils/render/shader/RoundedUtil.java index 33ac6490..1f345487 100644 --- a/shared/java/top/fpsmaster/utils/render/shader/RoundedUtil.java +++ b/shared/java/top/fpsmaster/utils/render/shader/RoundedUtil.java @@ -6,7 +6,7 @@ import net.minecraft.client.shader.Framebuffer; import org.lwjgl.opengl.GL11; -import java.awt.Color; +import java.awt.*; import static top.fpsmaster.utils.Utility.mc; import static top.fpsmaster.utils.render.shader.GradientUtils.interpolateColorC; diff --git a/shared/java/top/fpsmaster/utils/thirdparty/github/UpdateChecker.java b/shared/java/top/fpsmaster/utils/thirdparty/github/UpdateChecker.java index 84f9c176..20b01930 100644 --- a/shared/java/top/fpsmaster/utils/thirdparty/github/UpdateChecker.java +++ b/shared/java/top/fpsmaster/utils/thirdparty/github/UpdateChecker.java @@ -1,12 +1,8 @@ package top.fpsmaster.utils.thirdparty.github; -import com.google.gson.JsonObject; -import com.google.gson.JsonParser; import top.fpsmaster.utils.GitInfo; import top.fpsmaster.utils.os.HttpRequest; -import java.io.IOException; - public class UpdateChecker { public static String getLatestVersion() { return HttpRequest.get("https://service.fpsmaster.top/api/github/latest/commit?branch=refs/heads/"+ GitInfo.getBranch()); diff --git a/shared/java/top/fpsmaster/utils/thirdparty/microsoft/MicrosoftLogin.java b/shared/java/top/fpsmaster/utils/thirdparty/microsoft/MicrosoftLogin.java index 40b876d3..2719d3c3 100644 --- a/shared/java/top/fpsmaster/utils/thirdparty/microsoft/MicrosoftLogin.java +++ b/shared/java/top/fpsmaster/utils/thirdparty/microsoft/MicrosoftLogin.java @@ -1,12 +1,9 @@ package top.fpsmaster.utils.thirdparty.microsoft; import com.google.gson.JsonObject; -import com.google.gson.JsonParser; import com.sun.net.httpserver.HttpServer; -import net.minecraft.client.Minecraft; import net.minecraft.util.Session; import top.fpsmaster.interfaces.ProviderManager; -import top.fpsmaster.interfaces.game.IMinecraftProvider; import top.fpsmaster.ui.screens.mainmenu.MainMenu; import top.fpsmaster.utils.os.HttpRequest; @@ -18,7 +15,6 @@ import java.net.URLEncoder; import java.nio.charset.StandardCharsets; import java.util.HashMap; -import java.util.LinkedHashMap; import java.util.Map; import java.util.StringJoiner; import java.util.concurrent.Executors; diff --git a/shared/java/top/fpsmaster/utils/thirdparty/openai/OpenAI.java b/shared/java/top/fpsmaster/utils/thirdparty/openai/OpenAI.java index 72ffd8e0..a2fbdfeb 100644 --- a/shared/java/top/fpsmaster/utils/thirdparty/openai/OpenAI.java +++ b/shared/java/top/fpsmaster/utils/thirdparty/openai/OpenAI.java @@ -1,6 +1,5 @@ package top.fpsmaster.utils.thirdparty.openai; -import com.google.gson.Gson; import com.google.gson.JsonArray; import com.google.gson.JsonObject; import com.google.gson.JsonParser; diff --git a/shared/java/top/fpsmaster/utils/thirdparty/openai/OpenAIClient.java b/shared/java/top/fpsmaster/utils/thirdparty/openai/OpenAIClient.java index f2fa5bab..43da1004 100644 --- a/shared/java/top/fpsmaster/utils/thirdparty/openai/OpenAIClient.java +++ b/shared/java/top/fpsmaster/utils/thirdparty/openai/OpenAIClient.java @@ -1,16 +1,16 @@ package top.fpsmaster.utils.thirdparty.openai; +import com.google.gson.*; import org.apache.commons.lang3.StringEscapeUtils; import org.apache.http.client.HttpClient; import org.apache.http.client.methods.HttpPost; -import org.apache.http.impl.client.HttpClients; import org.apache.http.entity.StringEntity; -import com.google.gson.*; +import org.apache.http.impl.client.HttpClients; import top.fpsmaster.exception.FileException; import java.io.BufferedReader; -import java.io.InputStreamReader; import java.io.IOException; +import java.io.InputStreamReader; import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.concurrent.ExecutorService; diff --git a/shared/java/top/fpsmaster/websocket/client/WsClient.java b/shared/java/top/fpsmaster/websocket/client/WsClient.java index 03993ad8..3dbd6cd0 100644 --- a/shared/java/top/fpsmaster/websocket/client/WsClient.java +++ b/shared/java/top/fpsmaster/websocket/client/WsClient.java @@ -1,14 +1,11 @@ package top.fpsmaster.websocket.client; -import com.google.gson.JsonObject; -import com.google.gson.JsonParser; import org.java_websocket.client.WebSocketClient; import org.java_websocket.handshake.ServerHandshake; import top.fpsmaster.FPSMaster; import top.fpsmaster.features.impl.interfaces.ClientSettings; import top.fpsmaster.features.impl.utility.IRC; import top.fpsmaster.interfaces.ProviderManager; -import top.fpsmaster.modules.client.ClientUsersManager; import top.fpsmaster.utils.Utility; import top.fpsmaster.websocket.data.message.Packet; import top.fpsmaster.websocket.data.message.client.*; From 0f8ac1c062e12d2aed1e15cf8c858a280324b778 Mon Sep 17 00:00:00 2001 From: SuperSkidder Date: Mon, 14 Jul 2025 17:29:27 +0800 Subject: [PATCH 086/193] code cleanup --- .../fpsmaster/features/command/impl/AI.java | 2 +- .../features/impl/interfaces/CPSDisplay.java | 2 +- .../impl/interfaces/DirectionDisplay.java | 2 +- .../impl/interfaces/TargetDisplay.java | 4 +-- .../features/impl/optimizes/Performance.java | 2 +- .../features/impl/optimizes/SmoothZoom.java | 4 +-- .../features/impl/render/BlockOverlay.java | 12 +++---- .../features/impl/render/FreeLook.java | 2 +- .../features/impl/render/Hitboxes.java | 2 +- .../features/impl/render/MotionBlur.java | 4 +-- .../features/impl/utility/ChatBot.java | 2 +- .../features/impl/utility/LevelTag.java | 8 ++--- .../features/impl/utility/SkinChanger.java | 2 +- .../features/impl/utility/TNTTimer.java | 2 +- .../features/impl/utility/TimeChanger.java | 2 +- .../fpsmaster/features/manager/Module.java | 12 +++---- .../fpsmaster/features/settings/Setting.java | 2 +- .../features/settings/impl/ModeSetting.java | 2 +- .../modules/config/ConfigManager.java | 2 +- .../top/fpsmaster/modules/i18n/Language.java | 2 +- .../modules/music/IngameOverlay.java | 2 +- .../fpsmaster/modules/music/JLayerHelper.java | 4 +-- .../netease/deserialize/MusicWrapper.java | 2 +- .../fpsmaster/ui/click/CategoryComponent.java | 2 +- .../ui/click/component/ScrollContainer.java | 2 +- .../modules/impl/BooleanSettingRender.java | 2 +- .../click/modules/impl/TextSettingRender.java | 2 +- .../fpsmaster/ui/click/music/MusicPanel.java | 10 +++--- .../ui/click/music/NewMusicPanel.java | 4 +-- .../fpsmaster/ui/click/music/SearchBox.java | 16 +++++----- .../top/fpsmaster/ui/common/GuiButton.java | 2 +- .../ui/custom/impl/MiniMapComponent.java | 2 +- .../ui/custom/impl/TargetHUDComponent.java | 8 ++--- .../top/fpsmaster/ui/devspace/DevSpace.java | 2 +- .../top/fpsmaster/ui/mc/GuiMultiplayer.java | 16 +++++----- .../top/fpsmaster/ui/mc/ServerListEntry.java | 10 +++--- .../ui/notification/Notification.java | 4 +-- .../ui/screens/mainmenu/MenuButton.java | 4 +-- .../fpsmaster/ui/screens/oobe/GuiLogin.java | 2 +- .../top/fpsmaster/utils/awt/AWTUtils.java | 4 +-- .../utils/math/animation/ColorAnimation.java | 32 +++++++++---------- .../utils/render/shader/RoundedUtil.java | 4 +-- 42 files changed, 103 insertions(+), 105 deletions(-) diff --git a/shared/java/top/fpsmaster/features/command/impl/AI.java b/shared/java/top/fpsmaster/features/command/impl/AI.java index e23f401f..adc4c095 100644 --- a/shared/java/top/fpsmaster/features/command/impl/AI.java +++ b/shared/java/top/fpsmaster/features/command/impl/AI.java @@ -14,7 +14,7 @@ import java.util.ArrayList; public class AI extends Command { - private String luaPrompt = "请遵守以下规则:\n" + + private final String luaPrompt = "请遵守以下规则:\n" + "1. 你的角色:作为代码生成机器人\n" + "2. 你的目标:参考下面的lua示例,完成用户所输入的要求,编写相应的lua代码\n" + "3. 禁止做:与用户闲聊、生成有危害性的代码\n" + diff --git a/shared/java/top/fpsmaster/features/impl/interfaces/CPSDisplay.java b/shared/java/top/fpsmaster/features/impl/interfaces/CPSDisplay.java index 9b32a6c3..f8b86cc4 100644 --- a/shared/java/top/fpsmaster/features/impl/interfaces/CPSDisplay.java +++ b/shared/java/top/fpsmaster/features/impl/interfaces/CPSDisplay.java @@ -12,7 +12,7 @@ public class CPSDisplay extends InterfaceModule { - private LinkedList keys = new LinkedList<>(); + private final LinkedList keys = new LinkedList<>(); public CPSDisplay() { super("CPSDisplay", Category.Interface); diff --git a/shared/java/top/fpsmaster/features/impl/interfaces/DirectionDisplay.java b/shared/java/top/fpsmaster/features/impl/interfaces/DirectionDisplay.java index 0acb7bfb..2f566725 100644 --- a/shared/java/top/fpsmaster/features/impl/interfaces/DirectionDisplay.java +++ b/shared/java/top/fpsmaster/features/impl/interfaces/DirectionDisplay.java @@ -10,7 +10,7 @@ public class DirectionDisplay extends Module { - private Compass compass = new Compass(325f, 325f, 1f, 2, true); + private final Compass compass = new Compass(325f, 325f, 1f, 2, true); public DirectionDisplay() { super("DirectionDisplay", Category.Interface); diff --git a/shared/java/top/fpsmaster/features/impl/interfaces/TargetDisplay.java b/shared/java/top/fpsmaster/features/impl/interfaces/TargetDisplay.java index 3d36126f..f3788100 100644 --- a/shared/java/top/fpsmaster/features/impl/interfaces/TargetDisplay.java +++ b/shared/java/top/fpsmaster/features/impl/interfaces/TargetDisplay.java @@ -17,8 +17,8 @@ import java.awt.*; public class TargetDisplay extends InterfaceModule { - private ModeSetting targetESP = new ModeSetting("TargetESP", 0, "glow", "none"); - private ColorSetting espColor = new ColorSetting("EspColor", new Color(255, 255, 255, 255), () -> !targetESP.isMode("none")); + private final ModeSetting targetESP = new ModeSetting("TargetESP", 0, "glow", "none"); + private final ColorSetting espColor = new ColorSetting("EspColor", new Color(255, 255, 255, 255), () -> !targetESP.isMode("none")); public static ModeSetting targetHUD = new ModeSetting("TargetHUD", 0, "simple", "none"); public static BooleanSetting omit = new BooleanSetting("OmitName", true); public static EntityPlayer target; diff --git a/shared/java/top/fpsmaster/features/impl/optimizes/Performance.java b/shared/java/top/fpsmaster/features/impl/optimizes/Performance.java index e82d8c1a..28f13535 100644 --- a/shared/java/top/fpsmaster/features/impl/optimizes/Performance.java +++ b/shared/java/top/fpsmaster/features/impl/optimizes/Performance.java @@ -21,7 +21,7 @@ public class Performance extends Module { public static BooleanSetting staticParticleColor = new BooleanSetting("StaticParticleColor", true); public static BooleanSetting limitChunks = new BooleanSetting("LimitChunks", true); public static BooleanSetting batchModelRendering = new BooleanSetting("BatchModelRendering", true); - public static BooleanSetting lowAnimationTick = new BooleanSetting("LowAnimationTick", true);; + public static BooleanSetting lowAnimationTick = new BooleanSetting("LowAnimationTick", true); public static NumberSetting chunkUpdateLimit = new NumberSetting("ChunkUpdateLimit", 50, 0, 250, 1); public static NumberSetting fpsLimit = new NumberSetting("FPSLimit", 30, 0, 360, 1); diff --git a/shared/java/top/fpsmaster/features/impl/optimizes/SmoothZoom.java b/shared/java/top/fpsmaster/features/impl/optimizes/SmoothZoom.java index c20716c8..b448fc84 100644 --- a/shared/java/top/fpsmaster/features/impl/optimizes/SmoothZoom.java +++ b/shared/java/top/fpsmaster/features/impl/optimizes/SmoothZoom.java @@ -12,8 +12,8 @@ public class SmoothZoom extends Module { - private BindSetting zoomBind = new BindSetting("ZoomBind", Keyboard.KEY_C); - private BooleanSetting smoothMouse = new BooleanSetting("SmoothMouse", false); + private final BindSetting zoomBind = new BindSetting("ZoomBind", Keyboard.KEY_C); + private final BooleanSetting smoothMouse = new BooleanSetting("SmoothMouse", false); public SmoothZoom() { super("SmoothZoom", Category.OPTIMIZE); diff --git a/shared/java/top/fpsmaster/features/impl/render/BlockOverlay.java b/shared/java/top/fpsmaster/features/impl/render/BlockOverlay.java index f10611ed..b7415077 100644 --- a/shared/java/top/fpsmaster/features/impl/render/BlockOverlay.java +++ b/shared/java/top/fpsmaster/features/impl/render/BlockOverlay.java @@ -21,12 +21,12 @@ import java.awt.*; public class BlockOverlay extends Module { - private BooleanSetting fill = new BooleanSetting("Fill", true); - private BooleanSetting outline = new BooleanSetting("Outline", true); - private BooleanSetting throughBlock = new BooleanSetting("ThroughBlock", false); - private NumberSetting width = new NumberSetting("Width", 1, 0.1, 10, 0.1, ()->outline.getValue()); - private ColorSetting color1 = new ColorSetting("FillColor", new Color(255, 255, 255, 50), ()->fill.getValue()); - private ColorSetting color2 = new ColorSetting("OutlineColor", new Color(255, 255, 255, 255), ()->outline.getValue()); + private final BooleanSetting fill = new BooleanSetting("Fill", true); + private final BooleanSetting outline = new BooleanSetting("Outline", true); + private final BooleanSetting throughBlock = new BooleanSetting("ThroughBlock", false); + private final NumberSetting width = new NumberSetting("Width", 1, 0.1, 10, 0.1, ()->outline.getValue()); + private final ColorSetting color1 = new ColorSetting("FillColor", new Color(255, 255, 255, 50), ()->fill.getValue()); + private final ColorSetting color2 = new ColorSetting("OutlineColor", new Color(255, 255, 255, 255), ()->outline.getValue()); public static boolean using = false; public BlockOverlay(){ diff --git a/shared/java/top/fpsmaster/features/impl/render/FreeLook.java b/shared/java/top/fpsmaster/features/impl/render/FreeLook.java index 5aadad26..289e8ec6 100644 --- a/shared/java/top/fpsmaster/features/impl/render/FreeLook.java +++ b/shared/java/top/fpsmaster/features/impl/render/FreeLook.java @@ -11,7 +11,7 @@ import top.fpsmaster.wrapper.mods.WrapperFreeLook; public class FreeLook extends Module { - private BindSetting bind = new BindSetting("bind", Keyboard.KEY_LMENU); + private final BindSetting bind = new BindSetting("bind", Keyboard.KEY_LMENU); public FreeLook() { super("FreeLook", Category.RENDER); diff --git a/shared/java/top/fpsmaster/features/impl/render/Hitboxes.java b/shared/java/top/fpsmaster/features/impl/render/Hitboxes.java index 2e2630e2..01dc27ee 100644 --- a/shared/java/top/fpsmaster/features/impl/render/Hitboxes.java +++ b/shared/java/top/fpsmaster/features/impl/render/Hitboxes.java @@ -10,7 +10,7 @@ import java.awt.*; public class Hitboxes extends Module { - private ColorSetting color = new ColorSetting("Color", new Color(255, 255, 255, 255)); + private final ColorSetting color = new ColorSetting("Color", new Color(255, 255, 255, 255)); public static boolean using = false; public Hitboxes(){ super("HitBoxes", Category.RENDER); diff --git a/shared/java/top/fpsmaster/features/impl/render/MotionBlur.java b/shared/java/top/fpsmaster/features/impl/render/MotionBlur.java index 592d57fa..f6fb2ce5 100644 --- a/shared/java/top/fpsmaster/features/impl/render/MotionBlur.java +++ b/shared/java/top/fpsmaster/features/impl/render/MotionBlur.java @@ -32,8 +32,8 @@ public class MotionBlur extends Module { private static Framebuffer blurBufferMain; private static Framebuffer blurBufferInto; - private ModeSetting mode = new ModeSetting("Mode", 1, "Old", "New"); - private NumberSetting multiplier = new NumberSetting("Strength", 2, 0, 10, 0.5); + private final ModeSetting mode = new ModeSetting("Mode", 1, "Old", "New"); + private final NumberSetting multiplier = new NumberSetting("Strength", 2, 0, 10, 0.5); public MotionBlur() { super("MotionBlur", Category.RENDER); diff --git a/shared/java/top/fpsmaster/features/impl/utility/ChatBot.java b/shared/java/top/fpsmaster/features/impl/utility/ChatBot.java index 2b1b3dee..06cf1e82 100644 --- a/shared/java/top/fpsmaster/features/impl/utility/ChatBot.java +++ b/shared/java/top/fpsmaster/features/impl/utility/ChatBot.java @@ -37,7 +37,7 @@ public class ChatBot extends Module { NumberSetting delay = new NumberSetting("responddelay", 500, 0, 5000, 10); MathTimer timer = new MathTimer(); - private ArrayList msgs = new ArrayList<>(); + private final ArrayList msgs = new ArrayList<>(); public ChatBot() { super("ChatBot", Category.Utility); diff --git a/shared/java/top/fpsmaster/features/impl/utility/LevelTag.java b/shared/java/top/fpsmaster/features/impl/utility/LevelTag.java index eb9441c9..38527427 100644 --- a/shared/java/top/fpsmaster/features/impl/utility/LevelTag.java +++ b/shared/java/top/fpsmaster/features/impl/utility/LevelTag.java @@ -86,10 +86,10 @@ else if (mc.gameSettings.thirdPersonView == 1) int j = fontRenderer.getStringWidth(str) / 2; GlStateManager.disableTexture2D(); worldRenderer.begin(7, DefaultVertexFormats.POSITION_COLOR); - worldRenderer.pos((double)(-j - 1), (double)(-1 + i), (double)0.0F).color(0.0F, 0.0F, 0.0F, 0.25F).endVertex(); - worldRenderer.pos((double)(-j - 1), (double)(8 + i), (double)0.0F).color(0.0F, 0.0F, 0.0F, 0.25F).endVertex(); - worldRenderer.pos((double)(j + 1), (double)(8 + i), (double)0.0F).color(0.0F, 0.0F, 0.0F, 0.25F).endVertex(); - worldRenderer.pos((double)(j + 1), (double)(-1 + i), (double)0.0F).color(0.0F, 0.0F, 0.0F, 0.25F).endVertex(); + worldRenderer.pos(-j - 1, -1 + i, 0.0F).color(0.0F, 0.0F, 0.0F, 0.25F).endVertex(); + worldRenderer.pos(-j - 1, 8 + i, 0.0F).color(0.0F, 0.0F, 0.0F, 0.25F).endVertex(); + worldRenderer.pos(j + 1, 8 + i, 0.0F).color(0.0F, 0.0F, 0.0F, 0.25F).endVertex(); + worldRenderer.pos(j + 1, -1 + i, 0.0F).color(0.0F, 0.0F, 0.0F, 0.25F).endVertex(); tessellator.draw(); GlStateManager.enableTexture2D(); fontRenderer.drawString(str, -fontRenderer.getStringWidth(str) / 2, i, 553648127); diff --git a/shared/java/top/fpsmaster/features/impl/utility/SkinChanger.java b/shared/java/top/fpsmaster/features/impl/utility/SkinChanger.java index 26bc110a..393c7c15 100644 --- a/shared/java/top/fpsmaster/features/impl/utility/SkinChanger.java +++ b/shared/java/top/fpsmaster/features/impl/utility/SkinChanger.java @@ -11,7 +11,7 @@ public class SkinChanger extends Module { - private TextSetting skinName = new TextSetting("Skin", ""); + private final TextSetting skinName = new TextSetting("Skin", ""); private Thread updateThread = new Thread(() -> { while (true) { update(); diff --git a/shared/java/top/fpsmaster/features/impl/utility/TNTTimer.java b/shared/java/top/fpsmaster/features/impl/utility/TNTTimer.java index 50c90d86..7ff299a1 100644 --- a/shared/java/top/fpsmaster/features/impl/utility/TNTTimer.java +++ b/shared/java/top/fpsmaster/features/impl/utility/TNTTimer.java @@ -16,7 +16,7 @@ public class TNTTimer extends Module { private static boolean using = false; - private static NumberSetting duration = new NumberSetting("Duration", 4, 1, 10, 0.1); + private static final NumberSetting duration = new NumberSetting("Duration", 4, 1, 10, 0.1); public TNTTimer() { super("TNTTimer", Category.Utility); diff --git a/shared/java/top/fpsmaster/features/impl/utility/TimeChanger.java b/shared/java/top/fpsmaster/features/impl/utility/TimeChanger.java index 50e97fd0..04e26b02 100644 --- a/shared/java/top/fpsmaster/features/impl/utility/TimeChanger.java +++ b/shared/java/top/fpsmaster/features/impl/utility/TimeChanger.java @@ -10,7 +10,7 @@ public class TimeChanger extends Module { - private NumberSetting time; + private final NumberSetting time; public TimeChanger() { super("TimeChanger", Category.Utility); diff --git a/shared/java/top/fpsmaster/features/manager/Module.java b/shared/java/top/fpsmaster/features/manager/Module.java index 769b6e23..d09014d1 100644 --- a/shared/java/top/fpsmaster/features/manager/Module.java +++ b/shared/java/top/fpsmaster/features/manager/Module.java @@ -36,17 +36,17 @@ public void addSettings(Setting... settings) { for (Setting setting : settings) { if (setting != null) { if (setting instanceof BooleanSetting) { - this.settings.add((BooleanSetting) setting); + this.settings.add(setting); } else if (setting instanceof BindSetting) { - this.settings.add((BindSetting) setting); + this.settings.add(setting); } else if (setting instanceof ModeSetting) { - this.settings.add((ModeSetting) setting); + this.settings.add(setting); } else if (setting instanceof NumberSetting) { - this.settings.add((NumberSetting) setting); + this.settings.add(setting); } else if (setting instanceof TextSetting) { - this.settings.add((TextSetting) setting); + this.settings.add(setting); } else if (setting instanceof ColorSetting) { - this.settings.add((ColorSetting) setting); + this.settings.add(setting); } } } diff --git a/shared/java/top/fpsmaster/features/settings/Setting.java b/shared/java/top/fpsmaster/features/settings/Setting.java index 5885ba1a..3966366b 100644 --- a/shared/java/top/fpsmaster/features/settings/Setting.java +++ b/shared/java/top/fpsmaster/features/settings/Setting.java @@ -25,7 +25,7 @@ public boolean getVisible() { // Functional interface to represent the visibility check (similar to the Kotlin lambda) public interface VisibleCondition { - abstract boolean isVisible(); + boolean isVisible(); } public T getValue() { diff --git a/shared/java/top/fpsmaster/features/settings/impl/ModeSetting.java b/shared/java/top/fpsmaster/features/settings/impl/ModeSetting.java index 5baabb9e..dabc6838 100644 --- a/shared/java/top/fpsmaster/features/settings/impl/ModeSetting.java +++ b/shared/java/top/fpsmaster/features/settings/impl/ModeSetting.java @@ -6,7 +6,7 @@ public class ModeSetting extends Setting { - private String[] modes; + private final String[] modes; public ModeSetting(String name, int value, String... modes) { super(name, value); diff --git a/shared/java/top/fpsmaster/modules/config/ConfigManager.java b/shared/java/top/fpsmaster/modules/config/ConfigManager.java index 4b87f40d..9c3781e7 100644 --- a/shared/java/top/fpsmaster/modules/config/ConfigManager.java +++ b/shared/java/top/fpsmaster/modules/config/ConfigManager.java @@ -22,7 +22,7 @@ public class ConfigManager { - private Gson gson = new GsonBuilder().setPrettyPrinting().create(); + private final Gson gson = new GsonBuilder().setPrettyPrinting().create(); public Configure configure = new Configure(); diff --git a/shared/java/top/fpsmaster/modules/i18n/Language.java b/shared/java/top/fpsmaster/modules/i18n/Language.java index 5ee75c6c..17bc4c92 100644 --- a/shared/java/top/fpsmaster/modules/i18n/Language.java +++ b/shared/java/top/fpsmaster/modules/i18n/Language.java @@ -7,7 +7,7 @@ import java.util.Map; public class Language { - private Map prompts = new HashMap<>(); + private final Map prompts = new HashMap<>(); public Language() { FileUtils.release("en_us"); diff --git a/shared/java/top/fpsmaster/modules/music/IngameOverlay.java b/shared/java/top/fpsmaster/modules/music/IngameOverlay.java index 97a552c9..3d0e8abc 100644 --- a/shared/java/top/fpsmaster/modules/music/IngameOverlay.java +++ b/shared/java/top/fpsmaster/modules/music/IngameOverlay.java @@ -66,7 +66,7 @@ public static void drawSong(float x, float y, float width, float height) { Render2DUtils.drawOptimizedRoundedRect(x, y, width, height, new Color(0, 0, 0, 180)); Render2DUtils.drawOptimizedRoundedRect(x, y, songProgress, height, MusicOverlay.progressColor.getColor()); - songProgress = (float) AnimationUtils.base((double) songProgress, 6 + (width - 6) * MusicPlayer.curPlayProgress, 0.1); + songProgress = (float) AnimationUtils.base(songProgress, 6 + (width - 6) * MusicPlayer.curPlayProgress, 0.1); Render2DUtils.drawImage( new ResourceLocation("music/netease/" + current.id), diff --git a/shared/java/top/fpsmaster/modules/music/JLayerHelper.java b/shared/java/top/fpsmaster/modules/music/JLayerHelper.java index 486fdbe9..3bf996e0 100644 --- a/shared/java/top/fpsmaster/modules/music/JLayerHelper.java +++ b/shared/java/top/fpsmaster/modules/music/JLayerHelper.java @@ -104,9 +104,7 @@ private static double[] performFFT(byte[] buffer) { int fftSize = 1024; double[] paddedData = new double[fftSize]; - for (int i = 0; i < min(fftSize, audioData.length); i++) { - paddedData[i] = audioData[i]; - } + System.arraycopy(audioData, 0, paddedData, 0, min(fftSize, audioData.length)); DoubleFFT_1D fft = new DoubleFFT_1D(fftSize); fft.realForward(paddedData); diff --git a/shared/java/top/fpsmaster/modules/music/netease/deserialize/MusicWrapper.java b/shared/java/top/fpsmaster/modules/music/netease/deserialize/MusicWrapper.java index 1062a390..c10a3669 100644 --- a/shared/java/top/fpsmaster/modules/music/netease/deserialize/MusicWrapper.java +++ b/shared/java/top/fpsmaster/modules/music/netease/deserialize/MusicWrapper.java @@ -16,7 +16,7 @@ import java.util.Iterator; public class MusicWrapper { - private static Gson gson = new GsonBuilder().create(); + private static final Gson gson = new GsonBuilder().create(); public static String getSongUrl(String id) { JsonObject jsonObject = gson.fromJson(NeteaseApi.getPlayURL(id), JsonObject.class); diff --git a/shared/java/top/fpsmaster/ui/click/CategoryComponent.java b/shared/java/top/fpsmaster/ui/click/CategoryComponent.java index 566e4d32..380041b2 100644 --- a/shared/java/top/fpsmaster/ui/click/CategoryComponent.java +++ b/shared/java/top/fpsmaster/ui/click/CategoryComponent.java @@ -12,7 +12,7 @@ public class CategoryComponent { public Category category; - private ColorAnimation animationName = new ColorAnimation(); + private final ColorAnimation animationName = new ColorAnimation(); public ColorAnimation categorySelectionColor = new ColorAnimation(); public CategoryComponent(Category category) { diff --git a/shared/java/top/fpsmaster/ui/click/component/ScrollContainer.java b/shared/java/top/fpsmaster/ui/click/component/ScrollContainer.java index c220e0a5..c480631b 100644 --- a/shared/java/top/fpsmaster/ui/click/component/ScrollContainer.java +++ b/shared/java/top/fpsmaster/ui/click/component/ScrollContainer.java @@ -78,7 +78,7 @@ public void draw(float x, float y, float width, float height, int mouseX, int mo float maxUp = this.height - height; wheel_anim = Math.min(Math.max(wheel_anim, -maxUp), 0f); } - wheel = (float) AnimationUtils.base((double) wheel, (double) wheel_anim, 0.2); + wheel = (float) AnimationUtils.base(wheel, wheel_anim, 0.2); } } diff --git a/shared/java/top/fpsmaster/ui/click/modules/impl/BooleanSettingRender.java b/shared/java/top/fpsmaster/ui/click/modules/impl/BooleanSettingRender.java index 03904eba..94d0b9cc 100644 --- a/shared/java/top/fpsmaster/ui/click/modules/impl/BooleanSettingRender.java +++ b/shared/java/top/fpsmaster/ui/click/modules/impl/BooleanSettingRender.java @@ -13,7 +13,7 @@ public class BooleanSettingRender extends SettingRender { // animation - private ColorAnimation box = new ColorAnimation(new Color(255, 255, 255, 0)); + private final ColorAnimation box = new ColorAnimation(new Color(255, 255, 255, 0)); public BooleanSettingRender(Module mod, BooleanSetting setting) { super(setting); diff --git a/shared/java/top/fpsmaster/ui/click/modules/impl/TextSettingRender.java b/shared/java/top/fpsmaster/ui/click/modules/impl/TextSettingRender.java index 342a08b0..a3bd7b9e 100644 --- a/shared/java/top/fpsmaster/ui/click/modules/impl/TextSettingRender.java +++ b/shared/java/top/fpsmaster/ui/click/modules/impl/TextSettingRender.java @@ -11,7 +11,7 @@ import java.util.Locale; public class TextSettingRender extends SettingRender { - private TextField inputBox; + private final TextField inputBox; public TextSettingRender(Module mod, TextSetting setting) { super(setting); diff --git a/shared/java/top/fpsmaster/ui/click/music/MusicPanel.java b/shared/java/top/fpsmaster/ui/click/music/MusicPanel.java index 50dc5714..3f04c9ed 100644 --- a/shared/java/top/fpsmaster/ui/click/music/MusicPanel.java +++ b/shared/java/top/fpsmaster/ui/click/music/MusicPanel.java @@ -33,17 +33,17 @@ public class MusicPanel { private static Thread searchThread = null; private static float playProgress = 0f; - private static SearchBox inputBox = new SearchBox(FPSMaster.i18n.get("music.search"), () -> { + private static final SearchBox inputBox = new SearchBox(FPSMaster.i18n.get("music.search"), () -> { searchThread = new Thread(MusicPanel::run); searchThread.start(); }); - private static String[] pages = {"music.name", "music.list", "music.daily"}; + private static final String[] pages = {"music.name", "music.list", "music.daily"}; private static int curSearch = 0; private static boolean isWaitingLogin = false; private static String key = null; private static Thread loginThread = null; - private static ScrollContainer container = new ScrollContainer(); + private static final ScrollContainer container = new ScrollContainer(); public static int code = 801; public static String nickname = "Unknown"; @@ -225,8 +225,8 @@ public static void draw(float x, float y, float width, float height, int mouseX, FPSMaster.fontManager.s16.drawString(music.name + " " + music.author, x + 60, dY.get() + 10, new Color(234, 234, 234).getRGB()); FPSMaster.fontManager.s16.drawString(music.author, x + 60, dY.get() + 20, new Color(162, 162, 162).getRGB()); } - dY.updateAndGet(v -> new Float((float) (v + 40f))); - musicHeight.updateAndGet(v -> new Float((float) (v + 40f))); + dY.updateAndGet(v -> new Float(v + 40f)); + musicHeight.updateAndGet(v -> new Float(v + 40f)); } container.setHeight(musicHeight.get()); }); diff --git a/shared/java/top/fpsmaster/ui/click/music/NewMusicPanel.java b/shared/java/top/fpsmaster/ui/click/music/NewMusicPanel.java index 943720e2..5f10088a 100644 --- a/shared/java/top/fpsmaster/ui/click/music/NewMusicPanel.java +++ b/shared/java/top/fpsmaster/ui/click/music/NewMusicPanel.java @@ -10,8 +10,8 @@ public class NewMusicPanel { private static Thread playThread; - private static PlayList playList = new PlayList(); - private static PlayList displayList = new PlayList(); + private static final PlayList playList = new PlayList(); + private static final PlayList displayList = new PlayList(); public static void draw(float x, int y, float width, float height, int mouseX, int mouseY, int scaleFactor) { diff --git a/shared/java/top/fpsmaster/ui/click/music/SearchBox.java b/shared/java/top/fpsmaster/ui/click/music/SearchBox.java index d42d740f..5731f071 100644 --- a/shared/java/top/fpsmaster/ui/click/music/SearchBox.java +++ b/shared/java/top/fpsmaster/ui/click/music/SearchBox.java @@ -13,7 +13,7 @@ import java.awt.*; public class SearchBox extends Gui { - private UFontRenderer font; + private final UFontRenderer font; private float width; private float height; @@ -21,21 +21,21 @@ public class SearchBox extends Gui { private float yPosition; private String text = ""; - private int maxStringLength = 1000; + private final int maxStringLength = 1000; private int cursorCounter; - private boolean enableBackgroundDrawing = true; + private final boolean enableBackgroundDrawing = true; private boolean canLoseFocus = true; private boolean isFocused; private boolean isEnabled = true; - private int lineScrollOffset = 0; + private final int lineScrollOffset = 0; private int cursorPosition = 0; private int selectionEnd = 0; - private Color enabledColor; - private Color disabledColor; + private final Color enabledColor; + private final Color disabledColor; - private Predicate validator = Predicates.alwaysTrue(); + private final Predicate validator = Predicates.alwaysTrue(); private String placeholder = ""; - private ColorAnimation btnColor = new ColorAnimation(); + private final ColorAnimation btnColor = new ColorAnimation(); private boolean visible = true; private Runnable runnable; diff --git a/shared/java/top/fpsmaster/ui/common/GuiButton.java b/shared/java/top/fpsmaster/ui/common/GuiButton.java index 171ff2af..2d97f34b 100644 --- a/shared/java/top/fpsmaster/ui/common/GuiButton.java +++ b/shared/java/top/fpsmaster/ui/common/GuiButton.java @@ -16,7 +16,7 @@ public class GuiButton { private float height = 0f; Color color; Color hoverColor; - private ColorAnimation btnColor = new ColorAnimation(new Color(113, 127, 254)); + private final ColorAnimation btnColor = new ColorAnimation(new Color(113, 127, 254)); public GuiButton(String text, Runnable runnable, Color color, Color hoverColor) { diff --git a/shared/java/top/fpsmaster/ui/custom/impl/MiniMapComponent.java b/shared/java/top/fpsmaster/ui/custom/impl/MiniMapComponent.java index 9d53447b..df16b69f 100644 --- a/shared/java/top/fpsmaster/ui/custom/impl/MiniMapComponent.java +++ b/shared/java/top/fpsmaster/ui/custom/impl/MiniMapComponent.java @@ -16,7 +16,7 @@ public class MiniMapComponent extends Component { private boolean loadedMinimap = false; - private XaeroMinimap minimap = new XaeroMinimap(); + private final XaeroMinimap minimap = new XaeroMinimap(); public MiniMapComponent() { super(MiniMap.class); diff --git a/shared/java/top/fpsmaster/ui/custom/impl/TargetHUDComponent.java b/shared/java/top/fpsmaster/ui/custom/impl/TargetHUDComponent.java index 00ea9b1d..fd91712a 100644 --- a/shared/java/top/fpsmaster/ui/custom/impl/TargetHUDComponent.java +++ b/shared/java/top/fpsmaster/ui/custom/impl/TargetHUDComponent.java @@ -17,7 +17,7 @@ public class TargetHUDComponent extends Component { private float animation = 0f; private float healthWidth = 0f; - private ColorAnimation colorAnimation = new ColorAnimation(); + private final ColorAnimation colorAnimation = new ColorAnimation(); public TargetHUDComponent() { super(TargetDisplay.class); @@ -39,7 +39,7 @@ public void draw(float x, float y) { if (target1 == null) return; // Set width and height - String name = ((Entity) target1).getDisplayName().getFormattedText(); + String name = target1.getDisplayName().getFormattedText(); if (name.length() > 12 && TargetDisplay.omit.getValue()) { name = name.substring(0, 10) + ".."; @@ -53,8 +53,8 @@ public void draw(float x, float y) { : (float) AnimationUtils.base(animation, 80.0, 0.1); // Health width - float health = ((EntityPlayer) target1).getHealth(); - float maxHealth = ((EntityPlayer) target1).getMaxHealth(); + float health = target1.getHealth(); + float maxHealth = target1.getMaxHealth(); healthWidth = (float) AnimationUtils.base(healthWidth, (health / maxHealth), 0.1); // Set color based on health percentage diff --git a/shared/java/top/fpsmaster/ui/devspace/DevSpace.java b/shared/java/top/fpsmaster/ui/devspace/DevSpace.java index 9b20f4e4..46e766eb 100644 --- a/shared/java/top/fpsmaster/ui/devspace/DevSpace.java +++ b/shared/java/top/fpsmaster/ui/devspace/DevSpace.java @@ -259,7 +259,7 @@ public static ExpressionComponent parseExpression(Expression expression) { if (expression instanceof Expression.AnonymousFunctionExpression) return new AnonymousFunctionExpressionComponent((Expression.AnonymousFunctionExpression) expression); if (expression instanceof Expression.NilLiteralExpression) - return new NilLiteralExpressionComponent((Expression.NilLiteralExpression) expression); + return new NilLiteralExpressionComponent(expression); return new LiteralExpressionComponent(new Expression.LiteralExpression("UNKNOWN", expression.getClass().getSimpleName())); } diff --git a/shared/java/top/fpsmaster/ui/mc/GuiMultiplayer.java b/shared/java/top/fpsmaster/ui/mc/GuiMultiplayer.java index 0c08b282..e1946220 100644 --- a/shared/java/top/fpsmaster/ui/mc/GuiMultiplayer.java +++ b/shared/java/top/fpsmaster/ui/mc/GuiMultiplayer.java @@ -39,10 +39,10 @@ public class GuiMultiplayer extends ScaledGuiScreen { private final List servers = Lists.newArrayList(); private final List serverListDisplay = Lists.newArrayList(); private final List serverListInternet = Lists.newArrayList(); - private static List serverListRecommended = Lists.newArrayList(); + private static final List serverListRecommended = Lists.newArrayList(); public final OldServerPinger oldServerPinger = new OldServerPinger(); - private Gson gson = new GsonBuilder().setPrettyPrinting().create(); + private final Gson gson = new GsonBuilder().setPrettyPrinting().create(); String action = ""; @@ -54,12 +54,12 @@ public class GuiMultiplayer extends ScaledGuiScreen { FMLClientHandler.instance().connectToServer(this, selectedServer); }, new Color(0, 0, 0, 140), new Color(113, 127, 254)); GuiButton connect = new GuiButton("直接连接", () -> { - this.mc.displayGuiScreen(new GuiScreenServerList(this, this.selectedServer = new ServerData(I18n.format("selectServer.defaultName", new Object[0]), "", false))); + this.mc.displayGuiScreen(new GuiScreenServerList(this, this.selectedServer = new ServerData(I18n.format("selectServer.defaultName"), "", false))); action = "connect"; }, new Color(0, 0, 0, 140), new Color(113, 127, 254)); GuiButton add = new GuiButton("添加服务器", () -> { action = "add"; - this.mc.displayGuiScreen(new GuiScreenAddServer(this, this.selectedServer = new ServerData(I18n.format("selectServer.defaultName", new Object[0]), "", false))); + this.mc.displayGuiScreen(new GuiScreenAddServer(this, this.selectedServer = new ServerData(I18n.format("selectServer.defaultName"), "", false))); }, new Color(0, 0, 0, 140), new Color(113, 127, 254)); GuiButton edit = new GuiButton("编辑", () -> { if (selectedServer == null) @@ -73,10 +73,10 @@ public class GuiMultiplayer extends ScaledGuiScreen { action = "remove"; String s4 = selectedServer.serverName; if (s4 != null) { - String s = I18n.format("selectServer.deleteQuestion", new Object[0]); - String s1 = "'" + s4 + "' " + I18n.format("selectServer.deleteWarning", new Object[0]); - String s2 = I18n.format("selectServer.deleteButton", new Object[0]); - String s3 = I18n.format("gui.cancel", new Object[0]); + String s = I18n.format("selectServer.deleteQuestion"); + String s1 = "'" + s4 + "' " + I18n.format("selectServer.deleteWarning"); + String s2 = I18n.format("selectServer.deleteButton"); + String s3 = I18n.format("gui.cancel"); GuiYesNo guiyesno = new GuiYesNo(this, s, s1, s2, s3, servers.indexOf(selectedServer)); this.mc.displayGuiScreen(guiyesno); } diff --git a/shared/java/top/fpsmaster/ui/mc/ServerListEntry.java b/shared/java/top/fpsmaster/ui/mc/ServerListEntry.java index 1711dce6..bc874d84 100644 --- a/shared/java/top/fpsmaster/ui/mc/ServerListEntry.java +++ b/shared/java/top/fpsmaster/ui/mc/ServerListEntry.java @@ -97,7 +97,7 @@ public void drawEntry(int slotIndex, int x, int y, int listWidth, int slotHeight List list = text.listFormattedStringToWidth(FMLClientHandler.instance().fixDescription(this.server.serverMOTD), listWidth - 48 - 2); for (int i = 0; i < Math.min(list.size(), 2); ++i) { - text.drawString((String) list.get(i), x + 32 + 3 + 10, y + 12 + 10 + this.mc.fontRendererObj.FONT_HEIGHT * i, -1); + text.drawString(list.get(i), x + 32 + 3 + 10, y + 12 + 10 + this.mc.fontRendererObj.FONT_HEIGHT * i, -1); } String s2 = flag2 ? EnumChatFormatting.DARK_RED + this.server.gameVersion : this.server.populationInfo; @@ -134,7 +134,7 @@ public void drawEntry(int slotIndex, int x, int y, int listWidth, int slotHeight } } else { k = 1; - l = (int) (Minecraft.getSystemTime() / 100L + (long) (slotIndex * 2) & 7L); + l = (int) (Minecraft.getSystemTime() / 100L + (long) (slotIndex * 2L) & 7L); if (l > 4) { l = 8 - l; } @@ -229,12 +229,12 @@ private void prepareServerIcon() { { try { bufferedimage = TextureUtil.readBufferedImage(new ByteBufInputStream(bytebuf1)); - Validate.validState(bufferedimage.getWidth() == 64, "Must be 64 pixels wide", new Object[0]); - Validate.validState(bufferedimage.getHeight() == 64, "Must be 64 pixels high", new Object[0]); + Validate.validState(bufferedimage.getWidth() == 64, "Must be 64 pixels wide"); + Validate.validState(bufferedimage.getHeight() == 64, "Must be 64 pixels high"); break label80; } catch (Throwable throwable) { logger.error("Invalid icon for server " + this.server.serverName + " (" + this.server.serverIP + ")", throwable); - this.server.setBase64EncodedIconData((String) null); + this.server.setBase64EncodedIconData(null); } finally { bytebuf.release(); bytebuf1.release(); diff --git a/shared/java/top/fpsmaster/ui/notification/Notification.java b/shared/java/top/fpsmaster/ui/notification/Notification.java index c956fb65..e97ac219 100644 --- a/shared/java/top/fpsmaster/ui/notification/Notification.java +++ b/shared/java/top/fpsmaster/ui/notification/Notification.java @@ -16,8 +16,8 @@ public class Notification { public Animation animation; private float positionY; - private float width; - private float height; + private final float width; + private final float height; private long startTime = -1L; public Notification(String title, String description, Type type, float time) { diff --git a/shared/java/top/fpsmaster/ui/screens/mainmenu/MenuButton.java b/shared/java/top/fpsmaster/ui/screens/mainmenu/MenuButton.java index 32e38af9..efe689f3 100644 --- a/shared/java/top/fpsmaster/ui/screens/mainmenu/MenuButton.java +++ b/shared/java/top/fpsmaster/ui/screens/mainmenu/MenuButton.java @@ -8,8 +8,8 @@ import java.awt.*; public class MenuButton { - private String text; - private Runnable runnable; + private final String text; + private final Runnable runnable; private float x; private float y; private float width; diff --git a/shared/java/top/fpsmaster/ui/screens/oobe/GuiLogin.java b/shared/java/top/fpsmaster/ui/screens/oobe/GuiLogin.java index 3a9f7197..b34710e5 100644 --- a/shared/java/top/fpsmaster/ui/screens/oobe/GuiLogin.java +++ b/shared/java/top/fpsmaster/ui/screens/oobe/GuiLogin.java @@ -7,7 +7,7 @@ public class GuiLogin extends GuiScreen { - private static Login login = new Login(false); + private static final Login login = new Login(false); @Override public void drawScreen(int mouseX, int mouseY, float partialTicks) { diff --git a/shared/java/top/fpsmaster/utils/awt/AWTUtils.java b/shared/java/top/fpsmaster/utils/awt/AWTUtils.java index 57c3ea74..972cc793 100644 --- a/shared/java/top/fpsmaster/utils/awt/AWTUtils.java +++ b/shared/java/top/fpsmaster/utils/awt/AWTUtils.java @@ -10,8 +10,8 @@ import java.util.HashMap; public class AWTUtils { - private static HashMap generated = new HashMap<>(); - private static HashMap generatedFull = new HashMap<>(); + private static final HashMap generated = new HashMap<>(); + private static final HashMap generatedFull = new HashMap<>(); public static ResourceLocation generateRoundImage(int width, int height, int radius) { ResourceLocation location = generatedFull.get(radius); diff --git a/shared/java/top/fpsmaster/utils/math/animation/ColorAnimation.java b/shared/java/top/fpsmaster/utils/math/animation/ColorAnimation.java index cb7a89e9..b5794e02 100644 --- a/shared/java/top/fpsmaster/utils/math/animation/ColorAnimation.java +++ b/shared/java/top/fpsmaster/utils/math/animation/ColorAnimation.java @@ -5,10 +5,10 @@ import java.awt.*; public class ColorAnimation { - private Animation r = new Animation(); - private Animation g = new Animation(); - private Animation b = new Animation(); - private Animation a = new Animation(); + private final Animation r = new Animation(); + private final Animation g = new Animation(); + private final Animation b = new Animation(); + private final Animation a = new Animation(); private boolean first = true; Color color; private Color end; @@ -25,10 +25,10 @@ public ColorAnimation(int red, int green, int blue, int alpha) { public void start(Color start, Color end, float duration, Type type) { this.end = end; - r.start((double) start.getRed(), (double) end.getRed(), duration, type); - g.start((double) start.getGreen(), (double) end.getGreen(), duration, type); - b.start((double) start.getBlue(), (double) end.getBlue(), duration, type); - a.start((double) start.getAlpha(), (double) end.getAlpha(), duration, type); + r.start(start.getRed(), end.getRed(), duration, type); + g.start(start.getGreen(), end.getGreen(), duration, type); + b.start(start.getBlue(), end.getBlue(), duration, type); + a.start(start.getAlpha(), end.getAlpha(), duration, type); } public void update() { @@ -70,16 +70,16 @@ public void setColor(Color color) { public void fstart(Color color, Color color1, float duration, Type type) { end = color1; - r.fstart((double) color.getRed(), (double) color1.getRed(), duration, type); - g.fstart((double) color.getGreen(), (double) color1.getGreen(), duration, type); - b.fstart((double) color.getBlue(), (double) color1.getBlue(), duration, type); - a.fstart((double) color.getAlpha(), (double) color1.getAlpha(), duration, type); + r.fstart(color.getRed(), color1.getRed(), duration, type); + g.fstart(color.getGreen(), color1.getGreen(), duration, type); + b.fstart(color.getBlue(), color1.getBlue(), duration, type); + a.fstart(color.getAlpha(), color1.getAlpha(), duration, type); } public void base(Color color) { - r.value = AnimationUtils.base(r.value, (double) color.getRed(), 0.1); - g.value = AnimationUtils.base(g.value, (double) color.getGreen(), 0.1); - b.value = AnimationUtils.base(b.value, (double) color.getBlue(), 0.1); - a.value = AnimationUtils.base(a.value, (double) color.getAlpha(), 0.1); + r.value = AnimationUtils.base(r.value, color.getRed(), 0.1); + g.value = AnimationUtils.base(g.value, color.getGreen(), 0.1); + b.value = AnimationUtils.base(b.value, color.getBlue(), 0.1); + a.value = AnimationUtils.base(a.value, color.getAlpha(), 0.1); } } diff --git a/shared/java/top/fpsmaster/utils/render/shader/RoundedUtil.java b/shared/java/top/fpsmaster/utils/render/shader/RoundedUtil.java index 1f345487..4d722c36 100644 --- a/shared/java/top/fpsmaster/utils/render/shader/RoundedUtil.java +++ b/shared/java/top/fpsmaster/utils/render/shader/RoundedUtil.java @@ -12,8 +12,8 @@ import static top.fpsmaster.utils.render.shader.GradientUtils.interpolateColorC; public class RoundedUtil { - private static ShaderUtil roundedShader = new ShaderUtil("roundedRect"); - private static ShaderUtil roundedGradientShader = new ShaderUtil("roundedRectGradient"); + private static final ShaderUtil roundedShader = new ShaderUtil("roundedRect"); + private static final ShaderUtil roundedGradientShader = new ShaderUtil("roundedRectGradient"); public static Framebuffer bloomFramebuffer = new Framebuffer(1, 1, false); public static void drawRound(float x, float y, float width, float height, float radius, Color color) { From 6d78cfd12b28715313ed09a1fc8085c56a6462e9 Mon Sep 17 00:00:00 2001 From: SuperSkidder Date: Mon, 14 Jul 2025 17:54:07 +0800 Subject: [PATCH 087/193] change: remove lua parser code, use dependency instead --- shared/java/top/fpsmaster/FPSMaster.java | 13 +- .../{AsyncTask.java => ClientThreadPool.java} | 4 +- .../top/fpsmaster/modules/lua/LuaManager.java | 2 +- .../top/fpsmaster/modules/lua/LuaScript.java | 2 +- .../modules/lua/parser/Expression.java | 262 ------- .../modules/lua/parser/LuaParser.java | 14 - .../modules/lua/parser/ParseError.java | 8 - .../fpsmaster/modules/lua/parser/Parser.java | 661 ------------------ .../modules/lua/parser/Statement.java | 231 ------ .../fpsmaster/modules/lua/parser/Token.java | 243 ------- .../top/fpsmaster/ui/devspace/DevSpace.java | 4 +- .../AnonymousFunctionExpressionComponent.java | 2 +- .../BinaryExpressionComponent.java | 2 +- .../map/expressions/ExpressionComponent.java | 3 +- .../FunctionCallExpressionComponent.java | 2 +- ...FunctionDefinitionExpressionComponent.java | 2 +- .../LiteralExpressionComponent.java | 2 +- .../MemberAccessExpressionComponent.java | 2 +- .../MethodCallExpressionComponent.java | 2 +- .../NilLiteralExpressionComponent.java | 2 +- .../expressions/TableExpressionComponent.java | 2 +- .../expressions/UnaryExpressionComponent.java | 2 +- .../VariableExpressionComponent.java | 2 +- .../AssignmentStatementComponent.java | 2 +- .../ExpressionStatementComponent.java | 2 +- .../map/statements/IfStatementComponent.java | 2 +- .../LocalDeclarationStatementComponent.java | 2 +- .../statements/ReturnStatementComponent.java | 2 +- .../map/statements/StatementComponent.java | 2 +- .../top/fpsmaster/ui/mc/GuiMultiplayer.java | 6 +- v1.8.9/build.gradle.kts | 2 +- 31 files changed, 36 insertions(+), 1453 deletions(-) rename shared/java/top/fpsmaster/modules/client/{AsyncTask.java => ClientThreadPool.java} (90%) delete mode 100644 shared/java/top/fpsmaster/modules/lua/parser/Expression.java delete mode 100644 shared/java/top/fpsmaster/modules/lua/parser/LuaParser.java delete mode 100644 shared/java/top/fpsmaster/modules/lua/parser/ParseError.java delete mode 100644 shared/java/top/fpsmaster/modules/lua/parser/Parser.java delete mode 100644 shared/java/top/fpsmaster/modules/lua/parser/Statement.java delete mode 100644 shared/java/top/fpsmaster/modules/lua/parser/Token.java diff --git a/shared/java/top/fpsmaster/FPSMaster.java b/shared/java/top/fpsmaster/FPSMaster.java index c774a1a5..44afcae2 100644 --- a/shared/java/top/fpsmaster/FPSMaster.java +++ b/shared/java/top/fpsmaster/FPSMaster.java @@ -7,7 +7,7 @@ import top.fpsmaster.features.manager.ModuleManager; import top.fpsmaster.font.FontManager; import top.fpsmaster.modules.account.AccountManager; -import top.fpsmaster.modules.client.AsyncTask; +import top.fpsmaster.modules.client.ClientThreadPool; import top.fpsmaster.modules.client.ClientUsersManager; import top.fpsmaster.modules.config.ConfigManager; import top.fpsmaster.modules.i18n.Language; @@ -55,7 +55,7 @@ public class FPSMaster { public static ComponentsManager componentsManager = new ComponentsManager(); public static LuaManager luaManager = new LuaManager(); public static Language i18n = new Language(); - public static AsyncTask async = new AsyncTask(100); + public static ClientThreadPool async = new ClientThreadPool(100); public static boolean development = false; public static boolean isLatest = true; public static boolean updateFailed = false; @@ -150,8 +150,11 @@ private void checkOptifine() { } private void checkUpdate() { - AsyncTask asyncTask = new AsyncTask(100); - asyncTask.runnable(() -> { + if (development) { + isLatest = true; + return; + } + async.runnable(() -> { String s = UpdateChecker.getLatestVersion(); if (s == null || s.isEmpty()) { s = UpdateChecker.getLatestVersion(); @@ -163,8 +166,6 @@ private void checkUpdate() { } } s = s.trim(); -// ClientLogger.info("最新版本: " + s); -// ClientLogger.info("当前版本: " + GitInfo.getCommitId()); latest = s; isLatest = GitInfo.getCommitId().equals(s); }); diff --git a/shared/java/top/fpsmaster/modules/client/AsyncTask.java b/shared/java/top/fpsmaster/modules/client/ClientThreadPool.java similarity index 90% rename from shared/java/top/fpsmaster/modules/client/AsyncTask.java rename to shared/java/top/fpsmaster/modules/client/ClientThreadPool.java index ab8fa11b..f713b939 100644 --- a/shared/java/top/fpsmaster/modules/client/AsyncTask.java +++ b/shared/java/top/fpsmaster/modules/client/ClientThreadPool.java @@ -2,10 +2,10 @@ import java.util.concurrent.*; -public class AsyncTask { +public class ClientThreadPool { private final ExecutorService executorService; - public AsyncTask(int threadCount) { + public ClientThreadPool(int threadCount) { executorService = Executors.newFixedThreadPool(threadCount); } diff --git a/shared/java/top/fpsmaster/modules/lua/LuaManager.java b/shared/java/top/fpsmaster/modules/lua/LuaManager.java index 5351b251..cf5b36a8 100644 --- a/shared/java/top/fpsmaster/modules/lua/LuaManager.java +++ b/shared/java/top/fpsmaster/modules/lua/LuaManager.java @@ -9,10 +9,10 @@ import top.fpsmaster.exception.FileException; import top.fpsmaster.features.manager.Module; import top.fpsmaster.interfaces.ProviderManager; -import top.fpsmaster.modules.lua.parser.LuaParser; import top.fpsmaster.utils.Utility; import top.fpsmaster.utils.os.FileUtils; import top.fpsmaster.utils.render.Render2DUtils; +import top.skidder.parser.LuaParser; import java.awt.*; import java.io.File; diff --git a/shared/java/top/fpsmaster/modules/lua/LuaScript.java b/shared/java/top/fpsmaster/modules/lua/LuaScript.java index 30a13a47..b4854d5b 100644 --- a/shared/java/top/fpsmaster/modules/lua/LuaScript.java +++ b/shared/java/top/fpsmaster/modules/lua/LuaScript.java @@ -1,7 +1,7 @@ package top.fpsmaster.modules.lua; import party.iroiro.luajava.Lua; -import top.fpsmaster.modules.lua.parser.Statement; +import top.skidder.parser.Statement; import java.util.List; diff --git a/shared/java/top/fpsmaster/modules/lua/parser/Expression.java b/shared/java/top/fpsmaster/modules/lua/parser/Expression.java deleted file mode 100644 index 248d19e3..00000000 --- a/shared/java/top/fpsmaster/modules/lua/parser/Expression.java +++ /dev/null @@ -1,262 +0,0 @@ -package top.fpsmaster.modules.lua.parser; - -import java.util.List; -import java.util.Map; - -public class Expression { - - public static class LiteralExpression extends Expression { - public String type; - public String value; - - public LiteralExpression(String type, String value) { - this.type = type; - this.value = value; - } - - @Override - public String toString() { - return "LiteralExpression{" + - "type='" + type + '\'' + - "value='" + value + '\'' + - '}'; - } - } - - public static class BooleanLiteralExpression extends Expression { - private final boolean value; - - BooleanLiteralExpression(boolean value) { - this.value = value; - } - - public boolean getValue() { - return value; - } - - @Override - public String toString() { - return "BooleanLiteralExpression{" + - "value=" + value + - '}'; - } - } - - public static class NilLiteralExpression extends Expression { - NilLiteralExpression() { - // nil 本身没有值 - } - - @Override - public String toString() { - return "NilLiteralExpression{}"; - } - } - - public static class BinaryExpression extends Expression { - public Expression left; - public String operator; - public Expression right; - - BinaryExpression(Expression left, String operator, Expression right) { - this.left = left; - this.operator = operator; - this.right = right; - } - - @Override - public String toString() { - return "BinaryExpression{" + - "left=" + left + - ", operator='" + operator + '\'' + - ", right=" + right + - '}'; - } - } - - public static class FunctionDefinitionExpression extends Expression { - public String name; - public List parameters; - public List body; - - FunctionDefinitionExpression(String name, List parameters, List body) { - this.name = name; - this.parameters = parameters; - this.body = body; - } - - @Override - public String toString() { - return "FunctionDefinition{" + - "name='" + name + '\'' + - ", parameters=" + parameters.toString() + - ", body=" + body.toString() + - '}'; - } - } - - public static class UnaryExpression extends Expression { - public String operator; - public Expression expression; - - UnaryExpression(String operator, Expression expression) { - this.operator = operator; - this.expression = expression; - } - } - - public static class FunctionCallExpression extends Expression { - public String name; - public List arguments; - - FunctionCallExpression(String name, List arguments) { - this.name = name; - this.arguments = arguments; - } - - @Override - public String toString() { - return "FunctionCall{" + - "name='" + name + '\'' + - ", arguments=" + arguments.toString() + - '}'; - } - } - - public static class AnonymousFunctionExpression extends Expression { - public final List parameters; - public final List body; - - AnonymousFunctionExpression(List parameters, List body) { - this.parameters = parameters; - this.body = body; - } - - @Override - public String toString() { - return "AnonymousFunctionExpression{" + - "parameters=" + parameters + - ", body=" + body + - '}'; - } - } - - public static class TableExpression extends Expression { - private final List arrayElements; - private final Map tableEntries; - - public TableExpression(List arrayElements, Map tableEntries) { - this.arrayElements = arrayElements; - this.tableEntries = tableEntries; - } - - public List getArrayElements() { - return arrayElements; - } - - public Map getTableEntries() { - return tableEntries; - } - - @Override - public String toString() { - return "TableExpression{" + - "arrayElements=" + arrayElements + - ", tableEntries=" + tableEntries + - '}'; - } - } - - public static class MemberAccessExpression extends Expression { - private final Expression object; - private final String member; - - public MemberAccessExpression(Expression object, String member) { - this.object = object; - this.member = member; - } - - public Expression getObject() { - return object; - } - - public String getMember() { - return member; - } - - @Override - public String toString() { - return "MemberAccessExpression{" + - "object=" + object + - ", member='" + member + '\'' + - '}'; - } - } - - public static class MethodCallExpression extends Expression { - private final Expression object; - private final String method; - private final List arguments; - public final boolean isColonCall; - - public MethodCallExpression(Expression object, String method, List arguments) { - this(object, method, arguments, false); - } - - public MethodCallExpression(Expression object, String method, List arguments, boolean isColonCall) { - this.object = object; - this.method = method; - this.arguments = arguments; - this.isColonCall = isColonCall; - } - - public Expression getObject() { - return object; - } - - public String getMethod() { - return method; - } - - public List getArguments() { - return arguments; - } - - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append("MethodCallExpression{"); - sb.append("object=").append(object); - sb.append(", method='").append(method).append('\''); - sb.append(", arguments=["); - for (int i = 0; i < arguments.size(); i++) { - sb.append(arguments.get(i)); - if (i < arguments.size() - 1) sb.append(", "); - } - sb.append("]"); - sb.append(", isColonCall=").append(isColonCall); - sb.append('}'); - return sb.toString(); - } - } - - public static class VariableExpression extends Expression { - private final String name; - - public VariableExpression(String name) { - this.name = name; - } - - public String getName() { - return name; - } - - @Override - public String toString() { - return "VariableExpression{" + - "name='" + name + '\'' + - '}'; - } - } - -} diff --git a/shared/java/top/fpsmaster/modules/lua/parser/LuaParser.java b/shared/java/top/fpsmaster/modules/lua/parser/LuaParser.java deleted file mode 100644 index 8fb4c58d..00000000 --- a/shared/java/top/fpsmaster/modules/lua/parser/LuaParser.java +++ /dev/null @@ -1,14 +0,0 @@ -package top.fpsmaster.modules.lua.parser; - -import java.util.List; - -public class LuaParser { - public static List parse(String code) throws ParseError { - Lexer lexer = new Lexer(code); - List tokens = lexer.tokenize(); - Parser parser = new Parser(tokens); - List statements = null; - statements = parser.parseAll(); - return statements; - } -} diff --git a/shared/java/top/fpsmaster/modules/lua/parser/ParseError.java b/shared/java/top/fpsmaster/modules/lua/parser/ParseError.java deleted file mode 100644 index f6d949e6..00000000 --- a/shared/java/top/fpsmaster/modules/lua/parser/ParseError.java +++ /dev/null @@ -1,8 +0,0 @@ -package top.fpsmaster.modules.lua.parser; - -public class ParseError extends Exception { - - public ParseError(String message) { - super(message); - } -} diff --git a/shared/java/top/fpsmaster/modules/lua/parser/Parser.java b/shared/java/top/fpsmaster/modules/lua/parser/Parser.java deleted file mode 100644 index 5c4dd80f..00000000 --- a/shared/java/top/fpsmaster/modules/lua/parser/Parser.java +++ /dev/null @@ -1,661 +0,0 @@ -package top.fpsmaster.modules.lua.parser; - -import java.util.*; - -public class Parser { - private final List tokens; - private int position; - - private static final Map PRECEDENCE = new HashMap() {{ - put("^", 8); - put("not", 7); - put("#", 7); - put("unm", 7); - put("*", 6); - put("/", 6); - put("%", 6); - put("+", 5); - put("-", 5); - put("..", 4); - put("<", 3); - put(">", 3); - put("<=", 3); - put(">=", 3); - put("~=", 3); - put("==", 3); - put("and", 2); - put("or", 1); - }}; - - Parser(List tokens) { - this.tokens = tokens; - this.position = 0; - } - - // 解析主方法,支持多种语句 - Statement parse() throws ParseError { - - Token peek = peek(); - if (match("KEYWORD")) { - if ("function".equals(peek.value)) { - return new Statement.ExpressionStatement(parseFunctionDefinition()); - } else if ("local".equals(peek.value)) { - return parseLocalDeclaration(); - } else if ("return".equals(peek.value)) { - return parseReturnStatement(); - } else if ("if".equals(peek.value)) { - return parseIfStatement(); - } else if ("for".equals(peek.value)) { - return parseForStatement(); - } else if ("while".equals(peek.value)) { - return parseWhileStatement(); - } else if ("repeat".equals(peek.value)) { - return parseRepeatStatement(); - } - } else if (match("IDENTIFIER")) { - if (lookaheadIs("SYMBOL", "(")) { - return new Statement.ExpressionStatement(parseFunctionCall()); - } else if (lookaheadIs("OPERATOR", ".")) { - return new Statement.ExpressionStatement(parseExpression()); - } else if (lookaheadIs("SYMBOL", ":")) { - return new Statement.ExpressionStatement(parseExpression()); - } else if (lookaheadIs("OPERATOR", "..")) { - return new Statement.ExpressionStatement(parseExpression()); - } else if (lookaheadIs("OPERATOR", "=")) { - return parseAssignment(); - } - } - - throw new IllegalArgumentException("Unexpected token: " + peek.type + " " + peek.value + " at position " + position + " -> " + context()); - } - - public List parseAll() throws ParseError { - List statements = new ArrayList<>(); - while (position < tokens.size()) { - statements.add(parse()); - } - return statements; - } - - // 解析赋值语句 - private Statement parseAssignment() throws ParseError { - Token identifier = consume("IDENTIFIER"); - consume("OPERATOR"); // Expect '=' - Expression value = parseExpression(); - return new Statement.AssignmentStatement(identifier.value, value); - } - - // 解析函数定义 - private Expression.FunctionDefinitionExpression parseFunctionDefinition() throws ParseError { - consume("KEYWORD"); // 消费 "function" - Token functionName = consume("IDENTIFIER"); // 函数名称 - consume("SYMBOL"); // 消费 "(" - - // 解析参数列表 - List parameters = new ArrayList<>(); - while (!match("SYMBOL") || !peek().value.equals(")")) { - if (match("IDENTIFIER")) { - parameters.add(consume("IDENTIFIER").value); - } else if (match("KEYWORD") && peek().value.equals("function")) { - // 匿名函数作为参数 - parameters.add(parseAnonymousFunction().toString()); - } - if (match("SYMBOL") && peek().value.equals(",")) { - consume("SYMBOL"); // 跳过 "," - } - } - consume("SYMBOL"); // 消费 ")" - - // 解析函数体 - List body = parseBlock(); - consume("KEYWORD"); // 消费 "end" - - return new Expression.FunctionDefinitionExpression(functionName.value, parameters, body); - } - - // 解析表达式语句 - private Expression parseExpression() throws ParseError { - return parseExpression(0); // 初始优先级为 0 - } - - // 解析二元表达式,基于优先级 - private Expression parseExpression(int minPrecedence) throws ParseError { - Deque exprStack = new ArrayDeque<>(); - exprStack.push(parsePrefix()); - - while (true) { - Token opToken = peek(); - if (opToken == null) break; - - Integer currPrec = PRECEDENCE.get(getOperatorKey(opToken)); - if (currPrec == null || currPrec < minPrecedence) break; - - consumeCurrent(); - exprStack.push(parseInfix(exprStack.pop(), opToken, currPrec)); - } - - return exprStack.pop(); - } - - // 解析前缀表达式 - private Expression parsePrefix() throws ParseError { - Token token = consumeCurrent(); - switch (token.type) { - case "NUMBER": - return new Expression.LiteralExpression("NUMBER", token.value); - case "STRING": - return new Expression.LiteralExpression("STRING", token.value); - case "BOOLEAN": - return new Expression.LiteralExpression("BOOLEAN", token.value); - case "NIL": - return new Expression.NilLiteralExpression(); - case "IDENTIFIER": - return parseIdentifierExpression(token.value); - case "SYMBOL": - return handleSymbolPrefix(token.value); - case "OPERATOR": - return handleOperatorPrefix(token.value); - case "KEYWORD": - if (token.value.equals("function")) { - // 解析匿名函数 - position--; // 回退一个 - return parseAnonymousFunction(); - } - default: - throw new ParseError("Unexpected token type: " + token.type + " " + token.value + " at position " + position + " -> " + context()); - } - } - - // 处理符号前缀(括号/表) - private Expression handleSymbolPrefix(String symbol) throws ParseError { - switch (symbol) { - case "(": - Expression expr = parseExpression(0); - consume("SYMBOL", ")"); - return expr; - case "{": - position--; // 回退一个 - return parseTable(); - default: - throw new ParseError("Unexpected symbol: " + symbol); - } - } - - // 处理运算符前缀(一元运算符) - private Expression handleOperatorPrefix(String operator) throws ParseError { - if ("-".equals(operator)) { - return new Expression.UnaryExpression("-", parseExpression(getPrecedence("unm"))); - } - throw new ParseError("Unsupported prefix operator: " + operator); - } - - // 解析中缀表达式 - private Expression parseInfix(Expression left, Token opToken, int precedence) throws ParseError { - String operator = getOperatorKey(opToken); - - // 处理右结合运算符(如指数) - int nextPrecedence = ("^".equals(operator)) ? precedence - 1 : precedence; - - return new Expression.BinaryExpression( - left, - operator, - parseExpression(nextPrecedence) - ); - } - - // 处理标识符表达式(可能包含方法调用) - private Expression parseIdentifierExpression(String name) throws ParseError { - Expression expr = new Expression.VariableExpression(name); - - while (true) { - Token nextToken = peek(); - if (nextToken == null || !nextToken.type.equals("SYMBOL")) return expr; - if ("(".equals(nextToken.value)) { - expr = parseFunctionCall(expr); - } else if (".".equals(nextToken.value)) { - expr = parseMemberAccess(expr, false); - } else if (":".equals(nextToken.value)) { - expr = parseMemberAccess(expr, true); - } else { - return expr; - } - } - } - - // 解析函数调用 - private Expression parseFunctionCall(Expression function) throws ParseError { - consume("SYMBOL", "("); - List args = new ArrayList<>(); - while (!peek().value.equals(")")) { - args.add(parseExpression(0)); - if (peek().value.equals(",")) { - consumeCurrent(); - } - } - consume("SYMBOL", ")"); - return new Expression.FunctionCallExpression(((Expression.VariableExpression) function).getName(), args); - } - - // 辅助方法 - private String getOperatorKey(Token token) { - if ("KEYWORD".equals(token.type) && ("and".equals(token.value) || "or".equals(token.value))) { - return token.value; - } - return token.value; - } - - private int getPrecedence(String operator) { - return PRECEDENCE.getOrDefault(operator, -1); - } - - private Expression parseMemberAccess(Expression obj, boolean isMethod) throws ParseError { - consume("SYMBOL", isMethod ? ":" : "."); - Token member = consume("IDENTIFIER"); - - // 如果后面有参数列表则解析方法调用 - if (match("SYMBOL", "(")) { - List args = parseArguments(); - if (isMethod) { - args.add(0, obj); // 自动添加self参数 - } - return new Expression.MethodCallExpression(obj, member.value, args, isMethod); - } - - return new Expression.MemberAccessExpression(obj, member.value); - } - - private List parseArguments() throws ParseError { - consume("SYMBOL"); // 消费 "(" - List arguments = new ArrayList<>(); - while (!match("SYMBOL") || !peek().value.equals(")")) { - - if ((match("NUMBER") || match("STRING") || match("IDENTIFIER")) && (lookaheadIs("SYMBOL", ",") || lookaheadIs("SYMBOL", ")"))) { - arguments.add(parsePrimary()); // 解析基本的参数 - } else { - arguments.add(parseExpression()); // 解析表达式参数 - } - if (match("SYMBOL") && peek().value.equals(",")) { - consume("SYMBOL"); // 跳过 "," - } - } - consume("SYMBOL"); // 消费 ")" - return arguments; - } - - private Expression.FunctionCallExpression parseFunctionCall() throws ParseError { - String functionName = consume("IDENTIFIER").value; - - // 解析参数列表 - List arguments = parseArguments(); - - return new Expression.FunctionCallExpression(functionName, arguments); - } - - private Expression.TableExpression parseTable() throws ParseError { - consume("SYMBOL"); // 消费 "{" - - List arrayElements = new ArrayList<>(); - Map tableEntries = new HashMap<>(); - - while (!match("SYMBOL") || !peek().value.equals("}")) { - if (match("IDENTIFIER") && peek(1).type.equals("OPERATOR") && peek(1).value.equals("=")) { - // 解析键值对 - String key = consume("IDENTIFIER").value; - consume("OPERATOR"); // 消费 "=" - Expression value = parseExpression(); - tableEntries.put(key, value); - } else { - // 解析数组元素 - arrayElements.add(parseExpression()); - } - - // 跳过逗号 - if (match("SYMBOL") && peek().value.equals(",")) { - consume("SYMBOL"); - } - } - consume("SYMBOL"); // 消费 "}" - - return new Expression.TableExpression(arrayElements, tableEntries); - } - - - // 解析基本表达式 - private Expression parsePrimary() throws ParseError { - if (match("NUMBER")) { - Token token = consume("NUMBER"); - return new Expression.LiteralExpression("NUMBER", token.value); // 数字字面量 - } else if (match("BOOLEAN")) { - Token token = consume("BOOLEAN"); - return new Expression.LiteralExpression("BOOLEAN", token.value); // true 或 false - } else if (match("NIL")) { - consume("NIL"); - return new Expression.NilLiteralExpression(); // nil - } else if (match("SYMBOL") && peek().value.equals("{")) { - return parseTable(); // 表构造器 - } else if (match("STRING")) { - Token token = consume("STRING"); - return new Expression.LiteralExpression("STRING", token.value); // 字符串字面量 - } else if (match("SYMBOL") && peek().value.equals("(")) { - // 处理括号表达式 - consume("SYMBOL"); // 消费 "(" - Expression inner = parseExpression(); // 递归解析括号内表达式 - consume("SYMBOL"); // 消费 ")" - return inner; - } else if (match("IDENTIFIER")) { - // 解析标识符 - if (lookaheadIs("SYMBOL", "(")) { - return parseFunctionCall(); - } else { - String identifier = consume("IDENTIFIER").value; - Expression base = new Expression.VariableExpression(identifier); - - // 处理点运算符和冒号运算符 - base = parseMemberOrMethod(base); - - return base; - } - } - - throw new IllegalArgumentException( - "Unexpected token: " + peek().type + " " + peek().value + " at position " + position + " -> " + context() - ); - } - - // 解析成员访问和方法调用 - private Expression parseMemberOrMethod(Expression base) throws ParseError { - // 处理点运算符 "." - while (match("SYMBOL") && peek().value.equals(".")) { - consume("SYMBOL"); // 消费 "." - Token identifier = consume("IDENTIFIER"); // 消费字段名 - // 判断是否为函数调用 - if (match("SYMBOL") && peek().value.equals("(")) { - // 如果后面是 "(", 那么我们视为方法调用 - List arguments = parseArguments(); // 解析函数调用参数 - base = new Expression.MethodCallExpression(base, identifier.value, arguments); // 生成方法调用 - } else { - base = new Expression.MemberAccessExpression(base, identifier.value); // 否则是成员访问 - } - } - - // 处理冒号运算符 ":" - while (match("SYMBOL") && peek().value.equals(":")) { - consume("SYMBOL"); // 消费 ":" - Token identifier = consume("IDENTIFIER"); // 消费方法名 - List arguments = parseArguments(); // 解析函数调用参数 - // 对于冒号调用,自动将 base 作为第一个参数传递 - arguments.add(0, base); - base = new Expression.MethodCallExpression(base, identifier.value, arguments, true); // 自动传递对象本身作为第一个参数 - } - - return base; - } - - - // 解析局部声明语句 - private Statement parseLocalDeclaration() throws ParseError { - consume("KEYWORD"); // 消费 "local" - - if (match("KEYWORD", "function")) { - // 局部函数声明 - Token identifier = peek(1); // 变量名 - // 局部函数定义 - return new Statement.LocalDeclarationStatement(identifier.value, parseFunctionDefinition()); - } else { - Token identifier = consume("IDENTIFIER"); // 变量名 - - Expression initializer = null; - - if (match("OPERATOR") && peek().value.equals("=")) { - consume("OPERATOR"); // 消费 "=" - initializer = parseExpression(); // 解析初始化表达式 - } - - return new Statement.LocalDeclarationStatement(identifier.value, initializer); - } - } - - // 解析 return 语句 - private Statement.ReturnStatement parseReturnStatement() throws ParseError { - consume("KEYWORD"); // 消费 "return" - - List returnValues = new ArrayList<>(); - - // 如果有表达式 - if (!match("SYMBOL", ";")) { - // 解析一个或多个返回值 - do { - returnValues.add(parseExpression()); - - // 检查下一个符号是否为逗号,如果是则继续解析 - } while (match("SYMBOL") && peek().value.equals(",")); - } - - return new Statement.ReturnStatement(returnValues); - } - - // 解析 if 语句 - private Statement.IfStatement parseIfStatement() throws ParseError { - consume("KEYWORD"); // 消费 "if" - - Expression condition = parseExpression(); // 解析条件表达式 - consume("KEYWORD"); // 消费 "then" - - // 解析 if 部分的语句 - List ifStatements = parseBlock(); - - List elseifStatements = new ArrayList<>(); - List elseifConditions = new ArrayList<>(); - - // 解析 elseif 部分(如果有的话) - while (match("KEYWORD") && "elseif".equals(peek().value)) { - consume("KEYWORD"); // 消费 "elseif" - Expression elseifCondition = parseExpression(); // 解析 elseif 条件 - consume("KEYWORD"); // 消费 "then" - List elseifBlock = parseBlock(); // 解析 elseif 语句块 - elseifConditions.add(elseifCondition); - elseifStatements.addAll(elseifBlock); - } - - // 解析 else 部分(如果有的话) - List elseStatements = new ArrayList<>(); - if (match("KEYWORD") && "else".equals(peek().value)) { - consume("KEYWORD"); // 消费 "else" - elseStatements.addAll(parseBlock()); // 解析 else 语句块 - } - - consume("KEYWORD"); // 消费 "end" - - return new Statement.IfStatement(condition, ifStatements, elseifStatements, elseifConditions, elseStatements); - } - - private Statement parseRepeatStatement() throws ParseError { - consume("KEYWORD", "repeat"); // 消费 "repeat" - - // 解析循环体 - List body = parseBlock(); - - consume("KEYWORD", "until"); // 消费 "until" - - // 解析终止条件 - Expression condition = parseExpression(); - - return new Statement.RepeatStatement(body, condition); - } - - private Statement parseWhileStatement() throws ParseError { - consume("KEYWORD", "while"); // 消费 "while" - - // 解析条件表达式 - Expression condition = parseExpression(); - - consume("KEYWORD", "do"); // 消费 "do" - - // 解析循环体 - List body = parseBlock(); - - consume("KEYWORD", "end"); // 消费 "end" - - return new Statement.WhileStatement(condition, body); - } - - - private Statement parseForStatement() throws ParseError { - consume("KEYWORD", "for"); // 消费 "for" - - // 判断是数值型还是泛型 for 循环 - if (match("IDENTIFIER")) { - String firstVariable = consume("IDENTIFIER").value; - - // 数值型 for 循环:for var = start, end, step do - if (match("OPERATOR") && peek().value.equals("=")) { - consume("OPERATOR", "="); // 消费 "=" - Expression start = parseExpression(); // 起始值 - consume("SYMBOL", ","); // 消费 "," - Expression end = parseExpression(); // 结束值 - Expression step = null; - if (match("SYMBOL") && peek().value.equals(",")) { - consume("SYMBOL", ","); // 消费 "," - step = parseExpression(); // 步长 - } - consume("KEYWORD", "do"); // 消费 "do" - List body = parseBlock(); // 解析循环体 - consume("KEYWORD", "end"); // 消费 "end" - return new Statement.ForStatement(firstVariable, start, end, step, body); - } - - // 泛型 for 循环:for key, value in iterator do - else if (match("SYMBOL") && peek().value.equals(",")) { - consume("SYMBOL", ","); // 消费 "," - String secondVariable = consume("IDENTIFIER").value; - consume("KEYWORD", "in"); // 消费 "in" - Expression iterator = parseExpression(); // 解析迭代器 - consume("KEYWORD", "do"); // 消费 "do" - List body = parseBlock(); // 解析循环体 - consume("KEYWORD", "end"); // 消费 "end" - return new Statement.ForInStatement(firstVariable, secondVariable, iterator, body); - } - - // 支持单变量泛型 for:for key in iterator do - else if (match("KEYWORD") && peek().value.equals("in")) { - consume("KEYWORD", "in"); // 消费 "in" - Expression iterator = parseExpression(); // 解析迭代器 - consume("KEYWORD", "do"); // 消费 "do" - List body = parseBlock(); // 解析循环体 - consume("KEYWORD", "end"); // 消费 "end" - return new Statement.ForInStatement(firstVariable, null, iterator, body); - } - } - - throw new IllegalArgumentException("Unexpected token in for statement: " + peek().type); - } - - - // 解析匿名函数 - private Expression.AnonymousFunctionExpression parseAnonymousFunction() throws ParseError { - consume("KEYWORD"); // 消费 "function" - consume("SYMBOL"); // 消费 "(" - - // 解析匿名函数参数 - List parameters = new ArrayList<>(); - while (!match("SYMBOL") || !peek().value.equals(")")) { - if (match("IDENTIFIER")) { - parameters.add(consume("IDENTIFIER").value); - } - if (match("SYMBOL") && peek().value.equals(",")) { - consume("SYMBOL"); // 跳过 "," - } - } - consume("SYMBOL"); // 消费 ")" - - // 解析函数体 - List body = parseBlock(); - consume("KEYWORD"); // 消费 "end" - - return new Expression.AnonymousFunctionExpression(parameters, body); - } - - private List parseBlock() throws ParseError { - List statements = new ArrayList<>(); - - while (!match("KEYWORD") || - (!peek().value.equals("end") && - !peek().value.equals("else") && - !peek().value.equals("elseif") && - !peek().value.equals("until"))) { - statements.add(parse()); - } - - return statements; - } - - private Token consumeCurrent() { - return tokens.get(position++); - } - - // 消费token - private Token consume(String type) { - Token token = tokens.get(position++); - if (!token.type.equals(type)) { - StringBuilder context = new StringBuilder(); - for (int i = Math.max(position - 3, 0); i < Math.min(tokens.size() - 1, position + 3); i++) { - context.append(tokens.get(i).value); - context.append(" "); - } - - throw new IllegalArgumentException("Expected " + type + " but found " + token.type + " " + token.value + " at position " + position + " -> " + context); - } - return token; - } - - // 消费token - private Token consume(String type, String value) throws ParseError { - Token token = tokens.get(position++); - if (!token.type.equals(type) || !token.value.equals(value)) { - throw new ParseError("Expected " + type + " but found " + token.type + " " + token.value + " at position " + position + " -> " + context()); - } - return token; - } - - - private String context() { - StringBuilder context = new StringBuilder(); - for (int i = Math.max(position - 3, 0); i < Math.min(tokens.size() - 1, position + 3); i++) { - if (i == position) - context.append("=> "); - context.append(tokens.get(i).value); - context.append(" "); - } - return context.toString(); - } - - // 检查当前 token 是否匹配 - private boolean match(String type) { - return position < tokens.size() && tokens.get(position).type.equals(type); - } - - // 检查当前 token 和值是否匹配 - private boolean match(String type, String value) { - return match(type) && tokens.get(position).value.equals(value); - } - - // 查看下一个 token - private Token peek() { - return peek(0); - } - - // 查看当前位置的 offset 个 Token,不移动 position - private Token peek(int offset) { - int index = position + offset; - if (index >= tokens.size()) { - return null; // 如果超出范围,返回 null - } - return tokens.get(index); - } - - // 检查后续 token 是否满足指定类型和值 - private boolean lookaheadIs(String type, String value) { - return position + 1 < tokens.size() && tokens.get(position + 1).type.equals(type) && tokens.get(position + 1).value.equals(value); - } - -} diff --git a/shared/java/top/fpsmaster/modules/lua/parser/Statement.java b/shared/java/top/fpsmaster/modules/lua/parser/Statement.java deleted file mode 100644 index 6eb27887..00000000 --- a/shared/java/top/fpsmaster/modules/lua/parser/Statement.java +++ /dev/null @@ -1,231 +0,0 @@ -package top.fpsmaster.modules.lua.parser; - -import java.util.List; - -public abstract class Statement { - public static class ExpressionStatement extends Statement { - private final Expression expression; - - public ExpressionStatement(Expression expression) { - this.expression = expression; - } - - public Expression getExpression() { - return expression; - } - - @Override - public String toString() { - return "ExpressionStatement{" + - "expression=" + expression.toString() + - '}'; - } - } - - public static class AssignmentStatement extends Statement { - public String variable; - public Expression value; - - AssignmentStatement(String variable, Expression value) { - this.variable = variable; - this.value = value; - } - - @Override - public String toString() { - return "AssignmentStatement{" + - "variable='" + variable + '\'' + - ", value=" + value + - '}'; - } - } - - public static class IfStatement extends Statement { - private final Expression condition; - private final List ifStatements; - private final List elseifStatements; - private final List elseifConditions; - private final List elseStatements; - - public IfStatement(Expression condition, List ifStatements, - List elseifStatements, List elseifConditions, - List elseStatements) { - this.condition = condition; - this.ifStatements = ifStatements; - this.elseifStatements = elseifStatements; - this.elseifConditions = elseifConditions; - this.elseStatements = elseStatements; - } - - public Expression getCondition() { - return condition; - } - - public List getIfStatements() { - return ifStatements; - } - - public List getElseifStatements() { - return elseifStatements; - } - - public List getElseifConditions() { - return elseifConditions; - } - - public List getElseStatements() { - return elseStatements; - } - - @Override - public String toString() { - return "IfStatement{" + - "condition=" + condition.toString() + - "ifStatements=" + ifStatements.toString() + - "elseifStatements=" + elseifStatements.toString() + - "elseifConditions=" + elseifConditions.toString() + - "elseStatements=" + elseStatements.toString() + - "}"; - } - } - - - public static class WhileStatement extends Statement { - private final Expression condition; - private final List body; - - public WhileStatement(Expression condition, List body) { - this.condition = condition; - this.body = body; - } - - public Expression getCondition() { - return condition; - } - - public List getBody() { - return body; - } - - @Override - public String toString() { - return "WhileStatement{" + - "condition=" + condition + - ", body=" + body + - '}'; - } - } - - - public static class RepeatStatement extends Statement { - private final List body; - private final Expression condition; - - public RepeatStatement(List body, Expression condition) { - this.body = body; - this.condition = condition; - } - - public List getBody() { - return body; - } - - public Expression getCondition() { - return condition; - } - - @Override - public String toString() { - return "RepeatStatement{" + - "body=" + body + - ", condition=" + condition + - '}'; - } - } - - - public static class ForStatement extends Statement { - private final String varName; - private final Expression start; - private final Expression end; - private final Expression step; - private final List body; - - public ForStatement(String varName, Expression start, Expression end, Expression step, List body) { - this.varName = varName; - this.start = start; - this.end = end; - this.step = step; - this.body = body; - } - - @Override - public String toString() { - return "ForStatement{" + - "varName='" + varName + '\'' + - ", start=" + start + - ", end=" + end + - ", step=" + step + - ", body=" + body.toString() + - '}'; - } - } - - - public static class ForInStatement extends Statement { - private final String key; - private final String value; - private final Expression iterator; - private final List body; - - public ForInStatement(String key, String value, Expression iterator, List body) { - this.key = key; - this.value = value; - this.iterator = iterator; - this.body = body; - } - - @Override - public String toString() { - return "ForInStatement{" + - "key='" + key + '\'' + - ", value='" + value + '\'' + - ", iterator=" + iterator.toString() + - ", body=" + body.toString() + - '}'; - } - } - - - public static class LocalDeclarationStatement extends Statement { - public final String variableName; - public final Expression initializer; - - LocalDeclarationStatement(String variableName, Expression initializer) { - this.variableName = variableName; - this.initializer = initializer; - } - - @Override - public String toString() { - return "LocalDeclarationStatement{" + - "variableName='" + variableName + '\'' + - ", initializer=" + initializer + - '}'; - } - } - - public static class ReturnStatement extends Statement { - private final List returnValues; - - ReturnStatement(List returnValues) { - this.returnValues = returnValues; - } - - public List getReturnValues() { - return returnValues; - } - } - -} - diff --git a/shared/java/top/fpsmaster/modules/lua/parser/Token.java b/shared/java/top/fpsmaster/modules/lua/parser/Token.java deleted file mode 100644 index 489fe1d6..00000000 --- a/shared/java/top/fpsmaster/modules/lua/parser/Token.java +++ /dev/null @@ -1,243 +0,0 @@ -package top.fpsmaster.modules.lua.parser; - -import java.util.ArrayList; -import java.util.List; -import java.util.function.Predicate; - -class Token { - String type; //定义每个token的类型,比如: "IDENTIFIER"(标识符), "STRING"(字符串), "NUMBER"(数字), "OPERATOR"(运算符) - String value; //定义每个token的值,比如: "abc"(标识符), "hello world"(字符串), "3.14"(数字), "+"(运算符) - - Token(String type, String value) { - this.type = type; - this.value = value; - } - - @Override - public String toString() { - return type + " " + value; - } - - public boolean match(String type) { - return this.type.equals(type); - } - - public boolean match(String type, String value) { - return this.type.equals(type) && this.value.equals(value); - } -} - -class Lexer { - private final String input; - private int position; // 当前解析到的位置 - - // 构造函数,初始化输入字符串和解析位置 - Lexer(String input) { - this.input = input; - this.position = 0; - } - - // 将输入字符串解析为Token列表 - List tokenize() { - List tokens = new ArrayList<>(); - while (position < input.length()) { - char current = input.charAt(position); - if (Character.isWhitespace(current)) { // 跳过空白 - position++; - } else if (current == '-' && lookaheadIs('-')) { - // 跳过注释 - skipComment(); - } else if (Character.isLetter(current) || current == '_') { - String identifier = readWhile(c -> Character.isLetterOrDigit(c) || c == '_'); - switch (identifier) { - case "local": - tokens.add(new Token("KEYWORD", "local")); - break; - case "function": - tokens.add(new Token("KEYWORD", "function")); - break; - case "end": - tokens.add(new Token("KEYWORD", "end")); - break; - case "return": - tokens.add(new Token("KEYWORD", "return")); - break; - case "true": - tokens.add(new Token("BOOLEAN", "true")); - break; - case "false": - tokens.add(new Token("BOOLEAN", "false")); - break; - case "nil": - tokens.add(new Token("NIL", "nil")); - break; - case "if": - tokens.add(new Token("KEYWORD", "if")); - break; - case "then": - tokens.add(new Token("KEYWORD", "then")); - break; - case "elseif": - tokens.add(new Token("KEYWORD", "elseif")); - break; - case "else": - tokens.add(new Token("KEYWORD", "else")); - break; - case "until": - tokens.add(new Token("KEYWORD", "until")); - break; - case "while": - tokens.add(new Token("KEYWORD", "while")); - break; - case "for": - tokens.add(new Token("KEYWORD", "for")); - break; - case "in": - tokens.add(new Token("KEYWORD", "in")); - break; - case "do": - tokens.add(new Token("KEYWORD", "do")); - break; - case "repeat": - tokens.add(new Token("KEYWORD", "repeat")); - break; - default: - tokens.add(new Token("IDENTIFIER", identifier)); - break; - } - } else if (Character.isDigit(current)) { - String number = readWhile(t -> Character.isDigit(t) || t == '.' || t == 'e' || t == 'E' || t == '+' || t == '-'); // 读取数字,直到遇到非数字为止 - // 合法性检查 - if (number.contains(".") && number.endsWith(".")) { - throw new IllegalArgumentException("Invalid number: " + number); - } - if (number.contains("e") || number.contains("E")) { - if (number.endsWith("e") || number.endsWith("E")) { - throw new IllegalArgumentException("Invalid number: " + number); - } - String[] parts = number.split("[eE]"); - if (parts.length != 2) { - throw new IllegalArgumentException("Invalid number: " + number); - } - if (!parts[1].matches("[+-]?\\d+")) { - throw new IllegalArgumentException("Invalid number: " + number); - } - } - - - tokens.add(new Token("NUMBER", number)); - } else if (current == '"' || (current == '[' && lookaheadIs('['))) { - // 读取字符串 - tokens.add(new Token("STRING", readString())); - } else if (current == '=' && input.charAt(position + 1) == '=') { - tokens.add(new Token("OPERATOR", "==")); - position += 2; - } else if (current == '<' && input.charAt(position + 1) == '=') { - tokens.add(new Token("OPERATOR", "<=")); - position += 2; - } else if (current == '>' && input.charAt(position + 1) == '=') { - tokens.add(new Token("OPERATOR", ">=")); - position += 2; - } else if (current == '.' && input.charAt(position + 1) == '.') { - tokens.add(new Token("OPERATOR", "..")); - position += 2; - } else if (current == '+' || current == '-' || current == '*' || current == '/' || current == '%' || current == '^' || current == '#' || current == '&' || current == '|' || current == '~' || current == '>' || current == '<' || current == '=' || current == '?' || current == '!') { - tokens.add(new Token("OPERATOR", String.valueOf(current))); - position++; - } else if (".:{}(),".indexOf(current) != -1) { - tokens.add(new Token("SYMBOL", String.valueOf(current))); - position++; - } else { - throw new IllegalArgumentException("Unexpected character: " + current + position); - } - } - return tokens; - } - - private boolean lookaheadIs(char expected) { - return position + 1 < input.length() && input.charAt(position + 1) == expected; - } - - private boolean lookaheadIs(char expected, int index) { - return index < input.length() && input.charAt(index) == expected; - } - - private void skipComment() { - position += 2; // 跳过 "--" - if (lookaheadIs('[') && lookaheadIs('[', position + 1)) { - // 多行注释 - position += 3; // 跳过 "[[" - while (position < input.length() && !(lookaheadIs(']') && lookaheadIs(']', position + 1))) { - position++; - } - if (position < input.length()) { - position += 3; // 跳过 "]]" - } else { - throw new IllegalArgumentException("Unterminated multi-line comment"); - } - } else { - // 单行注释 - while (position < input.length() && input.charAt(position) != '\n') { - position++; - } - } - } - - private String readString() { - StringBuilder stringLiteral = new StringBuilder(); - char marker = input.charAt(position); - if (marker == '[') { - position++; - } - position++; // 跳过开头的双引号 - while (position < input.length()) { - char current = input.charAt(position); - if (current == '\\') { - // 处理转义字符 - position++; - if (position >= input.length()) { - throw new IllegalArgumentException("Unterminated escape sequence in string"); - } - char escaped = input.charAt(position); - switch (escaped) { - case 'n': - stringLiteral.append('\n'); - break; - case 't': - stringLiteral.append('\t'); - break; - case '"': - stringLiteral.append('"'); - break; - case '\\': - stringLiteral.append('\\'); - break; - default: - throw new IllegalArgumentException("Unknown escape sequence: \\" + escaped); - } - } else if (current == '\"' || (marker == '[' && current == ']')) { - // 结束字符串 - if (marker == '[') - position++; - position++; - break; - } else { - // 普通字符 - stringLiteral.append(current); - } - position++; - } - return stringLiteral.toString(); - } - - - // 根据条件读取字符,直到条件不满足为止,这里用了Predicate接口 - private String readWhile(Predicate condition) { - StringBuilder result = new StringBuilder(); - while (position < input.length() && condition.test(input.charAt(position))) { - result.append(input.charAt(position++)); - } - return result.toString(); - } -} - diff --git a/shared/java/top/fpsmaster/ui/devspace/DevSpace.java b/shared/java/top/fpsmaster/ui/devspace/DevSpace.java index 46e766eb..8bf83714 100644 --- a/shared/java/top/fpsmaster/ui/devspace/DevSpace.java +++ b/shared/java/top/fpsmaster/ui/devspace/DevSpace.java @@ -11,8 +11,6 @@ import top.fpsmaster.exception.FileException; import top.fpsmaster.modules.lua.LuaManager; import top.fpsmaster.modules.lua.LuaScript; -import top.fpsmaster.modules.lua.parser.Expression; -import top.fpsmaster.modules.lua.parser.Statement; import top.fpsmaster.ui.click.component.ScrollContainer; import top.fpsmaster.ui.devspace.map.expressions.*; import top.fpsmaster.ui.devspace.map.statements.*; @@ -20,6 +18,8 @@ import top.fpsmaster.utils.os.FileUtils; import top.fpsmaster.utils.render.Render2DUtils; import top.fpsmaster.utils.render.ScaledGuiScreen; +import top.skidder.parser.Expression; +import top.skidder.parser.Statement; import java.awt.*; import java.io.IOException; diff --git a/shared/java/top/fpsmaster/ui/devspace/map/expressions/AnonymousFunctionExpressionComponent.java b/shared/java/top/fpsmaster/ui/devspace/map/expressions/AnonymousFunctionExpressionComponent.java index ba89fecc..7d5a385d 100644 --- a/shared/java/top/fpsmaster/ui/devspace/map/expressions/AnonymousFunctionExpressionComponent.java +++ b/shared/java/top/fpsmaster/ui/devspace/map/expressions/AnonymousFunctionExpressionComponent.java @@ -1,9 +1,9 @@ package top.fpsmaster.ui.devspace.map.expressions; import top.fpsmaster.FPSMaster; -import top.fpsmaster.modules.lua.parser.Expression; import top.fpsmaster.ui.devspace.DevSpace; import top.fpsmaster.ui.devspace.map.statements.StatementComponent; +import top.skidder.parser.Expression; import java.util.List; diff --git a/shared/java/top/fpsmaster/ui/devspace/map/expressions/BinaryExpressionComponent.java b/shared/java/top/fpsmaster/ui/devspace/map/expressions/BinaryExpressionComponent.java index d41e42ca..d28ad0c0 100644 --- a/shared/java/top/fpsmaster/ui/devspace/map/expressions/BinaryExpressionComponent.java +++ b/shared/java/top/fpsmaster/ui/devspace/map/expressions/BinaryExpressionComponent.java @@ -1,8 +1,8 @@ package top.fpsmaster.ui.devspace.map.expressions; import top.fpsmaster.FPSMaster; -import top.fpsmaster.modules.lua.parser.Expression; import top.fpsmaster.ui.devspace.DevSpace; +import top.skidder.parser.Expression; public class BinaryExpressionComponent extends ExpressionComponent { ExpressionComponent left; diff --git a/shared/java/top/fpsmaster/ui/devspace/map/expressions/ExpressionComponent.java b/shared/java/top/fpsmaster/ui/devspace/map/expressions/ExpressionComponent.java index 3f06e5cc..f4aca90a 100644 --- a/shared/java/top/fpsmaster/ui/devspace/map/expressions/ExpressionComponent.java +++ b/shared/java/top/fpsmaster/ui/devspace/map/expressions/ExpressionComponent.java @@ -1,6 +1,7 @@ package top.fpsmaster.ui.devspace.map.expressions; -import top.fpsmaster.modules.lua.parser.Expression; + +import top.skidder.parser.Expression; public class ExpressionComponent { public Expression expression; diff --git a/shared/java/top/fpsmaster/ui/devspace/map/expressions/FunctionCallExpressionComponent.java b/shared/java/top/fpsmaster/ui/devspace/map/expressions/FunctionCallExpressionComponent.java index 616907bd..310eeac5 100644 --- a/shared/java/top/fpsmaster/ui/devspace/map/expressions/FunctionCallExpressionComponent.java +++ b/shared/java/top/fpsmaster/ui/devspace/map/expressions/FunctionCallExpressionComponent.java @@ -1,9 +1,9 @@ package top.fpsmaster.ui.devspace.map.expressions; import top.fpsmaster.FPSMaster; -import top.fpsmaster.modules.lua.parser.Expression; import top.fpsmaster.ui.devspace.DevSpace; import top.fpsmaster.utils.render.Render2DUtils; +import top.skidder.parser.Expression; import java.awt.*; import java.util.List; diff --git a/shared/java/top/fpsmaster/ui/devspace/map/expressions/FunctionDefinitionExpressionComponent.java b/shared/java/top/fpsmaster/ui/devspace/map/expressions/FunctionDefinitionExpressionComponent.java index 250115d5..2efca031 100644 --- a/shared/java/top/fpsmaster/ui/devspace/map/expressions/FunctionDefinitionExpressionComponent.java +++ b/shared/java/top/fpsmaster/ui/devspace/map/expressions/FunctionDefinitionExpressionComponent.java @@ -2,10 +2,10 @@ import net.minecraft.util.ResourceLocation; import top.fpsmaster.FPSMaster; -import top.fpsmaster.modules.lua.parser.Expression; import top.fpsmaster.ui.devspace.DevSpace; import top.fpsmaster.ui.devspace.map.statements.StatementComponent; import top.fpsmaster.utils.render.Render2DUtils; +import top.skidder.parser.Expression; import java.awt.*; import java.util.List; diff --git a/shared/java/top/fpsmaster/ui/devspace/map/expressions/LiteralExpressionComponent.java b/shared/java/top/fpsmaster/ui/devspace/map/expressions/LiteralExpressionComponent.java index 0ae8c684..60118a67 100644 --- a/shared/java/top/fpsmaster/ui/devspace/map/expressions/LiteralExpressionComponent.java +++ b/shared/java/top/fpsmaster/ui/devspace/map/expressions/LiteralExpressionComponent.java @@ -1,8 +1,8 @@ package top.fpsmaster.ui.devspace.map.expressions; import top.fpsmaster.FPSMaster; -import top.fpsmaster.modules.lua.parser.Expression; import top.fpsmaster.utils.render.Render2DUtils; +import top.skidder.parser.Expression; import java.awt.*; diff --git a/shared/java/top/fpsmaster/ui/devspace/map/expressions/MemberAccessExpressionComponent.java b/shared/java/top/fpsmaster/ui/devspace/map/expressions/MemberAccessExpressionComponent.java index ecf0b902..7a431d83 100644 --- a/shared/java/top/fpsmaster/ui/devspace/map/expressions/MemberAccessExpressionComponent.java +++ b/shared/java/top/fpsmaster/ui/devspace/map/expressions/MemberAccessExpressionComponent.java @@ -1,8 +1,8 @@ package top.fpsmaster.ui.devspace.map.expressions; import top.fpsmaster.FPSMaster; -import top.fpsmaster.modules.lua.parser.Expression; import top.fpsmaster.ui.devspace.DevSpace; +import top.skidder.parser.Expression; public class MemberAccessExpressionComponent extends ExpressionComponent { ExpressionComponent object; diff --git a/shared/java/top/fpsmaster/ui/devspace/map/expressions/MethodCallExpressionComponent.java b/shared/java/top/fpsmaster/ui/devspace/map/expressions/MethodCallExpressionComponent.java index 4bab6b54..d5371bce 100644 --- a/shared/java/top/fpsmaster/ui/devspace/map/expressions/MethodCallExpressionComponent.java +++ b/shared/java/top/fpsmaster/ui/devspace/map/expressions/MethodCallExpressionComponent.java @@ -1,8 +1,8 @@ package top.fpsmaster.ui.devspace.map.expressions; import top.fpsmaster.FPSMaster; -import top.fpsmaster.modules.lua.parser.Expression; import top.fpsmaster.ui.devspace.DevSpace; +import top.skidder.parser.Expression; import java.awt.*; import java.util.List; diff --git a/shared/java/top/fpsmaster/ui/devspace/map/expressions/NilLiteralExpressionComponent.java b/shared/java/top/fpsmaster/ui/devspace/map/expressions/NilLiteralExpressionComponent.java index e22629c6..3106665f 100644 --- a/shared/java/top/fpsmaster/ui/devspace/map/expressions/NilLiteralExpressionComponent.java +++ b/shared/java/top/fpsmaster/ui/devspace/map/expressions/NilLiteralExpressionComponent.java @@ -1,7 +1,7 @@ package top.fpsmaster.ui.devspace.map.expressions; import top.fpsmaster.FPSMaster; -import top.fpsmaster.modules.lua.parser.Expression; +import top.skidder.parser.Expression; public class NilLiteralExpressionComponent extends ExpressionComponent{ public NilLiteralExpressionComponent(Expression expression) { diff --git a/shared/java/top/fpsmaster/ui/devspace/map/expressions/TableExpressionComponent.java b/shared/java/top/fpsmaster/ui/devspace/map/expressions/TableExpressionComponent.java index 84feb0ea..730799d3 100644 --- a/shared/java/top/fpsmaster/ui/devspace/map/expressions/TableExpressionComponent.java +++ b/shared/java/top/fpsmaster/ui/devspace/map/expressions/TableExpressionComponent.java @@ -1,8 +1,8 @@ package top.fpsmaster.ui.devspace.map.expressions; import top.fpsmaster.FPSMaster; -import top.fpsmaster.modules.lua.parser.Expression; import top.fpsmaster.ui.devspace.DevSpace; +import top.skidder.parser.Expression; import java.util.HashMap; import java.util.List; diff --git a/shared/java/top/fpsmaster/ui/devspace/map/expressions/UnaryExpressionComponent.java b/shared/java/top/fpsmaster/ui/devspace/map/expressions/UnaryExpressionComponent.java index 365d1b60..192ad446 100644 --- a/shared/java/top/fpsmaster/ui/devspace/map/expressions/UnaryExpressionComponent.java +++ b/shared/java/top/fpsmaster/ui/devspace/map/expressions/UnaryExpressionComponent.java @@ -1,8 +1,8 @@ package top.fpsmaster.ui.devspace.map.expressions; import top.fpsmaster.FPSMaster; -import top.fpsmaster.modules.lua.parser.Expression; import top.fpsmaster.ui.devspace.DevSpace; +import top.skidder.parser.Expression; public class UnaryExpressionComponent extends ExpressionComponent { diff --git a/shared/java/top/fpsmaster/ui/devspace/map/expressions/VariableExpressionComponent.java b/shared/java/top/fpsmaster/ui/devspace/map/expressions/VariableExpressionComponent.java index 5d8a4795..88e62c4d 100644 --- a/shared/java/top/fpsmaster/ui/devspace/map/expressions/VariableExpressionComponent.java +++ b/shared/java/top/fpsmaster/ui/devspace/map/expressions/VariableExpressionComponent.java @@ -1,7 +1,7 @@ package top.fpsmaster.ui.devspace.map.expressions; import top.fpsmaster.FPSMaster; -import top.fpsmaster.modules.lua.parser.Expression; +import top.skidder.parser.Expression; public class VariableExpressionComponent extends ExpressionComponent { String name; diff --git a/shared/java/top/fpsmaster/ui/devspace/map/statements/AssignmentStatementComponent.java b/shared/java/top/fpsmaster/ui/devspace/map/statements/AssignmentStatementComponent.java index 85f1636e..7f88a5ca 100644 --- a/shared/java/top/fpsmaster/ui/devspace/map/statements/AssignmentStatementComponent.java +++ b/shared/java/top/fpsmaster/ui/devspace/map/statements/AssignmentStatementComponent.java @@ -1,9 +1,9 @@ package top.fpsmaster.ui.devspace.map.statements; import top.fpsmaster.FPSMaster; -import top.fpsmaster.modules.lua.parser.Statement; import top.fpsmaster.ui.devspace.DevSpace; import top.fpsmaster.ui.devspace.map.expressions.ExpressionComponent; +import top.skidder.parser.Statement; public class AssignmentStatementComponent extends StatementComponent { String variable; diff --git a/shared/java/top/fpsmaster/ui/devspace/map/statements/ExpressionStatementComponent.java b/shared/java/top/fpsmaster/ui/devspace/map/statements/ExpressionStatementComponent.java index 9f328311..ee36e8e3 100644 --- a/shared/java/top/fpsmaster/ui/devspace/map/statements/ExpressionStatementComponent.java +++ b/shared/java/top/fpsmaster/ui/devspace/map/statements/ExpressionStatementComponent.java @@ -1,8 +1,8 @@ package top.fpsmaster.ui.devspace.map.statements; -import top.fpsmaster.modules.lua.parser.Statement; import top.fpsmaster.ui.devspace.DevSpace; import top.fpsmaster.ui.devspace.map.expressions.ExpressionComponent; +import top.skidder.parser.Statement; public class ExpressionStatementComponent extends StatementComponent { ExpressionComponent expr; diff --git a/shared/java/top/fpsmaster/ui/devspace/map/statements/IfStatementComponent.java b/shared/java/top/fpsmaster/ui/devspace/map/statements/IfStatementComponent.java index 8486a2fd..5e200c50 100644 --- a/shared/java/top/fpsmaster/ui/devspace/map/statements/IfStatementComponent.java +++ b/shared/java/top/fpsmaster/ui/devspace/map/statements/IfStatementComponent.java @@ -1,9 +1,9 @@ package top.fpsmaster.ui.devspace.map.statements; import top.fpsmaster.FPSMaster; -import top.fpsmaster.modules.lua.parser.Statement; import top.fpsmaster.ui.devspace.DevSpace; import top.fpsmaster.ui.devspace.map.expressions.ExpressionComponent; +import top.skidder.parser.Statement; import java.util.List; diff --git a/shared/java/top/fpsmaster/ui/devspace/map/statements/LocalDeclarationStatementComponent.java b/shared/java/top/fpsmaster/ui/devspace/map/statements/LocalDeclarationStatementComponent.java index 5ccecaa1..3b0784c2 100644 --- a/shared/java/top/fpsmaster/ui/devspace/map/statements/LocalDeclarationStatementComponent.java +++ b/shared/java/top/fpsmaster/ui/devspace/map/statements/LocalDeclarationStatementComponent.java @@ -1,10 +1,10 @@ package top.fpsmaster.ui.devspace.map.statements; import top.fpsmaster.FPSMaster; -import top.fpsmaster.modules.lua.parser.Statement; import top.fpsmaster.ui.devspace.DevSpace; import top.fpsmaster.ui.devspace.map.expressions.ExpressionComponent; import top.fpsmaster.utils.render.Render2DUtils; +import top.skidder.parser.Statement; import java.awt.*; diff --git a/shared/java/top/fpsmaster/ui/devspace/map/statements/ReturnStatementComponent.java b/shared/java/top/fpsmaster/ui/devspace/map/statements/ReturnStatementComponent.java index a63c32ed..24329a90 100644 --- a/shared/java/top/fpsmaster/ui/devspace/map/statements/ReturnStatementComponent.java +++ b/shared/java/top/fpsmaster/ui/devspace/map/statements/ReturnStatementComponent.java @@ -1,9 +1,9 @@ package top.fpsmaster.ui.devspace.map.statements; import top.fpsmaster.FPSMaster; -import top.fpsmaster.modules.lua.parser.Statement; import top.fpsmaster.ui.devspace.DevSpace; import top.fpsmaster.ui.devspace.map.expressions.ExpressionComponent; +import top.skidder.parser.Statement; import java.util.List; diff --git a/shared/java/top/fpsmaster/ui/devspace/map/statements/StatementComponent.java b/shared/java/top/fpsmaster/ui/devspace/map/statements/StatementComponent.java index 3f4cf3f9..caae7fb8 100644 --- a/shared/java/top/fpsmaster/ui/devspace/map/statements/StatementComponent.java +++ b/shared/java/top/fpsmaster/ui/devspace/map/statements/StatementComponent.java @@ -1,6 +1,6 @@ package top.fpsmaster.ui.devspace.map.statements; -import top.fpsmaster.modules.lua.parser.Statement; +import top.skidder.parser.Statement; public class StatementComponent { public Statement statement; diff --git a/shared/java/top/fpsmaster/ui/mc/GuiMultiplayer.java b/shared/java/top/fpsmaster/ui/mc/GuiMultiplayer.java index e1946220..9b141b81 100644 --- a/shared/java/top/fpsmaster/ui/mc/GuiMultiplayer.java +++ b/shared/java/top/fpsmaster/ui/mc/GuiMultiplayer.java @@ -19,7 +19,7 @@ import org.lwjgl.opengl.GL11; import top.fpsmaster.FPSMaster; import top.fpsmaster.font.impl.UFontRenderer; -import top.fpsmaster.modules.client.AsyncTask; +import top.fpsmaster.modules.client.ClientThreadPool; import top.fpsmaster.ui.click.component.ScrollContainer; import top.fpsmaster.ui.common.GuiButton; import top.fpsmaster.ui.screens.mainmenu.MainMenu; @@ -100,8 +100,8 @@ public void initGui() { serverListDisplay.clear(); serverListDisplay.addAll(serverListInternet); if (serverListRecommended.isEmpty()) { - AsyncTask asyncTask = new AsyncTask(100); - asyncTask.runnable(() -> { + ClientThreadPool clientThreadPool = new ClientThreadPool(100); + clientThreadPool.runnable(() -> { String s = HttpRequest.get("https://service.fpsmaster.top/api/client/servers"); JsonObject jsonObject = gson.fromJson(s, JsonObject.class); jsonObject.get("data").getAsJsonArray().forEach(e -> { diff --git a/v1.8.9/build.gradle.kts b/v1.8.9/build.gradle.kts index e82246af..7d42bcba 100644 --- a/v1.8.9/build.gradle.kts +++ b/v1.8.9/build.gradle.kts @@ -117,7 +117,7 @@ dependencies { implementation("javazoom:jlayer:1.0.1") // https://mvnrepository.com/artifact/net.sourceforge.jtransforms/jtransforms implementation("net.sourceforge.jtransforms:jtransforms:2.4.0") - + implementation("com.github.FPSMasterTeam:JLuaParser:master-SNAPSHOT") } From 0698a8426cc88bf1d3c5a7ccb17926d0f03e77af Mon Sep 17 00:00:00 2001 From: SuperSkidder Date: Wed, 16 Jul 2025 19:01:13 +0800 Subject: [PATCH 088/193] feat: custom titles and other adjust --- shared/java/top/fpsmaster/FPSMaster.java | 4 +- ...obalSubmitter.java => GlobalListener.java} | 30 +++++++++++- .../impl/interfaces/CustomTitles.java | 47 +++++++++++++++++++ .../features/manager/ModuleManager.java | 1 + .../assets/minecraft/client/lang/en_us.lang | 6 +++ .../assets/minecraft/client/lang/zh_cn.lang | 6 +++ .../fpsmaster/forge/mixin/MixinGuiIngame.java | 6 +++ .../forge/mixin/MixinGuiIngameForge.java | 14 ++++++ 8 files changed, 111 insertions(+), 3 deletions(-) rename shared/java/top/fpsmaster/features/{GlobalSubmitter.java => GlobalListener.java} (65%) create mode 100644 shared/java/top/fpsmaster/features/impl/interfaces/CustomTitles.java diff --git a/shared/java/top/fpsmaster/FPSMaster.java b/shared/java/top/fpsmaster/FPSMaster.java index 44afcae2..188bea09 100644 --- a/shared/java/top/fpsmaster/FPSMaster.java +++ b/shared/java/top/fpsmaster/FPSMaster.java @@ -2,7 +2,7 @@ import top.fpsmaster.exception.ExceptionHandler; import top.fpsmaster.exception.FileException; -import top.fpsmaster.features.GlobalSubmitter; +import top.fpsmaster.features.GlobalListener; import top.fpsmaster.features.command.CommandManager; import top.fpsmaster.features.manager.ModuleManager; import top.fpsmaster.font.FontManager; @@ -50,7 +50,7 @@ public class FPSMaster { public static OOBEScreen oobeScreen = new OOBEScreen(); public static AccountManager accountManager = new AccountManager(); public static ClientUsersManager clientUsersManager = new ClientUsersManager(); - public static GlobalSubmitter submitter = new GlobalSubmitter(); + public static GlobalListener submitter = new GlobalListener(); public static CommandManager commandManager = new CommandManager(); public static ComponentsManager componentsManager = new ComponentsManager(); public static LuaManager luaManager = new LuaManager(); diff --git a/shared/java/top/fpsmaster/features/GlobalSubmitter.java b/shared/java/top/fpsmaster/features/GlobalListener.java similarity index 65% rename from shared/java/top/fpsmaster/features/GlobalSubmitter.java rename to shared/java/top/fpsmaster/features/GlobalListener.java index 7943ef91..6a2cb297 100644 --- a/shared/java/top/fpsmaster/features/GlobalSubmitter.java +++ b/shared/java/top/fpsmaster/features/GlobalListener.java @@ -19,7 +19,7 @@ import java.net.URISyntaxException; -public class GlobalSubmitter { +public class GlobalListener { MathTimer musicSwitchTimer = new MathTimer(); @@ -41,9 +41,21 @@ public void onChatSend(EventSendChatMessage e) { String msg = e.msg; } + + PlayerInformation playerInformation = null; + + @Subscribe public void onTick(EventTick e) throws URISyntaxException { if (musicSwitchTimer.delay(500)) { +// if (playerInformation == null) { +// playerInformation = new PlayerInformation(ProviderManager.mcProvider.getPlayer().getName(), ProviderManager.mcProvider.getPlayer().getUniqueID().toString(), ProviderManager.mcProvider.getServerAddress(), "", AccountManager.skin); +// FPSMaster.INSTANCE.wsClient.sendInformation(AccountManager.skin, "", ProviderManager.mcProvider.getPlayer().getName(), ProviderManager.mcProvider.getServerAddress()); +// } else if (!playerInformation.serverAddress.equals(ProviderManager.mcProvider.getServerAddress()) || !playerInformation.name.equals(ProviderManager.mcProvider.getPlayer().getName()) || !playerInformation.skin.equals(AccountManager.skin) || !playerInformation.uuid.equals(ProviderManager.mcProvider.getPlayer().getUniqueID().toString())) { +// playerInformation = new PlayerInformation(ProviderManager.mcProvider.getPlayer().getName(), ProviderManager.mcProvider.getPlayer().getUniqueID().toString(), ProviderManager.mcProvider.getServerAddress(), "", AccountManager.skin); +// FPSMaster.INSTANCE.wsClient.sendInformation(AccountManager.skin, "", ProviderManager.mcProvider.getPlayer().getName(), ProviderManager.mcProvider.getServerAddress()); +// } + FPSMaster.async.runnable(() -> { if (MusicPlayer.isPlaying && MusicPlayer.getPlayProgress() > 0.999) { MusicPlayer.curPlayProgress = 0f; @@ -87,4 +99,20 @@ public void onRender(EventRender2D e) { FPSMaster.componentsManager.draw((int) mouseX, (int) mouseY); NotificationManager.drawNotifications(); } + + class PlayerInformation{ + String name; + String uuid; + String serverAddress; + String cosmetics; + String skin; + + public PlayerInformation(String name, String uuid, String serverAddress, String cosmetics, String skin) { + this.name = name; + this.uuid = uuid; + this.serverAddress = serverAddress; + this.cosmetics = cosmetics; + this.skin = skin; + } + } } diff --git a/shared/java/top/fpsmaster/features/impl/interfaces/CustomTitles.java b/shared/java/top/fpsmaster/features/impl/interfaces/CustomTitles.java new file mode 100644 index 00000000..bafb41aa --- /dev/null +++ b/shared/java/top/fpsmaster/features/impl/interfaces/CustomTitles.java @@ -0,0 +1,47 @@ +package top.fpsmaster.features.impl.interfaces; + +import top.fpsmaster.features.manager.Category; +import top.fpsmaster.features.manager.Module; +import top.fpsmaster.features.settings.impl.NumberSetting; + +public class CustomTitles extends Module { + + static NumberSetting x = new NumberSetting("x", 0, -500, 500, 1); + static NumberSetting y = new NumberSetting("y", 0, -500, 500, 1); + static NumberSetting scale = new NumberSetting("scale", 1, 0, 3, 0.02); + + static boolean using; + + public CustomTitles() { + super("CustomTitles", Category.Interface); + addSettings(x, y, scale); + } + + @Override + public void onEnable() { + super.onEnable(); + using = true; + } + + @Override + public void onDisable() { + super.onDisable(); + using = false; + } + + public static int getX() { + if (!using) + return 0; + return x.getValue().intValue(); + } + public static int getY() { + if (!using) + return 0; + return y.getValue().intValue(); + } + public static float getScale() { + if (!using) + return 1; + return scale.getValue().floatValue(); + } +} diff --git a/shared/java/top/fpsmaster/features/manager/ModuleManager.java b/shared/java/top/fpsmaster/features/manager/ModuleManager.java index 31821327..01d8cf8a 100644 --- a/shared/java/top/fpsmaster/features/manager/ModuleManager.java +++ b/shared/java/top/fpsmaster/features/manager/ModuleManager.java @@ -100,6 +100,7 @@ public void init() { modules.add(new LevelTag()); modules.add(new Keystrokes()); modules.add(new Crosshair()); + modules.add(new CustomTitles()); modules.add(new CustomFOV()); modules.add(new InventoryDisplay()); modules.add(new PlayerDisplay()); diff --git a/shared/resources/assets/minecraft/client/lang/en_us.lang b/shared/resources/assets/minecraft/client/lang/en_us.lang index e7ead5dc..584acc83 100644 --- a/shared/resources/assets/minecraft/client/lang/en_us.lang +++ b/shared/resources/assets/minecraft/client/lang/en_us.lang @@ -472,6 +472,12 @@ directiondisplay.desc=Display a compass damageindicator=Damage Indicator damageindicator.desc=Show damage numbers on hit +customtitles=Custom Titles +customtitles.desc=Change the position of the title +customtitles.x=xOffset +customtitles.y=yOffset +customtitles.scale=Scale + # Categories category.optimize=Performance category.render=Visual diff --git a/shared/resources/assets/minecraft/client/lang/zh_cn.lang b/shared/resources/assets/minecraft/client/lang/zh_cn.lang index 360b5fb4..c15bef0e 100644 --- a/shared/resources/assets/minecraft/client/lang/zh_cn.lang +++ b/shared/resources/assets/minecraft/client/lang/zh_cn.lang @@ -478,6 +478,12 @@ directiondisplay.desc=显示一个指南针 damageindicator=伤害指示器 damageindicator.desc=在生物受到伤害时显示伤害数字 +customtitles=自定义标题 +customtitles.desc=修改屏幕中间的标题文字的位置 +customtitles.x=横坐标偏移 +customtitles.y=纵坐标偏移 +customtitles.scale=缩放 + # 类别 category.optimize=优化 category.render=视觉 diff --git a/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinGuiIngame.java b/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinGuiIngame.java index 5aec71f6..70cc1958 100644 --- a/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinGuiIngame.java +++ b/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinGuiIngame.java @@ -1,15 +1,19 @@ package top.fpsmaster.forge.mixin; +import net.minecraft.client.gui.FontRenderer; import net.minecraft.client.gui.GuiIngame; import net.minecraft.client.gui.ScaledResolution; +import net.minecraft.client.renderer.GlStateManager; import net.minecraft.scoreboard.ScoreObjective; 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.Redirect; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; import top.fpsmaster.event.EventDispatcher; import top.fpsmaster.event.events.EventRender2D; +import top.fpsmaster.features.impl.interfaces.CustomTitles; import top.fpsmaster.features.impl.interfaces.Scoreboard; import top.fpsmaster.features.impl.render.Crosshair; @@ -31,4 +35,6 @@ public void scoreboard(ScoreObjective objective, ScaledResolution scaledRes, Cal if (Scoreboard.using) ci.cancel(); } + + } diff --git a/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinGuiIngameForge.java b/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinGuiIngameForge.java index cce12bf8..5396e601 100644 --- a/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinGuiIngameForge.java +++ b/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinGuiIngameForge.java @@ -1,12 +1,15 @@ package top.fpsmaster.forge.mixin; +import net.minecraft.client.renderer.GlStateManager; import net.minecraftforge.client.GuiIngameForge; 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.Redirect; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import top.fpsmaster.event.EventDispatcher; import top.fpsmaster.event.events.EventMotionBlur; +import top.fpsmaster.features.impl.interfaces.CustomTitles; @Mixin(GuiIngameForge.class) public class MixinGuiIngameForge { @@ -14,4 +17,15 @@ public class MixinGuiIngameForge { public void motionblur(float partialTicks, CallbackInfo ci){ EventDispatcher.dispatchEvent(new EventMotionBlur()); } + + @Redirect(method = "renderTitle", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/GlStateManager;translate(FFF)V")) + public void drawString(float x, float y, float z) { + GlStateManager.translate(x + CustomTitles.getX(), y + CustomTitles.getY(), z); + } + + @Redirect(method = "renderTitle", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/GlStateManager;scale(FFF)V")) + public void scale(float x, float y, float z) { + float scale = CustomTitles.getScale(); + GlStateManager.scale(x * scale, y * scale, z * scale); + } } From 2ffeaa727d8cc175b335398ab102e762a815f1e5 Mon Sep 17 00:00:00 2001 From: SuperSkidder Date: Wed, 16 Jul 2025 19:10:14 +0800 Subject: [PATCH 089/193] fix: musicplayer searchbox --- .../fpsmaster/ui/click/music/MusicPanel.java | 26 ++++++++++--------- .../top/fpsmaster/ui/common/TextField.java | 12 ++++++++- 2 files changed, 25 insertions(+), 13 deletions(-) diff --git a/shared/java/top/fpsmaster/ui/click/music/MusicPanel.java b/shared/java/top/fpsmaster/ui/click/music/MusicPanel.java index 3f04c9ed..dd9fc6b5 100644 --- a/shared/java/top/fpsmaster/ui/click/music/MusicPanel.java +++ b/shared/java/top/fpsmaster/ui/click/music/MusicPanel.java @@ -17,6 +17,7 @@ import top.fpsmaster.modules.music.netease.NeteaseApi; import top.fpsmaster.modules.music.netease.deserialize.MusicWrapper; import top.fpsmaster.ui.click.component.ScrollContainer; +import top.fpsmaster.ui.common.TextField; import top.fpsmaster.utils.os.FileUtils; import top.fpsmaster.utils.render.Render2DUtils; @@ -33,10 +34,11 @@ public class MusicPanel { private static Thread searchThread = null; private static float playProgress = 0f; - private static final SearchBox inputBox = new SearchBox(FPSMaster.i18n.get("music.search"), () -> { - searchThread = new Thread(MusicPanel::run); - searchThread.start(); - }); +// private static final SearchBox inputBox = new SearchBox(FPSMaster.i18n.get("music.search"), () -> { +// searchThread = new Thread(MusicPanel::run); +// searchThread.start(); +// }); + private static final TextField inputBox = new TextField(FPSMaster.fontManager.s16, FPSMaster.i18n.get("music.search"), new Color(40,40,40, 180).getRGB(), -1, 100); private static final String[] pages = {"music.name", "music.list", "music.daily"}; private static int curSearch = 0; @@ -150,7 +152,7 @@ public static void mouseClicked(int mouseX, int mouseY, int btn) { } public static void keyTyped(char c, int keyCode) { - inputBox.keyTyped(c, keyCode); + inputBox.textboxKeyTyped(c, keyCode); } public static void draw(float x, float y, float width, float height, int mouseX, int mouseY, int scaleFactor) { @@ -237,7 +239,7 @@ public static void draw(float x, float y, float width, float height, int mouseX, GL11.glDisable(GL11.GL_SCISSOR_TEST); // 搜索 - inputBox.render(x + 5, y + 6, 80f, 16f, mouseX, mouseY); + inputBox.drawTextBox(x + 5, y + 8, 80f, 16f); // 分页 int xOffset = 0; @@ -245,14 +247,14 @@ public static void draw(float x, float y, float width, float height, int mouseX, for (String page : pages) { pagesWidth += FPSMaster.fontManager.s16.getStringWidth(FPSMaster.i18n.get(page)) + 10; } - Render2DUtils.drawOptimizedRoundedRect(x + 90, y + 6, pagesWidth, 16f, new Color(50, 50, 50,100).getRGB()); + Render2DUtils.drawOptimizedRoundedRect(x + 90, y + 8, pagesWidth, 16f, new Color(50, 50, 50,100).getRGB()); for (String page : pages) { int stringWidth = FPSMaster.fontManager.s16.getStringWidth(FPSMaster.i18n.get(page)); if (page.equals(pages[curSearch])) { - Render2DUtils.drawOptimizedRoundedRect(x + 90 + xOffset, y + 6, stringWidth + 10, 16f, -1); - FPSMaster.fontManager.s16.drawString(FPSMaster.i18n.get(page), x + 95 + xOffset, y + 10, new Color(50, 50, 50).getRGB()); + Render2DUtils.drawOptimizedRoundedRect(x + 90 + xOffset, y + 8, stringWidth + 10, 16f, -1); + FPSMaster.fontManager.s16.drawString(FPSMaster.i18n.get(page), x + 95 + xOffset, y + 12, new Color(50, 50, 50).getRGB()); } else { - FPSMaster.fontManager.s16.drawString(FPSMaster.i18n.get(page), x + 95 + xOffset, y + 10, -1); + FPSMaster.fontManager.s16.drawString(FPSMaster.i18n.get(page), x + 95 + xOffset, y + 12, -1); } xOffset += stringWidth + 10; } @@ -416,8 +418,8 @@ private static void setMusicList() { } private static void run() { - if (!inputBox.getContent().isEmpty()) { - searchList = curSearch == 0 ? MusicWrapper.searchSongs(inputBox.getContent()) : MusicWrapper.searchList(inputBox.getContent()); + if (!inputBox.getText().isEmpty()) { + searchList = curSearch == 0 ? MusicWrapper.searchSongs(inputBox.getText()) : MusicWrapper.searchList(inputBox.getText()); displayList = searchList; MusicPlayer.playList.pause(); setMusicList(); diff --git a/shared/java/top/fpsmaster/ui/common/TextField.java b/shared/java/top/fpsmaster/ui/common/TextField.java index be7c6008..768764d6 100644 --- a/shared/java/top/fpsmaster/ui/common/TextField.java +++ b/shared/java/top/fpsmaster/ui/common/TextField.java @@ -67,8 +67,14 @@ public class TextField extends Gui { public int backGroundColor; public int fontColor; public String placeHolder; + private Runnable onEnter; + public TextField(UFontRenderer fontrendererObj, String placeHolder, int color, int fontColor, int maxLength, Runnable onEnter) { + this(fontrendererObj, placeHolder, color, fontColor, maxLength); + this.onEnter = onEnter; + } + public TextField(UFontRenderer fontrendererObj, String placeHolder, int color, int fontColor, int maxLength) { this.backGroundColor = color; this.fontColor = fontColor; @@ -384,7 +390,11 @@ public boolean textboxKeyTyped(char p_146201_1_, int p_146201_2_) { } return true; - + case 28: + if (onEnter != null) { + onEnter.run(); + } + return true; default: if (ChatAllowedCharacters.isAllowedCharacter(p_146201_1_)) { if (this.isEnabled) { From eab29f90ff1c4b7f20513cc5f18ccb9e35edf52d Mon Sep 17 00:00:00 2001 From: SuperSkidder Date: Wed, 16 Jul 2025 19:21:22 +0800 Subject: [PATCH 090/193] fix: some crash bug(simply remove because we dont use this temporarily) --- .../fpsmaster/ui/click/music/SearchBox.java | 425 ------------------ .../src/main/resources/mixins.fpsmaster.json | 1 - 2 files changed, 426 deletions(-) delete mode 100644 shared/java/top/fpsmaster/ui/click/music/SearchBox.java diff --git a/shared/java/top/fpsmaster/ui/click/music/SearchBox.java b/shared/java/top/fpsmaster/ui/click/music/SearchBox.java deleted file mode 100644 index 5731f071..00000000 --- a/shared/java/top/fpsmaster/ui/click/music/SearchBox.java +++ /dev/null @@ -1,425 +0,0 @@ -package top.fpsmaster.ui.click.music; - -import com.google.common.base.Predicate; -import com.google.common.base.Predicates; -import net.minecraft.client.gui.Gui; -import net.minecraft.client.gui.GuiScreen; -import net.minecraft.util.ChatAllowedCharacters; -import top.fpsmaster.FPSMaster; -import top.fpsmaster.font.impl.UFontRenderer; -import top.fpsmaster.utils.math.animation.ColorAnimation; -import top.fpsmaster.utils.render.Render2DUtils; - -import java.awt.*; - -public class SearchBox extends Gui { - private final UFontRenderer font; - - private float width; - private float height; - private float xPosition; - private float yPosition; - - private String text = ""; - private final int maxStringLength = 1000; - private int cursorCounter; - private final boolean enableBackgroundDrawing = true; - private boolean canLoseFocus = true; - private boolean isFocused; - private boolean isEnabled = true; - private final int lineScrollOffset = 0; - private int cursorPosition = 0; - private int selectionEnd = 0; - private final Color enabledColor; - private final Color disabledColor; - - private final Predicate validator = Predicates.alwaysTrue(); - private String placeholder = ""; - private final ColorAnimation btnColor = new ColorAnimation(); - - private boolean visible = true; - private Runnable runnable; - - public SearchBox(String placeholder, Color enable, Color disable, Color focus, Color hover, UFontRenderer fontrendererObj) { - this.placeholder = placeholder; - this.enabledColor = enable; - this.disabledColor = disable; - this.font = fontrendererObj; - } - - public SearchBox(String placeholder, UFontRenderer fontrendererObj, Runnable runnable) { - this.font = fontrendererObj; - this.runnable = runnable; - this.placeholder = placeholder; - this.enabledColor = new Color(58, 58, 58); - this.disabledColor = new Color(30, 30, 30); - } - - public SearchBox(String placeholder) { - this.font = FPSMaster.fontManager.s18; - this.placeholder = placeholder; - this.enabledColor = new Color(58, 58, 58); - this.disabledColor = new Color(30, 30, 30); - } - - public SearchBox(String s, Runnable runnable) { - this.font = FPSMaster.fontManager.s18; - this.placeholder = s; - this.runnable = runnable; - this.enabledColor = new Color(58, 58, 58); - this.disabledColor = new Color(30, 30, 30); - } - - public void updateCursorCounter() { - ++this.cursorCounter; - } - - public String getContent() { - return this.text; - } - - public void setContent(String content) { - this.text = content; - this.setCursorPositionEnd(); - } - - private String getSelectedText() { - int i = Math.min(cursorPosition, selectionEnd); - int j = Math.max(cursorPosition, selectionEnd); - return text.substring(i, j); - } - - private void writeText(String textToWrite) { - String s = ""; - String s1 = ChatAllowedCharacters.filterAllowedCharacters(textToWrite); - int i = Math.min(cursorPosition, selectionEnd); - int j = Math.max(cursorPosition, selectionEnd); - int k = this.maxStringLength - text.length() - (i - j); - - if (!text.isEmpty()) { - s += text.substring(0, i); - } - - int l; - if (k < s1.length()) { - s += s1.substring(0, k); - l = k; - } else { - s += s1; - l = s1.length(); - } - - if (!text.isEmpty() && j < text.length()) { - s += text.substring(j); - } - - if (validator.apply(s)) { - this.text = s; - this.moveCursorBy(i - this.selectionEnd + l); - } - } - - private void deleteWords(int num) { - if (!text.isEmpty()) { - if (this.selectionEnd != this.cursorPosition) { - this.writeText(""); - } else { - this.deleteFromCursor(this.getNthWordFromCursor(num) - this.cursorPosition); - } - } - } - - private void deleteFromCursor(int num) { - if (!text.isEmpty()) { - if (this.selectionEnd != this.cursorPosition) { - this.writeText(""); - } else { - boolean flag = num < 0; - int i = flag ? this.cursorPosition + num : this.cursorPosition; - int j = flag ? this.cursorPosition : this.cursorPosition + num; - String s = ""; - - if (i >= 0) { - s = text.substring(0, i); - } - - if (j < text.length()) { - s += text.substring(j); - } - - if (validator.apply(s)) { - this.text = s; - - if (flag) { - this.moveCursorBy(num); - } - } - } - } - } - - private int getNthWordFromCursor(int numWords) { - return this.getNthWordFromPos(numWords, this.cursorPosition); - } - - private int getNthWordFromPos(int n, int pos) { - return this.getNthWordFromPosWS(n, pos, true); - } - - private int getNthWordFromPosWS(int n, int pos, boolean skipWs) { - int i = pos; - boolean flag = n < 0; - int j = Math.abs(n); - - for (int k = 0; k < j; k++) { - if (!flag) { - int l = text.length(); - i = text.indexOf(' ', i); - - if (i == -1) { - i = l; - } else { - while (skipWs && i < l && text.charAt(i) == ' ') { - ++i; - } - } - } else { - while (skipWs && i > 0 && text.charAt(i - 1) == ' ') { - --i; - } - - while (i > 0 && text.charAt(i - 1) != ' ') { - --i; - } - } - } - - return i; - } - - private void moveCursorBy(int num) { - this.cursorPosition = this.selectionEnd + num; - } - - private void setCursorPositionZero() { - this.cursorPosition = 0; - } - - private void setCursorPositionEnd() { - this.cursorPosition = text.length(); - } - - public boolean keyTyped(char typedChar, int keyCode) { - if (!this.isFocused) { - return false; - } else if (GuiScreen.isKeyComboCtrlA(keyCode)) { - this.setCursorPositionEnd(); - this.setSelectionPos(0); - return true; - } else if (GuiScreen.isKeyComboCtrlC(keyCode)) { - GuiScreen.setClipboardString(this.getSelectedText()); - return true; - } else if (GuiScreen.isKeyComboCtrlV(keyCode)) { - if (this.isEnabled) { - this.writeText(GuiScreen.getClipboardString()); - } - - return true; - } else if (GuiScreen.isKeyComboCtrlX(keyCode)) { - GuiScreen.setClipboardString(this.getSelectedText()); - - if (this.isEnabled) { - this.writeText(""); - } - - return true; - } else { - switch (keyCode) { - case 14: - if (GuiScreen.isCtrlKeyDown()) { - if (this.isEnabled) { - this.deleteWords(-1); - } - } else if (this.isEnabled) { - this.deleteFromCursor(-1); - } - return true; - - case 199: - if (GuiScreen.isShiftKeyDown()) { - this.setSelectionPos(0); - } else { - this.setCursorPositionZero(); - } - return true; - - case 203: - if (GuiScreen.isShiftKeyDown()) { - if (GuiScreen.isCtrlKeyDown()) { - this.setSelectionPos(this.getNthWordFromPos(-1, selectionEnd)); - } else { - this.setSelectionPos(this.selectionEnd - 1); - } - } else if (GuiScreen.isCtrlKeyDown()) { - this.cursorPosition = this.getNthWordFromCursor(-1); - } else { - this.moveCursorBy(-1); - } - return true; - - case 205: - if (GuiScreen.isShiftKeyDown()) { - if (GuiScreen.isCtrlKeyDown()) { - this.setSelectionPos(this.getNthWordFromPos(1, selectionEnd)); - } else { - this.setSelectionPos(this.selectionEnd + 1); - } - } else if (GuiScreen.isCtrlKeyDown()) { - this.cursorPosition = this.getNthWordFromCursor(1); - } else { - this.moveCursorBy(1); - } - return true; - - case 207: - if (GuiScreen.isShiftKeyDown()) { - this.setSelectionPos(text.length()); - } else { - this.setCursorPositionEnd(); - } - return true; - - case 211: - if (GuiScreen.isCtrlKeyDown()) { - if (this.isEnabled) { - this.deleteWords(1); - } - } else if (this.isEnabled) { - this.deleteFromCursor(1); - } - return true; - - case 28: - if (runnable != null) { - runnable.run(); - } - return true; - - default: - if (ChatAllowedCharacters.isAllowedCharacter(typedChar)) { - if (this.isEnabled) { - this.writeText(String.valueOf(typedChar)); - } - return true; - } - return false; - } - } - } - - public boolean mouseClicked(int mouseX, int mouseY, int mouseButton) { - boolean flag = (mouseX >= this.xPosition && mouseX < xPosition + this.width && mouseY >= yPosition) && mouseY < this.yPosition + this.height; - - if (this.canLoseFocus) { - this.isFocused = flag; - } - - if (this.isFocused && flag && mouseButton == 0) { - int i = (int) (mouseX - this.xPosition); - - if (this.enableBackgroundDrawing) { - i -= 4; - } - - String s = font.trimStringToWidth(text.substring(this.lineScrollOffset), this.getWidth()); - this.cursorPosition = font.trimStringToWidth(s, i).length() + this.lineScrollOffset; - return true; - } else { - return false; - } - } - - public void render(float x, float y, float width, float height, int mouseX, int mouseY) { - this.xPosition = x; - this.yPosition = y; - this.width = width; - this.height = height; - if (this.visible) { - if (Render2DUtils.isHovered(x, y, width, height, mouseX, mouseY)) { - if (isFocused) { - btnColor.base(new Color(255, 255, 255, 50)); - } else { - btnColor.base(new Color(255, 255, 255, 20)); - } - } else { - btnColor.base(new Color(255, 255, 255, 20)); - } - Render2DUtils.drawOptimizedRoundedRect(xPosition, yPosition, width, height, btnColor.getColor()); - - int j = this.cursorPosition - this.lineScrollOffset; - int k = this.selectionEnd - this.lineScrollOffset; - String s = font.trimStringToWidth(text.substring(this.lineScrollOffset), this.getWidth()); - boolean flag = j >= 0 && j <= s.length(); - boolean flag1 = this.isFocused && (this.cursorCounter / 6 % 2 == 0) && flag; - float l = this.enableBackgroundDrawing ? this.xPosition + 4 : this.xPosition; - float i1 = this.enableBackgroundDrawing ? this.yPosition + (this.height - 8) / 2 : this.yPosition; - float j1 = l; - - if (k > s.length()) { - k = s.length(); - } - - if (s.isEmpty() && !isFocused) { - font.drawStringWithShadow(placeholder, xPosition + 4, i1, new Color(120, 120, 120).getRGB()); - } else { - font.drawStringWithShadow(s.substring(0, k), l, i1, -1); - } - - if (flag1) { - Gui.drawRect((int) (j1 + font.getStringWidth(s.substring(0, j))), (int) (i1 - 1), (int) (j1 + font.getStringWidth(s.substring(0, j)) + 1), (int) (i1 + font.getHeight() - 1), -3092272); - } - } - } - - public int getWidth() { - return (int) this.width; - } - - public void setSelectionPos(int pos) { - if (pos > this.text.length()) { - pos = this.text.length(); - } - - if (pos < 0) { - pos = 0; - } - - this.selectionEnd = pos; - if (font != null) { - int i = font.trimStringToWidth(text, this.getWidth()).length(); - if (i > 0) { - this.selectionEnd = i; - } - } - } - - public void setVisible(boolean visible) { - this.visible = visible; - } - - public boolean isVisible() { - return visible; - } - - public void setCanLoseFocus(boolean canLoseFocus) { - this.canLoseFocus = canLoseFocus; - } - - public void setEnabled(boolean enabled) { - this.isEnabled = enabled; - } - - public boolean isEnabled() { - return this.isEnabled; - } -} diff --git a/v1.8.9/src/main/resources/mixins.fpsmaster.json b/v1.8.9/src/main/resources/mixins.fpsmaster.json index 2c59be17..e170c89f 100644 --- a/v1.8.9/src/main/resources/mixins.fpsmaster.json +++ b/v1.8.9/src/main/resources/mixins.fpsmaster.json @@ -19,7 +19,6 @@ "EntityFXMixin_StaticParticleColor", "MixinAbstractClientPlayer", "MixinChatLine", - "MixinClientBrandRetriever", "MixinEntityPlayerSP", "MixinEntityRenderer", "MixinFontRender", From 21da80466f1fb6a4cb96c7829466590bc5165735 Mon Sep 17 00:00:00 2001 From: SuperSkidder Date: Wed, 16 Jul 2025 19:23:51 +0800 Subject: [PATCH 091/193] fix: clickgui position wrong when resizing window --- shared/java/top/fpsmaster/ui/click/MainPanel.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/shared/java/top/fpsmaster/ui/click/MainPanel.java b/shared/java/top/fpsmaster/ui/click/MainPanel.java index f50168c9..29bf6ff1 100644 --- a/shared/java/top/fpsmaster/ui/click/MainPanel.java +++ b/shared/java/top/fpsmaster/ui/click/MainPanel.java @@ -1,5 +1,6 @@ package top.fpsmaster.ui.click; +import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.GlStateManager; import net.minecraft.util.ResourceLocation; import org.lwjgl.input.Mouse; @@ -239,6 +240,13 @@ public void initGui() { selection = y + 70f; } + @Override + public void onResize(Minecraft mcIn, int w, int h) { + super.onResize(mcIn, w, h); + x = (int) ((guiWidth - width) / 2); + y = (int) ((guiHeight - height) / 2); + } + @Override public void onGuiClosed() { super.onGuiClosed(); From 652c80a3b84763519a1cca424659860e1b11e199 Mon Sep 17 00:00:00 2001 From: SuperSkidder Date: Wed, 16 Jul 2025 19:35:43 +0800 Subject: [PATCH 092/193] fix: crash on some device because lua natives are not supported --- .../java/top/fpsmaster/modules/lua/LuaManager.java | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/shared/java/top/fpsmaster/modules/lua/LuaManager.java b/shared/java/top/fpsmaster/modules/lua/LuaManager.java index cf5b36a8..9f87c226 100644 --- a/shared/java/top/fpsmaster/modules/lua/LuaManager.java +++ b/shared/java/top/fpsmaster/modules/lua/LuaManager.java @@ -9,6 +9,7 @@ import top.fpsmaster.exception.FileException; import top.fpsmaster.features.manager.Module; import top.fpsmaster.interfaces.ProviderManager; +import top.fpsmaster.modules.logger.ClientLogger; import top.fpsmaster.utils.Utility; import top.fpsmaster.utils.os.FileUtils; import top.fpsmaster.utils.render.Render2DUtils; @@ -28,8 +29,15 @@ public void init() throws FileException { } - public static LuaScript loadLua(RawLua rawLua) { - Lua lua = new Lua53(); + public static LuaScript loadLua(RawLua rawLua) throws FileException { + Lua lua; + try { + lua = new Lua53(); + }catch (LinkageError e){ + ClientLogger.error("[Warning] Device does not support Lua."); + // todo: 在这里应该设置一个flag,然后禁止用户使用所有相关功能。 + return null; + } LuaScript luaScript = new LuaScript(lua, rawLua); try { lua.run("System = java.import('java.lang.System')"); @@ -217,7 +225,7 @@ public static void reload() throws FileException { } } - public static void hotswap() throws FileException { + public static void hotswap() throws Throwable { ArrayList newRawLuaList = new ArrayList<>(); File[] luas = FileUtils.plugins.listFiles(); for (File luaFile : luas) { From 2a4df5983a5ed504a4f44168ed4aeec53fc55577 Mon Sep 17 00:00:00 2001 From: SuperSkidder Date: Wed, 16 Jul 2025 19:37:45 +0800 Subject: [PATCH 093/193] fix: don't allow user open dev gui if is not in dev mode --- shared/java/top/fpsmaster/features/manager/ModuleManager.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/shared/java/top/fpsmaster/features/manager/ModuleManager.java b/shared/java/top/fpsmaster/features/manager/ModuleManager.java index 01d8cf8a..b7e38446 100644 --- a/shared/java/top/fpsmaster/features/manager/ModuleManager.java +++ b/shared/java/top/fpsmaster/features/manager/ModuleManager.java @@ -11,6 +11,7 @@ import top.fpsmaster.features.impl.render.*; import top.fpsmaster.features.impl.utility.*; import top.fpsmaster.interfaces.ProviderManager; +import top.fpsmaster.modules.dev.DevMode; import top.fpsmaster.modules.logger.ClientLogger; import top.fpsmaster.ui.click.MainPanel; import top.fpsmaster.ui.click.modules.ModuleRenderer; @@ -47,7 +48,7 @@ public void onKey(EventKey e) { } } - if (e.key == Keyboard.KEY_INSERT) { + if (e.key == Keyboard.KEY_INSERT && DevMode.INSTACE.dev) { Minecraft.getMinecraft().displayGuiScreen(new DevSpace()); } } From 48005cd0ef2030aac2b3355a2f0be1ded02d5e46 Mon Sep 17 00:00:00 2001 From: SuperSkidder Date: Wed, 16 Jul 2025 19:40:25 +0800 Subject: [PATCH 094/193] fix: compile error --- shared/java/top/fpsmaster/modules/lua/LuaManager.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/shared/java/top/fpsmaster/modules/lua/LuaManager.java b/shared/java/top/fpsmaster/modules/lua/LuaManager.java index 9f87c226..087e731c 100644 --- a/shared/java/top/fpsmaster/modules/lua/LuaManager.java +++ b/shared/java/top/fpsmaster/modules/lua/LuaManager.java @@ -225,7 +225,7 @@ public static void reload() throws FileException { } } - public static void hotswap() throws Throwable { + public static void hotswap() throws FileException { ArrayList newRawLuaList = new ArrayList<>(); File[] luas = FileUtils.plugins.listFiles(); for (File luaFile : luas) { From 9425048c6a315266ac2f9d162dc1a2bc30757085 Mon Sep 17 00:00:00 2001 From: SuperSkidder Date: Wed, 16 Jul 2025 19:46:31 +0800 Subject: [PATCH 095/193] fix: completely fixed gui position --- .../utils/render/ScaledGuiScreen.java | 21 +++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/shared/java/top/fpsmaster/utils/render/ScaledGuiScreen.java b/shared/java/top/fpsmaster/utils/render/ScaledGuiScreen.java index 4aaf8d2c..1dccd16b 100644 --- a/shared/java/top/fpsmaster/utils/render/ScaledGuiScreen.java +++ b/shared/java/top/fpsmaster/utils/render/ScaledGuiScreen.java @@ -1,5 +1,6 @@ package top.fpsmaster.utils.render; +import net.minecraft.client.Minecraft; import net.minecraft.client.gui.GuiScreen; import net.minecraft.client.gui.ScaledResolution; import org.lwjgl.opengl.GL11; @@ -14,19 +15,31 @@ public class ScaledGuiScreen extends GuiScreen { @Override public void drawScreen(int mouseX, int mouseY, float partialTicks) { super.drawScreen(mouseX, mouseY, partialTicks); - ScaledResolution sr = new ScaledResolution(mc); GL11.glPushMatrix(); + int realMouseX = mouseX * scaleFactor / 2; + int realMouseY = mouseY * scaleFactor / 2; scaleFactor = Render2DUtils.fixScale(); float[] bounds = Render2DUtils.getFixedBounds(); guiWidth = bounds[0]; guiHeight = bounds[1]; - int realMouseX = mouseX * scaleFactor / 2; - int realMouseY = mouseY * scaleFactor / 2; - render(realMouseX, realMouseY, partialTicks); GL11.glPopMatrix(); } + @Override + public void onResize(Minecraft mcIn, int w, int h) { + super.onResize(mcIn, w, h); + scaleFactor = Render2DUtils.fixScale(); + float[] bounds = Render2DUtils.getFixedBounds(); + guiWidth = bounds[0]; + guiHeight = bounds[1]; + } + + @Override + public void initGui() { + super.initGui(); + } + @Override protected void mouseClicked(int mouseX, int mouseY, int mouseButton) throws IOException { super.mouseClicked(mouseX, mouseY, mouseButton); From c2f0ef4f7c39c52a6e88b465426eed81fee10c51 Mon Sep 17 00:00:00 2001 From: SuperSkidder Date: Wed, 16 Jul 2025 19:59:40 +0800 Subject: [PATCH 096/193] feat: Language switch support --- shared/java/top/fpsmaster/FPSMaster.java | 9 +++++-- .../impl/interfaces/ClientSettings.java | 24 +++++++++++++++++-- .../assets/minecraft/client/lang/en_us.lang | 3 +++ .../assets/minecraft/client/lang/zh_cn.lang | 3 +++ 4 files changed, 35 insertions(+), 4 deletions(-) diff --git a/shared/java/top/fpsmaster/FPSMaster.java b/shared/java/top/fpsmaster/FPSMaster.java index 188bea09..ec21b9ad 100644 --- a/shared/java/top/fpsmaster/FPSMaster.java +++ b/shared/java/top/fpsmaster/FPSMaster.java @@ -4,6 +4,7 @@ import top.fpsmaster.exception.FileException; import top.fpsmaster.features.GlobalListener; import top.fpsmaster.features.command.CommandManager; +import top.fpsmaster.features.impl.interfaces.ClientSettings; import top.fpsmaster.features.manager.ModuleManager; import top.fpsmaster.font.FontManager; import top.fpsmaster.modules.account.AccountManager; @@ -88,7 +89,11 @@ private void initializeFonts() { private void initializeLang() throws FileException { ClientLogger.info("Initializing I18N..."); - i18n.read("zh_cn"); + if (ClientSettings.language.getValue() == 1) { + i18n.read("zh_cn"); + } else { + i18n.read("en_us"); + } } private void initializeConfigures() throws Exception { @@ -174,13 +179,13 @@ private void checkUpdate() { public void initialize() { try { initializeFonts(); - initializeLang(); initializeMusic(); initializeModules(); initializeComponents(); initializeConfigures(); initializeCommands(); initializePlugins(); + initializeLang(); checkUpdate(); checkOptifine(); } catch (Exception e) { diff --git a/shared/java/top/fpsmaster/features/impl/interfaces/ClientSettings.java b/shared/java/top/fpsmaster/features/impl/interfaces/ClientSettings.java index 76285315..b3b67f12 100644 --- a/shared/java/top/fpsmaster/features/impl/interfaces/ClientSettings.java +++ b/shared/java/top/fpsmaster/features/impl/interfaces/ClientSettings.java @@ -5,15 +5,20 @@ import top.fpsmaster.event.EventDispatcher; import top.fpsmaster.event.Subscribe; import top.fpsmaster.event.events.EventValueChange; +import top.fpsmaster.exception.FileException; import top.fpsmaster.features.impl.InterfaceModule; import top.fpsmaster.features.manager.Category; import top.fpsmaster.features.settings.impl.BindSetting; import top.fpsmaster.features.settings.impl.BooleanSetting; +import top.fpsmaster.features.settings.impl.ModeSetting; import top.fpsmaster.features.settings.impl.TextSetting; import top.fpsmaster.utils.OptifineUtil; import top.fpsmaster.utils.Utility; +import java.util.Locale; + public class ClientSettings extends InterfaceModule { + public static ModeSetting language = new ModeSetting("Language", 1, "English", "Chinese"); public static BooleanSetting blur = new BooleanSetting("blur", false); public static BindSetting keyBind = new BindSetting("ClickGuiKey", Keyboard.KEY_RSHIFT); public static BooleanSetting fixedScale = new BooleanSetting("FixedScale", false); @@ -22,8 +27,15 @@ public class ClientSettings extends InterfaceModule { public ClientSettings() { super("ClientSettings", Category.Utility); - addSettings(keyBind, fixedScale, blur, clientCommand, prefix); + addSettings(language, keyBind, fixedScale, blur, clientCommand, prefix); EventDispatcher.registerListener(this); + // get system language + Locale locale = Locale.getDefault(); + if (locale.getLanguage().equals("zh")) { + language.setValue(1); + } else { + language.setValue(0); + } } @Override @@ -33,7 +45,15 @@ public void onEnable() { } @Subscribe - public void onValueChange(EventValueChange e) { + public void onValueChange(EventValueChange e) throws FileException { + if (e.setting == language){ + if (((int) e.newValue) == 1) { + FPSMaster.i18n.read("zh_cn"); + } else { + FPSMaster.i18n.read("en_us"); + } + } + if (e.setting == blur && ((boolean) e.newValue)) { if (OptifineUtil.isFastRender()) { Utility.sendClientNotify(FPSMaster.i18n.get("blur.fast_render")); diff --git a/shared/resources/assets/minecraft/client/lang/en_us.lang b/shared/resources/assets/minecraft/client/lang/en_us.lang index 584acc83..8516e25a 100644 --- a/shared/resources/assets/minecraft/client/lang/en_us.lang +++ b/shared/resources/assets/minecraft/client/lang/en_us.lang @@ -459,6 +459,9 @@ clientsettings.fixedscale=Fixed GUI Scale clientsettings.blur=Blur UI Elements clientsettings.command=Client Command clientsettings.prefix=Command Prefix +clientsettings.language=Language +clientsettings.language.chinese=Simplified Chinese +clientsettings.language.english=English dragonwings=Dragon Wings dragonwings.desc=Display dragon wings diff --git a/shared/resources/assets/minecraft/client/lang/zh_cn.lang b/shared/resources/assets/minecraft/client/lang/zh_cn.lang index c15bef0e..ad3d793a 100644 --- a/shared/resources/assets/minecraft/client/lang/zh_cn.lang +++ b/shared/resources/assets/minecraft/client/lang/zh_cn.lang @@ -465,6 +465,9 @@ clientsettings.fixedscale=固定界面缩放比例 clientsettings.blur=界面组件模糊 clientsettings.command=客户端命令 clientsettings.prefix=命令前缀 +clientsettings.language=客户端语言 +clientsettings.language.chinese=简体中文 +clientsettings.language.english=英语 dragonwings=龙翅膀 dragonwings.desc=在自己身上龙翅膀 From fbfab1a88eed6b4bb3625c54e0a7b00459677173 Mon Sep 17 00:00:00 2001 From: SuperSkidder Date: Wed, 16 Jul 2025 20:26:58 +0800 Subject: [PATCH 097/193] feat: background theme switch --- .../fpsmaster/ui/screens/mainmenu/MainMenu.java | 14 ++++++++++++++ .../top/fpsmaster/utils/render/Render2DUtils.java | 3 ++- .../assets/minecraft/client/gui/screen/theme.png | Bin 0 -> 214 bytes 3 files changed, 16 insertions(+), 1 deletion(-) create mode 100644 shared/resources/assets/minecraft/client/gui/screen/theme.png diff --git a/shared/java/top/fpsmaster/ui/screens/mainmenu/MainMenu.java b/shared/java/top/fpsmaster/ui/screens/mainmenu/MainMenu.java index d2951fac..61722b15 100644 --- a/shared/java/top/fpsmaster/ui/screens/mainmenu/MainMenu.java +++ b/shared/java/top/fpsmaster/ui/screens/mainmenu/MainMenu.java @@ -81,6 +81,12 @@ public void render(int mouseX, int mouseY, float partialTicks) { Render2DUtils.drawImage(new ResourceLocation("client/gui/screen/avatar.png"), 14f, 15f, 10f, 10f, -1); FPSMaster.fontManager.s16.drawString(mc.getSession().getUsername(), 28, 16, Color.WHITE.getRGB()); + + // background theme button + Render2DUtils.drawOptimizedRoundedRect(guiWidth - 22, 13, 12, 12, new Color(0, 0, 0, 60)); + Render2DUtils.drawImage(new ResourceLocation("client/gui/screen/theme.png"), guiWidth - 20, 15f, 8f, 8f, -1); + + // Position buttons and render them float x = guiWidth / 2f - 50; float y = guiHeight / 2f - 30; @@ -130,6 +136,14 @@ public void onClick(int mouseX, int mouseY, int mouseButton) { float nw = FPSMaster.fontManager.s16.getStringWidth(info); if (mouseButton == 0) { + if (Render2DUtils.isHovered(guiWidth - 22, 13, 12, 12, mouseX, mouseY)) { + if (FPSMaster.configManager.configure.getOrCreate("background", "new").equals("classic")) { + FPSMaster.configManager.configure.set("background", "new"); + } else { + FPSMaster.configManager.configure.set("background", "classic"); + } + } + if (Render2DUtils.isHovered(4f, guiHeight - 52, nw, 14f, mouseX, mouseY)) { Minecraft.getMinecraft().displayGuiScreen(new GuiLogin()); } diff --git a/shared/java/top/fpsmaster/utils/render/Render2DUtils.java b/shared/java/top/fpsmaster/utils/render/Render2DUtils.java index 1a9cac0b..efae8f84 100644 --- a/shared/java/top/fpsmaster/utils/render/Render2DUtils.java +++ b/shared/java/top/fpsmaster/utils/render/Render2DUtils.java @@ -14,6 +14,7 @@ import org.lwjgl.opengl.GL11; import org.lwjgl.opengl.GL14; import org.lwjgl.opengl.GL20; +import top.fpsmaster.FPSMaster; import top.fpsmaster.features.impl.interfaces.ClientSettings; import top.fpsmaster.interfaces.ProviderManager; import top.fpsmaster.ui.screens.mainmenu.MainMenu; @@ -270,7 +271,7 @@ public static void drawBackground(int guiWidth, int guiHeight, int mouseX, int m Render2DUtils.drawImage(textureLocation, 0f, 0f, guiWidth, guiHeight, -1); Render2DUtils.drawRect(0f, 0f, guiWidth, guiHeight, new Color(22, 22, 22, 50)); } else { - if (OSUtil.supportShader()) { + if (OSUtil.supportShader() && !FPSMaster.configManager.configure.getOrCreate("background", "new").equals("classic")) { if (mc.currentScreen instanceof MainMenu) { animation = (float) AnimationUtils.base(animation, 1.0f, 0.05f); } else { diff --git a/shared/resources/assets/minecraft/client/gui/screen/theme.png b/shared/resources/assets/minecraft/client/gui/screen/theme.png new file mode 100644 index 0000000000000000000000000000000000000000..70c568697cdd6e735436db0bbd13501ede4e377d GIT binary patch literal 214 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`jKx9jP7LeL$-D$|Sc;uILpXq- zh9ji|$Zzm;aSXBOeLKOC_mG2t>wN*15T~UIj4}!fH5|N_hB&E~$Tl=z_vVk@bdxvc z!2$1QU!L#xWUJ%)x=Qa=%n7xx3;C8ls?>gV=2h+N>p6k`I}^UtE{nNPukeDgk3n$a z73mKw$BwPma}XEgRN(r*;aXou?DGpdu07G$;0{XNKdrV?)F$^RkMW(xKA>9|JYD@< J);T3K0RXOnP2&In literal 0 HcmV?d00001 From 01ff8d6216b81610bf01953f7468fcf99c1f466b Mon Sep 17 00:00:00 2001 From: SuperSkidder Date: Wed, 16 Jul 2025 20:54:46 +0800 Subject: [PATCH 098/193] fix: scroll container roll limit only work when hovered --- .../top/fpsmaster/ui/click/component/ScrollContainer.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/shared/java/top/fpsmaster/ui/click/component/ScrollContainer.java b/shared/java/top/fpsmaster/ui/click/component/ScrollContainer.java index c480631b..093798d3 100644 --- a/shared/java/top/fpsmaster/ui/click/component/ScrollContainer.java +++ b/shared/java/top/fpsmaster/ui/click/component/ScrollContainer.java @@ -75,11 +75,12 @@ public void draw(float x, float y, float width, float height, int mouseX, int mo } else if (mouseDWheel < 0) { wheel_anim -= 20f; } - float maxUp = this.height - height; - wheel_anim = Math.min(Math.max(wheel_anim, -maxUp), 0f); + } - wheel = (float) AnimationUtils.base(wheel, wheel_anim, 0.2); } + float maxUp = this.height - height; + wheel_anim = Math.min(Math.max(wheel_anim, -maxUp), 0f); + wheel = (float) AnimationUtils.base(wheel, wheel_anim, 0.2); } public void setHeight(float height) { From 8dad6148d0579a768ce913de4b0a67cacfc4bcf0 Mon Sep 17 00:00:00 2001 From: SuperSkidder Date: Wed, 16 Jul 2025 20:56:38 +0800 Subject: [PATCH 099/193] feat: clientmate logo(WIP) --- .../features/impl/utility/LevelTag.java | 21 ++++++++++++++++-- .../assets/minecraft/client/textures/mate.png | Bin 0 -> 707 bytes 2 files changed, 19 insertions(+), 2 deletions(-) create mode 100644 shared/resources/assets/minecraft/client/textures/mate.png diff --git a/shared/java/top/fpsmaster/features/impl/utility/LevelTag.java b/shared/java/top/fpsmaster/features/impl/utility/LevelTag.java index 38527427..80b150d3 100644 --- a/shared/java/top/fpsmaster/features/impl/utility/LevelTag.java +++ b/shared/java/top/fpsmaster/features/impl/utility/LevelTag.java @@ -6,11 +6,13 @@ import net.minecraft.client.renderer.WorldRenderer; import net.minecraft.client.renderer.vertex.DefaultVertexFormats; import net.minecraft.entity.Entity; +import net.minecraft.util.ResourceLocation; import org.lwjgl.opengl.GL11; import top.fpsmaster.features.manager.Category; import top.fpsmaster.features.manager.Module; import top.fpsmaster.features.settings.impl.BooleanSetting; import top.fpsmaster.interfaces.ProviderManager; +import top.fpsmaster.utils.render.Render2DUtils; import static top.fpsmaster.utils.Utility.mc; @@ -83,7 +85,13 @@ else if (mc.gameSettings.thirdPersonView == 1) i = -10; } + boolean isMate = entityIn == mc.thePlayer; int j = fontRenderer.getStringWidth(str) / 2; + + if (isMate) { + j += 6; + } + GlStateManager.disableTexture2D(); worldRenderer.begin(7, DefaultVertexFormats.POSITION_COLOR); worldRenderer.pos(-j - 1, -1 + i, 0.0F).color(0.0F, 0.0F, 0.0F, 0.25F).endVertex(); @@ -92,10 +100,19 @@ else if (mc.gameSettings.thirdPersonView == 1) worldRenderer.pos(j + 1, -1 + i, 0.0F).color(0.0F, 0.0F, 0.0F, 0.25F).endVertex(); tessellator.draw(); GlStateManager.enableTexture2D(); - fontRenderer.drawString(str, -fontRenderer.getStringWidth(str) / 2, i, 553648127); + if (isMate) { + Render2DUtils.drawImage(new ResourceLocation("client/textures/mate.png"), -fontRenderer.getStringWidth(str) / 2f - 4f, i - 1, 8, 8, -1, true); + fontRenderer.drawString(str, -fontRenderer.getStringWidth(str) / 2 + 6, i, 553648127); + }else{ + fontRenderer.drawString(str, -fontRenderer.getStringWidth(str) / 2, i, 553648127); + } GlStateManager.enableDepth(); GlStateManager.depthMask(true); - fontRenderer.drawString(str, -fontRenderer.getStringWidth(str) / 2, i, -1); + if (isMate) { + fontRenderer.drawString(str, -fontRenderer.getStringWidth(str) / 2 + 6, i, -1); + }else{ + fontRenderer.drawString(str, -fontRenderer.getStringWidth(str) / 2, i, -1); + } GlStateManager.enableLighting(); GlStateManager.disableBlend(); GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F); diff --git a/shared/resources/assets/minecraft/client/textures/mate.png b/shared/resources/assets/minecraft/client/textures/mate.png new file mode 100644 index 0000000000000000000000000000000000000000..7118b2c8a85cdb4cd2156bd7eacde26c8751c5ce GIT binary patch literal 707 zcmV;!0zCbRP)Px#1am@3R0s$N2z&@+hyVZrZAnByR5*=YlTB#UR}{s6=VfMs6Pp=DEYjL!l!{=b z>RQogT?7i1Zd|)A)NDkoiDENFs+%~QZUk{t#6ta8)F8A$DK129j22uO6@{Xv=0nJT zGRZq#{O2Rn3lARmopaxP=iDd$7lXqtEr^pLunoJ{fX#Hk*D{@9qy8z0vva6-V_+z8`+ZV*i5Ybl+F=pQfE?r;2%$$%!KA&f0S4+w(H_Ts; zQ?LXIYzq>_fr9f9MMb%qj7-A=TPi! zCtn>k7k|kxGpG7In4~K1P2|83@U@ULry7IuZU&MhCI9-HdGH9PXH#L51YW-le7I(b zSjT5N!$>F(Y0|i|ZY`8PfwMoQL<7+fBXnlr(UU9}E_X5UB+I9zMQm5fM>N?S<)dYf zDX?3#Y-$UqBMlHEw|*Q{pCktWNj@_a_Smkt4vZ08UoocL*bwbXgS_0*W(*FyR0|xo peL$!H7Ur3y@tiqT9%}#2{{hjV4=>ee$8`Vz002ovPDHLkV1g&?L8AZw literal 0 HcmV?d00001 From 093243a8269ff98f0b8a071961a94cd90e83638f Mon Sep 17 00:00:00 2001 From: SuperSkidder Date: Wed, 16 Jul 2025 21:22:50 +0800 Subject: [PATCH 100/193] fix: fix a render bug --- shared/java/top/fpsmaster/ui/custom/Component.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/shared/java/top/fpsmaster/ui/custom/Component.java b/shared/java/top/fpsmaster/ui/custom/Component.java index 9d76bf8b..9af98d89 100644 --- a/shared/java/top/fpsmaster/ui/custom/Component.java +++ b/shared/java/top/fpsmaster/ui/custom/Component.java @@ -3,6 +3,7 @@ import net.minecraft.client.Minecraft; import net.minecraft.client.gui.GuiChat; import net.minecraft.client.gui.ScaledResolution; +import net.minecraft.client.renderer.GlStateManager; import org.lwjgl.input.Mouse; import org.lwjgl.opengl.GL11; import top.fpsmaster.FPSMaster; @@ -17,6 +18,9 @@ import java.awt.*; +import static org.lwjgl.opengl.GL11.*; +import static org.lwjgl.opengl.GL11.GL_BLEND; + public class Component { private float dragX = 0f; @@ -99,6 +103,8 @@ public void display(int mouseX, int mouseY) { AnimationUtils.base(alpha, 50.0, 0.1f) : AnimationUtils.base(alpha, 0.0, 0.1f)); Render2DUtils.drawOptimizedRoundedRect(rX - 2, rY - 2, scaledWidth + 4, scaledHeight + 4, new Color(0, 0, 0, (int) alpha)); + GL11.glColor4f(1,1,1,1); + if (!Mouse.isButtonDown(0)) { FPSMaster.componentsManager.dragLock = ""; From b8fa88f1144fabf1ddee75254ec9c1acfa00879d Mon Sep 17 00:00:00 2001 From: SuperSkidder Date: Thu, 17 Jul 2025 00:04:36 +0800 Subject: [PATCH 101/193] fix: fix the bug of generateRoundImage --- .../top/fpsmaster/ui/custom/Component.java | 2 +- .../top/fpsmaster/utils/awt/AWTUtils.java | 54 ++++++++++--------- 2 files changed, 29 insertions(+), 27 deletions(-) diff --git a/shared/java/top/fpsmaster/ui/custom/Component.java b/shared/java/top/fpsmaster/ui/custom/Component.java index 9af98d89..82885ecc 100644 --- a/shared/java/top/fpsmaster/ui/custom/Component.java +++ b/shared/java/top/fpsmaster/ui/custom/Component.java @@ -201,7 +201,7 @@ public void drawRect(float x, float y, float width, float height, Color color) { if (mod.bg.getValue()) { if (mod.rounded.getValue()) { - Render2DUtils.drawOptimizedRoundedRect(x, y, scaledWidth, scaledHeight, mod.roundRadius.getValue().intValue(), color.getRGB()); + Render2DUtils.drawRoundedRectImage(x, y, scaledWidth, scaledHeight, mod.roundRadius.getValue().intValue(), color); } else { Render2DUtils.drawRect(x, y, scaledWidth, scaledHeight, color); } diff --git a/shared/java/top/fpsmaster/utils/awt/AWTUtils.java b/shared/java/top/fpsmaster/utils/awt/AWTUtils.java index 972cc793..6090328a 100644 --- a/shared/java/top/fpsmaster/utils/awt/AWTUtils.java +++ b/shared/java/top/fpsmaster/utils/awt/AWTUtils.java @@ -14,38 +14,40 @@ public class AWTUtils { private static final HashMap generatedFull = new HashMap<>(); public static ResourceLocation generateRoundImage(int width, int height, int radius) { - ResourceLocation location = generatedFull.get(radius); - if (location != null) { - return location; + if (width <= 0 || height <= 0 || radius < 0) { + throw new IllegalArgumentException("Width, height must be positive and radius must be non-negative"); } - width *= 2; - height *= 2; + return generatedFull.computeIfAbsent(radius, r -> { + int scaledWidth = width * 2; + int scaledHeight = height * 2; - try { - BufferedImage bufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); - java.awt.Graphics2D graphics2D = bufferedImage.createGraphics(); - - graphics2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); - graphics2D.setColor(new Color(0, 0, 0, 0)); // 透明背景 - graphics2D.fillRect(0, 0, width, height); - - graphics2D.setComposite(AlphaComposite.SrcOver); - graphics2D.setColor(Color.WHITE); // 白色圆角矩形 - RoundRectangle2D roundRectangle = new RoundRectangle2D.Float(0, 0, width, height, 0,0); - graphics2D.fill(roundRectangle); + try { + BufferedImage bufferedImage = new BufferedImage(scaledWidth, scaledHeight, BufferedImage.TYPE_INT_ARGB); + Graphics2D graphics2D = bufferedImage.createGraphics(); - location = Minecraft.getMinecraft().getTextureManager() - .getDynamicTextureLocation(radius + "_full", new DynamicTexture(bufferedImage)); + graphics2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + graphics2D.setColor(new Color(0,0,0,0)); + graphics2D.fillRect(0, 0, bufferedImage.getWidth(), bufferedImage.getHeight()); - generatedFull.put(radius, location); - - } catch (Exception e) { - e.printStackTrace(); - } + graphics2D.setComposite(AlphaComposite.SrcOver); + graphics2D.setColor(Color.WHITE); // 白色圆角矩形 + RoundRectangle2D roundRectangle = new RoundRectangle2D.Float(0, 0, scaledWidth, scaledHeight, r * 2, r * 2); + graphics2D.fill(roundRectangle); - // 返回生成的纹理 - return generatedFull.get(radius); + Minecraft mc = Minecraft.getMinecraft(); + if (mc == null || mc.getTextureManager() == null) { + return null; + } + graphics2D.dispose(); + + return mc.getTextureManager() + .getDynamicTextureLocation(r + "_full", new DynamicTexture(bufferedImage)); + } catch (Exception e) { + e.printStackTrace(); + return null; + } + }); } public static ResourceLocation[] generateRound(int radius) { From 8757b8e4f3f9119fb3ebceef9d2625b33606ec1d Mon Sep 17 00:00:00 2001 From: SuperSkidder Date: Thu, 17 Jul 2025 00:57:04 +0800 Subject: [PATCH 102/193] fix: resize bug --- shared/java/top/fpsmaster/ui/click/MainPanel.java | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/shared/java/top/fpsmaster/ui/click/MainPanel.java b/shared/java/top/fpsmaster/ui/click/MainPanel.java index 29bf6ff1..f3175831 100644 --- a/shared/java/top/fpsmaster/ui/click/MainPanel.java +++ b/shared/java/top/fpsmaster/ui/click/MainPanel.java @@ -215,6 +215,8 @@ public void render(int mouseX, int mouseY, float partialTicks) { @Override public void updateScreen() { super.updateScreen(); + x = (int) ((guiWidth - width) / 2); + y = (int) ((guiHeight - height) / 2); } @Override @@ -229,8 +231,6 @@ public void initGui() { // height = scaledHeight / 2f; // } - x = (int) ((guiWidth - width) / 2); - y = (int) ((guiHeight - height) / 2); categories.clear(); for (Category c : Category.values()) { @@ -243,8 +243,6 @@ public void initGui() { @Override public void onResize(Minecraft mcIn, int w, int h) { super.onResize(mcIn, w, h); - x = (int) ((guiWidth - width) / 2); - y = (int) ((guiHeight - height) / 2); } @Override From b5aa75c9472775d760a75a71f8131cced3d6df9d Mon Sep 17 00:00:00 2001 From: SuperSkidder Date: Thu, 17 Jul 2025 00:57:21 +0800 Subject: [PATCH 103/193] remove: not used resources --- .../minecraft/client/shaders/bloom.frag | 20 ------------------- .../minecraft/client/shaders/gaussian.frag | 19 ------------------ .../minecraft/client/shaders/kawaseDown.frag | 13 ------------ .../minecraft/client/shaders/kawaseUp.frag | 17 ---------------- 4 files changed, 69 deletions(-) delete mode 100644 shared/resources/assets/minecraft/client/shaders/bloom.frag delete mode 100644 shared/resources/assets/minecraft/client/shaders/gaussian.frag delete mode 100644 shared/resources/assets/minecraft/client/shaders/kawaseDown.frag delete mode 100644 shared/resources/assets/minecraft/client/shaders/kawaseUp.frag diff --git a/shared/resources/assets/minecraft/client/shaders/bloom.frag b/shared/resources/assets/minecraft/client/shaders/bloom.frag deleted file mode 100644 index 2ee42a61..00000000 --- a/shared/resources/assets/minecraft/client/shaders/bloom.frag +++ /dev/null @@ -1,20 +0,0 @@ -#version 120 - -uniform sampler2D inTexture, textureToCheck; -uniform vec2 texelSize, direction; -uniform float radius; -uniform float weights[256]; - -#define offset texelSize * direction - -void main() { - if (direction.y > 0 && texture2D(textureToCheck, gl_TexCoord[0].st).a != 0.0) discard; - float blr = texture2D(inTexture, gl_TexCoord[0].st).a * weights[0]; - - for (float f = 1.0; f <= radius; f++) { - blr += texture2D(inTexture, gl_TexCoord[0].st + f * offset).a * (weights[int(abs(f))]); - blr += texture2D(inTexture, gl_TexCoord[0].st - f * offset).a * (weights[int(abs(f))]); - } - - gl_FragColor = vec4(0.0, 0.0, 0.0, blr); -} diff --git a/shared/resources/assets/minecraft/client/shaders/gaussian.frag b/shared/resources/assets/minecraft/client/shaders/gaussian.frag deleted file mode 100644 index a0070b9d..00000000 --- a/shared/resources/assets/minecraft/client/shaders/gaussian.frag +++ /dev/null @@ -1,19 +0,0 @@ -#version 120 - -uniform sampler2D textureIn; -uniform vec2 texelSize, direction; -uniform float radius; -uniform float weights[256]; - -#define offset texelSize * direction - -void main() { - vec3 blr = texture2D(textureIn, gl_TexCoord[0].st).rgb * weights[0]; - - for (float f = 1.0; f <= radius; f++) { - blr += texture2D(textureIn, gl_TexCoord[0].st + f * offset).rgb * (weights[int(abs(f))]); - blr += texture2D(textureIn, gl_TexCoord[0].st - f * offset).rgb * (weights[int(abs(f))]); - } - - gl_FragColor = vec4(blr, 1.0); -} diff --git a/shared/resources/assets/minecraft/client/shaders/kawaseDown.frag b/shared/resources/assets/minecraft/client/shaders/kawaseDown.frag deleted file mode 100644 index 6f793375..00000000 --- a/shared/resources/assets/minecraft/client/shaders/kawaseDown.frag +++ /dev/null @@ -1,13 +0,0 @@ -#version 120 - -uniform sampler2D inTexture; -uniform vec2 offset, halfpixel; - -void main() { - vec4 sum = texture2D(inTexture, gl_TexCoord[0].st) * 4.0; - sum += texture2D(inTexture, gl_TexCoord[0].st - halfpixel.xy * offset); - sum += texture2D(inTexture, gl_TexCoord[0].st + halfpixel.xy * offset); - sum += texture2D(inTexture, gl_TexCoord[0].st + vec2(halfpixel.x, -halfpixel.y) * offset); - sum += texture2D(inTexture, gl_TexCoord[0].st - vec2(halfpixel.x, -halfpixel.y) * offset); - gl_FragColor = vec4(sum.rgb / 8.0, 1.0); -} diff --git a/shared/resources/assets/minecraft/client/shaders/kawaseUp.frag b/shared/resources/assets/minecraft/client/shaders/kawaseUp.frag deleted file mode 100644 index 775eb5fc..00000000 --- a/shared/resources/assets/minecraft/client/shaders/kawaseUp.frag +++ /dev/null @@ -1,17 +0,0 @@ -#version 120 - -uniform sampler2D inTexture; -uniform vec2 halfpixel, offset; - -void main() { - vec4 sum = texture2D(inTexture, gl_TexCoord[0].st + vec2(-halfpixel.x * 2.0, 0.0) * offset); - sum += texture2D(inTexture, gl_TexCoord[0].st + vec2(-halfpixel.x, halfpixel.y) * offset) * 2.0; - sum += texture2D(inTexture, gl_TexCoord[0].st + vec2(0.0, halfpixel.y * 2.0) * offset); - sum += texture2D(inTexture, gl_TexCoord[0].st + vec2(halfpixel.x, halfpixel.y) * offset) * 2.0; - sum += texture2D(inTexture, gl_TexCoord[0].st + vec2(halfpixel.x * 2.0, 0.0) * offset); - sum += texture2D(inTexture, gl_TexCoord[0].st + vec2(halfpixel.x, -halfpixel.y) * offset) * 2.0; - sum += texture2D(inTexture, gl_TexCoord[0].st + vec2(0.0, -halfpixel.y * 2.0) * offset); - sum += texture2D(inTexture, gl_TexCoord[0].st + vec2(-halfpixel.x, -halfpixel.y) * offset) * 2.0; - - gl_FragColor = vec4(sum.rgb / 12.0, 1.); -} From 36101d34349192751b7fe6378ec866e177c935a4 Mon Sep 17 00:00:00 2001 From: SuperSkidder Date: Thu, 17 Jul 2025 00:59:23 +0800 Subject: [PATCH 104/193] fix: change round image generation --- shared/java/top/fpsmaster/utils/awt/AWTUtils.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/shared/java/top/fpsmaster/utils/awt/AWTUtils.java b/shared/java/top/fpsmaster/utils/awt/AWTUtils.java index 6090328a..93ade31f 100644 --- a/shared/java/top/fpsmaster/utils/awt/AWTUtils.java +++ b/shared/java/top/fpsmaster/utils/awt/AWTUtils.java @@ -11,14 +11,14 @@ public class AWTUtils { private static final HashMap generated = new HashMap<>(); - private static final HashMap generatedFull = new HashMap<>(); + private static final HashMap generatedFull = new HashMap<>(); + public static ResourceLocation generateRoundImage(int width, int height, int radius) { if (width <= 0 || height <= 0 || radius < 0) { throw new IllegalArgumentException("Width, height must be positive and radius must be non-negative"); } - - return generatedFull.computeIfAbsent(radius, r -> { + return generatedFull.computeIfAbsent(width + "/" + height + "/" + radius, r -> { int scaledWidth = width * 2; int scaledHeight = height * 2; @@ -27,12 +27,12 @@ public static ResourceLocation generateRoundImage(int width, int height, int rad Graphics2D graphics2D = bufferedImage.createGraphics(); graphics2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); - graphics2D.setColor(new Color(0,0,0,0)); + graphics2D.setColor(new Color(0, 0, 0, 0)); graphics2D.fillRect(0, 0, bufferedImage.getWidth(), bufferedImage.getHeight()); graphics2D.setComposite(AlphaComposite.SrcOver); graphics2D.setColor(Color.WHITE); // 白色圆角矩形 - RoundRectangle2D roundRectangle = new RoundRectangle2D.Float(0, 0, scaledWidth, scaledHeight, r * 2, r * 2); + RoundRectangle2D roundRectangle = new RoundRectangle2D.Float(0, 0, scaledWidth, scaledHeight, radius * 2, radius * 2); graphics2D.fill(roundRectangle); Minecraft mc = Minecraft.getMinecraft(); From 9eab29296fc6310ec30edb2e8b359a2bb0bb7292 Mon Sep 17 00:00:00 2001 From: SuperSkidder Date: Thu, 17 Jul 2025 01:05:57 +0800 Subject: [PATCH 105/193] fix: color setting not render on some devices --- .../ui/click/modules/impl/ColorSettingRender.java | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/shared/java/top/fpsmaster/ui/click/modules/impl/ColorSettingRender.java b/shared/java/top/fpsmaster/ui/click/modules/impl/ColorSettingRender.java index fdc6ee27..75611480 100644 --- a/shared/java/top/fpsmaster/ui/click/modules/impl/ColorSettingRender.java +++ b/shared/java/top/fpsmaster/ui/click/modules/impl/ColorSettingRender.java @@ -48,7 +48,7 @@ public void render( ); if (aHeight > 1) { - if (OSUtil.supportShader()) { + if (!OSUtil.supportShader()) { GradientUtils.applyGradient( x + tW + 26, y + 15, 80f, aHeight, 1f, Color.getHSBColor(customColor.hue, 0.0f, 0f), @@ -61,6 +61,14 @@ public void render( new Color(255, 255, 255) ) ); + }else { + for (int i = 0; i < aHeight; i++) { + for (int j = 0; j < 80; j++) { + float brightness = 1 - (float) i / aHeight; + float saturation = (float) j / 80; + Render2DUtils.drawRect(x + tW + 26 + j, y + 16 + i, 1, 1, Color.getHSBColor(customColor.hue, saturation, brightness).getRGB()); + } + } } float saturation = customColor.saturation; From 170bd9bee62cce833f48693021847897b8040a3d Mon Sep 17 00:00:00 2001 From: SuperSkidder Date: Thu, 17 Jul 2025 01:06:21 +0800 Subject: [PATCH 106/193] fix: something wrong... --- .../top/fpsmaster/ui/click/modules/impl/ColorSettingRender.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/shared/java/top/fpsmaster/ui/click/modules/impl/ColorSettingRender.java b/shared/java/top/fpsmaster/ui/click/modules/impl/ColorSettingRender.java index 75611480..35ff07f7 100644 --- a/shared/java/top/fpsmaster/ui/click/modules/impl/ColorSettingRender.java +++ b/shared/java/top/fpsmaster/ui/click/modules/impl/ColorSettingRender.java @@ -48,7 +48,7 @@ public void render( ); if (aHeight > 1) { - if (!OSUtil.supportShader()) { + if (OSUtil.supportShader()) { GradientUtils.applyGradient( x + tW + 26, y + 15, 80f, aHeight, 1f, Color.getHSBColor(customColor.hue, 0.0f, 0f), From 283dc9c540626496eebc7a725d7555c6d3cecda2 Mon Sep 17 00:00:00 2001 From: SuperSkidder Date: Thu, 17 Jul 2025 01:10:26 +0800 Subject: [PATCH 107/193] docs: misc --- README.md | 2 -- docs/tasks.md | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/README.md b/README.md index 42b8e764..83f2c4fc 100644 --- a/README.md +++ b/README.md @@ -10,8 +10,6 @@ FPSMaster 是一个免费、强大的 Minecraft PvP 客户端。 ## 注意: -本分支是FPSMaster v4的开发分支,目前处于开发阶段,请勿在生产环境中使用。 - 如果你想参与到开发中,请查看以下注意事项: 1. 如果您要添加新的功能,请先在issue中提出,并进行讨论,避免您开发的功能与项目目标不一致 2. 请不要在生产环境中使用,除非你非常熟悉代码,并且知道自己在做什么。 diff --git a/docs/tasks.md b/docs/tasks.md index ed0c9066..2a19ffc3 100644 --- a/docs/tasks.md +++ b/docs/tasks.md @@ -38,7 +38,7 @@ 4. [ ] 添加事件调试/监控工具 ### 配置系统 -1. [ ] 重构配置保存格式 +1. [x] 重构配置保存格式 2. [ ] 实现配置版本迁移 3. [ ] 实现多配置文件切换 From 235b5f6730f4ad83e341f9aa76c35b4d3a15a8cd Mon Sep 17 00:00:00 2001 From: TeAnLi Date: Thu, 17 Jul 2025 02:55:47 +0800 Subject: [PATCH 108/193] feat(setting): Add spacing setting for InterfaceModule --- shared/java/top/fpsmaster/features/impl/InterfaceModule.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/shared/java/top/fpsmaster/features/impl/InterfaceModule.java b/shared/java/top/fpsmaster/features/impl/InterfaceModule.java index 7c7594a0..ae1b4810 100644 --- a/shared/java/top/fpsmaster/features/impl/InterfaceModule.java +++ b/shared/java/top/fpsmaster/features/impl/InterfaceModule.java @@ -16,6 +16,8 @@ public class InterfaceModule extends Module { public BooleanSetting fontShadow = new BooleanSetting("FontShadow", true, () -> betterFont.getValue()); public BooleanSetting bg = new BooleanSetting("Background", true); public ColorSetting backgroundColor = new ColorSetting("BackgroundColor", new Color(0, 0, 0, 0), () -> bg.getValue()); + public NumberSetting spacing = new NumberSetting("Spacing",0,0,3,1); + public InterfaceModule(String name, Category category) { super(name, category); From afe03c9572ec77b6ac0a3ae91b929b19f6591c16 Mon Sep 17 00:00:00 2001 From: TeAnLi Date: Thu, 17 Jul 2025 03:00:31 +0800 Subject: [PATCH 109/193] feat(KeyStrokes): fix excessive rounded setting and add spacing setting --- .../features/impl/interfaces/Keystrokes.java | 3 +- .../ui/custom/impl/KeystrokesComponent.java | 31 ++++++++++++++++--- 2 files changed, 29 insertions(+), 5 deletions(-) diff --git a/shared/java/top/fpsmaster/features/impl/interfaces/Keystrokes.java b/shared/java/top/fpsmaster/features/impl/interfaces/Keystrokes.java index 2a12adc8..9e15b306 100644 --- a/shared/java/top/fpsmaster/features/impl/interfaces/Keystrokes.java +++ b/shared/java/top/fpsmaster/features/impl/interfaces/Keystrokes.java @@ -3,6 +3,7 @@ import top.fpsmaster.features.impl.InterfaceModule; import top.fpsmaster.features.manager.Category; import top.fpsmaster.features.settings.impl.ColorSetting; +import top.fpsmaster.features.settings.impl.NumberSetting; import java.awt.*; @@ -11,6 +12,6 @@ public class Keystrokes extends InterfaceModule { public Keystrokes() { super("Keystrokes", Category.Interface); - addSettings(rounded, backgroundColor, fontShadow, betterFont, pressedColor, bg, rounded, roundRadius); + addSettings(fontShadow, betterFont, pressedColor, spacing, bg, backgroundColor, rounded, roundRadius); } } \ No newline at end of file diff --git a/shared/java/top/fpsmaster/ui/custom/impl/KeystrokesComponent.java b/shared/java/top/fpsmaster/ui/custom/impl/KeystrokesComponent.java index dadead51..3eb17bbe 100644 --- a/shared/java/top/fpsmaster/ui/custom/impl/KeystrokesComponent.java +++ b/shared/java/top/fpsmaster/ui/custom/impl/KeystrokesComponent.java @@ -29,6 +29,25 @@ public KeystrokesComponent() { public void draw(float x, float y) { super.draw(x, y); for (Key key : keys) { + switch (key.keyCode) { + case Keyboard.KEY_W: + key.yOffset = key.defaultYOffset - mod.spacing.getValue().intValue(); + break; + case Keyboard.KEY_A: + key.xOffset = key.defaultXOffset - mod.spacing.getValue().intValue(); + break; + case Keyboard.KEY_D: + key.xOffset = key.defaultXOffset + mod.spacing.getValue().intValue(); + break; + case -1: + key.xOffset = key.defaultXOffset - mod.spacing.getValue().intValue(); + key.yOffset = key.defaultYOffset + mod.spacing.getValue().intValue(); + break; + case -2: + key.xOffset = key.defaultXOffset + mod.spacing.getValue().intValue(); + key.yOffset = key.defaultYOffset + mod.spacing.getValue().intValue(); + break; + } key.render(x, y, 0f, mod.backgroundColor.getColor(), Keystrokes.pressedColor.getColor()); } width = 60f; @@ -38,16 +57,20 @@ public void draw(float x, float y) { public class Key { private final String name; private final int keyCode; - private final int xOffset; - private final int yOffset; + private final int defaultXOffset; + private final int defaultYOffset; + private int xOffset; + private int yOffset; private final ColorAnimation color; public Key(String name, int keyCode, int xOffset, int yOffset) { this.name = name; this.keyCode = keyCode; - this.xOffset = xOffset; - this.yOffset = yOffset; + this.defaultXOffset = xOffset; + this.defaultYOffset = yOffset; this.color = new ColorAnimation(); + this.xOffset = defaultXOffset; + this.yOffset = defaultYOffset; } public void render(float x, float y, float speed, Color color, Color color1) { From 2d2986f4e0763592abc10a08082cea9475956a18 Mon Sep 17 00:00:00 2001 From: TeAnLi Date: Thu, 17 Jul 2025 03:02:01 +0800 Subject: [PATCH 110/193] feat:add keystroke spacing language --- shared/resources/assets/minecraft/client/lang/en_us.lang | 1 + shared/resources/assets/minecraft/client/lang/zh_cn.lang | 1 + 2 files changed, 2 insertions(+) diff --git a/shared/resources/assets/minecraft/client/lang/en_us.lang b/shared/resources/assets/minecraft/client/lang/en_us.lang index 8516e25a..4406714a 100644 --- a/shared/resources/assets/minecraft/client/lang/en_us.lang +++ b/shared/resources/assets/minecraft/client/lang/en_us.lang @@ -113,6 +113,7 @@ keystrokes.fontshadow=Font Shadow keystrokes.betterfont=Clean Font keystrokes.roundradius=Corner Radius keystrokes.background=Show Background +keystrokes.spacing=Spacing potiondisplay=Potion HUD potiondisplay.desc=Displays active potion effects diff --git a/shared/resources/assets/minecraft/client/lang/zh_cn.lang b/shared/resources/assets/minecraft/client/lang/zh_cn.lang index ad3d793a..5b66acb9 100644 --- a/shared/resources/assets/minecraft/client/lang/zh_cn.lang +++ b/shared/resources/assets/minecraft/client/lang/zh_cn.lang @@ -113,6 +113,7 @@ keystrokes.fontshadow=字体阴影 keystrokes.betterfont=更好的字体 keystrokes.roundradius=圆角半径 keystrokes.background=背景 +keystrokes.spacing=间距 potiondisplay=药水显示 potiondisplay.desc=显示玩家的药水效果 From 177e46104ac9b1bdd5196dde74a51e95abbb9d20 Mon Sep 17 00:00:00 2001 From: SuperSkidder Date: Thu, 17 Jul 2025 09:13:07 +0800 Subject: [PATCH 111/193] fix: build --- v1.8.9/build.gradle.kts | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/v1.8.9/build.gradle.kts b/v1.8.9/build.gradle.kts index 7d42bcba..6273f558 100644 --- a/v1.8.9/build.gradle.kts +++ b/v1.8.9/build.gradle.kts @@ -117,8 +117,13 @@ dependencies { implementation("javazoom:jlayer:1.0.1") // https://mvnrepository.com/artifact/net.sourceforge.jtransforms/jtransforms implementation("net.sourceforge.jtransforms:jtransforms:2.4.0") + shadowImpl("net.sourceforge.jtransforms:jtransforms:2.4.0") { + isTransitive = true + } implementation("com.github.FPSMasterTeam:JLuaParser:master-SNAPSHOT") - + shadowImpl("com.github.FPSMasterTeam:JLuaParser:master-SNAPSHOT") { + isTransitive = true + } } // Tasks: From 813db86dd711e491b8007cbe1da672bfa877094a Mon Sep 17 00:00:00 2001 From: SuperSkidder Date: Thu, 17 Jul 2025 09:20:47 +0800 Subject: [PATCH 112/193] fix: music player search --- shared/java/top/fpsmaster/ui/click/music/MusicPanel.java | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/shared/java/top/fpsmaster/ui/click/music/MusicPanel.java b/shared/java/top/fpsmaster/ui/click/music/MusicPanel.java index dd9fc6b5..a7829f63 100644 --- a/shared/java/top/fpsmaster/ui/click/music/MusicPanel.java +++ b/shared/java/top/fpsmaster/ui/click/music/MusicPanel.java @@ -34,11 +34,14 @@ public class MusicPanel { private static Thread searchThread = null; private static float playProgress = 0f; -// private static final SearchBox inputBox = new SearchBox(FPSMaster.i18n.get("music.search"), () -> { + // private static final SearchBox inputBox = new SearchBox(FPSMaster.i18n.get("music.search"), () -> { // searchThread = new Thread(MusicPanel::run); // searchThread.start(); // }); - private static final TextField inputBox = new TextField(FPSMaster.fontManager.s16, FPSMaster.i18n.get("music.search"), new Color(40,40,40, 180).getRGB(), -1, 100); + private static final TextField inputBox = new TextField(FPSMaster.fontManager.s16, FPSMaster.i18n.get("music.search"), new Color(40, 40, 40, 180).getRGB(), -1, 100, () -> { + searchThread = new Thread(MusicPanel::run); + searchThread.start(); + }); private static final String[] pages = {"music.name", "music.list", "music.daily"}; private static int curSearch = 0; @@ -247,7 +250,7 @@ public static void draw(float x, float y, float width, float height, int mouseX, for (String page : pages) { pagesWidth += FPSMaster.fontManager.s16.getStringWidth(FPSMaster.i18n.get(page)) + 10; } - Render2DUtils.drawOptimizedRoundedRect(x + 90, y + 8, pagesWidth, 16f, new Color(50, 50, 50,100).getRGB()); + Render2DUtils.drawOptimizedRoundedRect(x + 90, y + 8, pagesWidth, 16f, new Color(50, 50, 50, 100).getRGB()); for (String page : pages) { int stringWidth = FPSMaster.fontManager.s16.getStringWidth(FPSMaster.i18n.get(page)); if (page.equals(pages[curSearch])) { From 30295a9b6fe0a7963fdf208688e88609e7fe203d Mon Sep 17 00:00:00 2001 From: SuperSkidder Date: Thu, 17 Jul 2025 09:31:57 +0800 Subject: [PATCH 113/193] change: add some error messages --- .../top/fpsmaster/event/ReflectHandler.java | 3 + .../fpsmaster/features/manager/Module.java | 2 + .../fpsmaster/modules/music/JLayerHelper.java | 3 + .../netease/deserialize/MusicWrapper.java | 8 +- shared/java/top/fpsmaster/ui/Compass.java | 164 +++++++++--------- .../top/fpsmaster/utils/awt/AWTUtils.java | 2 + .../top/fpsmaster/utils/os/FileUtils.java | 1 + .../fpsmaster/utils/render/shader/Shader.java | 4 +- 8 files changed, 98 insertions(+), 89 deletions(-) diff --git a/shared/java/top/fpsmaster/event/ReflectHandler.java b/shared/java/top/fpsmaster/event/ReflectHandler.java index 1c97cecf..4d98c826 100644 --- a/shared/java/top/fpsmaster/event/ReflectHandler.java +++ b/shared/java/top/fpsmaster/event/ReflectHandler.java @@ -1,5 +1,7 @@ package top.fpsmaster.event; +import top.fpsmaster.modules.logger.ClientLogger; + import java.lang.reflect.Method; public class ReflectHandler extends Handler { @@ -12,6 +14,7 @@ public void invoke(Event event) { try { method.invoke(listener, event); } catch (Exception e) { + ClientLogger.error("Error when invoking event " + listener.getClass().getSimpleName() + " -> " + method.getName()); e.printStackTrace(); } } diff --git a/shared/java/top/fpsmaster/features/manager/Module.java b/shared/java/top/fpsmaster/features/manager/Module.java index d09014d1..a3667cd8 100644 --- a/shared/java/top/fpsmaster/features/manager/Module.java +++ b/shared/java/top/fpsmaster/features/manager/Module.java @@ -6,6 +6,7 @@ import top.fpsmaster.features.settings.Setting; import top.fpsmaster.features.settings.impl.*; import top.fpsmaster.interfaces.ProviderManager; +import top.fpsmaster.modules.logger.ClientLogger; import top.fpsmaster.ui.notification.NotificationManager; import java.util.LinkedList; @@ -86,6 +87,7 @@ public void set(boolean state) { } } } catch (Exception e) { + ClientLogger.error("An error occurred while toggling module: " + this.name); e.printStackTrace(); } } diff --git a/shared/java/top/fpsmaster/modules/music/JLayerHelper.java b/shared/java/top/fpsmaster/modules/music/JLayerHelper.java index 3bf996e0..387ff97c 100644 --- a/shared/java/top/fpsmaster/modules/music/JLayerHelper.java +++ b/shared/java/top/fpsmaster/modules/music/JLayerHelper.java @@ -1,8 +1,10 @@ package top.fpsmaster.modules.music; +import com.sun.security.ntlm.Client; import edu.emory.mathcs.jtransforms.fft.DoubleFFT_1D; import javazoom.jl.converter.Converter; import javazoom.jl.decoder.JavaLayerException; +import top.fpsmaster.modules.logger.ClientLogger; import javax.sound.sampled.*; import java.io.File; @@ -36,6 +38,7 @@ public static void playWAV(String wavFile) throws IOException, LineUnavailableEx clip.open(aud); clip.start(); } catch (UnsupportedAudioFileException e) { + ClientLogger.error("Unsupported audio file: " + wavFile); e.printStackTrace(); } } diff --git a/shared/java/top/fpsmaster/modules/music/netease/deserialize/MusicWrapper.java b/shared/java/top/fpsmaster/modules/music/netease/deserialize/MusicWrapper.java index c10a3669..31a953d6 100644 --- a/shared/java/top/fpsmaster/modules/music/netease/deserialize/MusicWrapper.java +++ b/shared/java/top/fpsmaster/modules/music/netease/deserialize/MusicWrapper.java @@ -11,6 +11,7 @@ import top.fpsmaster.modules.music.Word; import top.fpsmaster.modules.music.netease.Music; import top.fpsmaster.modules.music.netease.NeteaseApi; +import top.fpsmaster.utils.Utility; import java.net.URLEncoder; import java.util.Iterator; @@ -181,16 +182,15 @@ public static PlayList searchSongs(String keywords) { long id1 = songObject.get("id").getAsLong(); String name = songObject.get("name").getAsString(); StringBuilder artists = new StringBuilder(); - Iterator artistIterator = songObject.getAsJsonArray("ar").iterator(); - while (artistIterator.hasNext()) { - artists.append(artistIterator.next().getAsJsonObject().get("name").getAsString()).append(" "); + for (JsonElement jsonElement : songObject.getAsJsonArray("ar")) { + artists.append(jsonElement.getAsJsonObject().get("name").getAsString()).append(" "); } String picUrl = songObject.getAsJsonObject("al").get("picUrl").getAsString(); playList.add(new Music(id1, name, artists.toString(), picUrl)); } return playList; } catch (Exception e) { - e.printStackTrace(); + Utility.sendClientNotify("fetch music list failed"); return new PlayList(); } } diff --git a/shared/java/top/fpsmaster/ui/Compass.java b/shared/java/top/fpsmaster/ui/Compass.java index bc1a5646..95742bc0 100644 --- a/shared/java/top/fpsmaster/ui/Compass.java +++ b/shared/java/top/fpsmaster/ui/Compass.java @@ -64,103 +64,99 @@ public void draw(ScaledResolution sr) { GL11.glPushMatrix(); GL11.glEnable(3089); int scaleFactor = Render2DUtils.fixScale(); - Render2DUtils.doGlScissor(sr.getScaledWidth() / 2f - 100, 25, 200, 25,scaleFactor); - try { - for (Degree d : degrees) { - float location = center + (count * 30) - yaaahhrewindTime; - float completeLocation = d.type == 1 ? (location - FPSMaster.fontManager.s28.getStringWidth(d.text) / 2f) - : d.type == 2 ? (location - FPSMaster.fontManager.s28.getStringWidth(d.text) / 2f) - : (location - FPSMaster.fontManager.s22.getStringWidth(d.text) / 2f); - - int opacity = opacity(sr, completeLocation); - - if (d.type == 1 && opacity != 16777215) { - GlStateManager.color(1, 1, 1, 1); - FPSMaster.fontManager.s28.drawString(d.text, completeLocation, -75 + 100, opacity(sr, completeLocation)); - } - - if (d.type == 2 && opacity != 16777215) { - GlStateManager.color(1, 1, 1, 1); - Gui.drawRect((int) (location - 0.5), -75 + 100 + 4, (int) (location + 0.5), -75 + 105 + 4, - opacity(sr, completeLocation)); - GlStateManager.color(1, 1, 1, 1); - FPSMaster.fontManager.s14.drawString(d.text, completeLocation, -75 + 105 + 3.5f + 4, opacity(sr, completeLocation)); - } - - if (d.type == 3 && opacity != 16777215) { - GlStateManager.color(1, 1, 1, 1); - FPSMaster.fontManager.s22.drawString(d.text, completeLocation, - -75 + 100 + FPSMaster.fontManager.s28.getHeight() / 2 - FPSMaster.fontManager.s22.getHeight() / 2, - opacity(sr, completeLocation)); - } - - count++; + Render2DUtils.doGlScissor(sr.getScaledWidth() / 2f - 100, 25, 200, 25, scaleFactor); + for (Degree d : degrees) { + float location = center + (count * 30) - yaaahhrewindTime; + float completeLocation = d.type == 1 ? (location - FPSMaster.fontManager.s28.getStringWidth(d.text) / 2f) + : d.type == 2 ? (location - FPSMaster.fontManager.s28.getStringWidth(d.text) / 2f) + : (location - FPSMaster.fontManager.s22.getStringWidth(d.text) / 2f); + + int opacity = opacity(sr, completeLocation); + + if (d.type == 1 && opacity != 16777215) { + GlStateManager.color(1, 1, 1, 1); + FPSMaster.fontManager.s28.drawString(d.text, completeLocation, -75 + 100, opacity(sr, completeLocation)); } - for (Degree d : degrees) { + if (d.type == 2 && opacity != 16777215) { + GlStateManager.color(1, 1, 1, 1); + Gui.drawRect((int) (location - 0.5), -75 + 100 + 4, (int) (location + 0.5), -75 + 105 + 4, + opacity(sr, completeLocation)); + GlStateManager.color(1, 1, 1, 1); + FPSMaster.fontManager.s14.drawString(d.text, completeLocation, -75 + 105 + 3.5f + 4, opacity(sr, completeLocation)); + } + + if (d.type == 3 && opacity != 16777215) { + GlStateManager.color(1, 1, 1, 1); + FPSMaster.fontManager.s22.drawString(d.text, completeLocation, + -75 + 100 + FPSMaster.fontManager.s28.getHeight() / 2 - FPSMaster.fontManager.s22.getHeight() / 2, + opacity(sr, completeLocation)); + } + + count++; + } + + for (Degree d : degrees) { + + float location = center + (count * 30) - yaaahhrewindTime; + float completeLocation = d.type == 1 ? (location - FPSMaster.fontManager.s28.getStringWidth(d.text) / 2f) + : d.type == 2 ? (location - FPSMaster.fontManager.s14.getStringWidth(d.text) / 2f) + : (location - FPSMaster.fontManager.s22.getStringWidth(d.text) / 2f); + - float location = center + (count * 30) - yaaahhrewindTime; - float completeLocation = d.type == 1 ? (location - FPSMaster.fontManager.s28.getStringWidth(d.text) / 2f) - : d.type == 2 ? (location - FPSMaster.fontManager.s14.getStringWidth(d.text) / 2f) - : (location - FPSMaster.fontManager.s22.getStringWidth(d.text) / 2f); + if (d.type == 1) { + GlStateManager.color(1, 1, 1, 1); + FPSMaster.fontManager.s28.drawString(d.text, completeLocation, -75 + 100, opacity(sr, completeLocation)); + } + + if (d.type == 2) { + GlStateManager.color(1, 1, 1, 1); + Gui.drawRect((int) (location - 0.5), -75 + 100 + 4, (int) (location + 0.5), -75 + 105 + 4, + opacity(sr, completeLocation)); + GlStateManager.color(1, 1, 1, 1); + FPSMaster.fontManager.s14.drawString(d.text, completeLocation, -75 + 105 + 3.5f + 4, opacity(sr, completeLocation)); + } + if (d.type == 3) { + GlStateManager.color(1, 1, 1, 1); + FPSMaster.fontManager.s22.drawString(d.text, completeLocation, + -75 + 100 + FPSMaster.fontManager.s28.getHeight() / 2 - FPSMaster.fontManager.s22.getHeight() / 2, + opacity(sr, completeLocation)); + } - if (d.type == 1) { - GlStateManager.color(1, 1, 1, 1); - FPSMaster.fontManager.s28.drawString(d.text, completeLocation, -75 + 100, opacity(sr, completeLocation)); - } + count++; + } + for (Degree d : degrees) { - if (d.type == 2) { - GlStateManager.color(1, 1, 1, 1); - Gui.drawRect((int) (location - 0.5), -75 + 100 + 4, (int) (location + 0.5), -75 + 105 + 4, - opacity(sr, completeLocation)); - GlStateManager.color(1, 1, 1, 1); - FPSMaster.fontManager.s14.drawString(d.text, completeLocation, -75 + 105 + 3.5f + 4, opacity(sr, completeLocation)); - } + float location = center + (count * 30) - yaaahhrewindTime; + float completeLocation = d.type == 1 ? (location - FPSMaster.fontManager.s28.getStringWidth(d.text) / 2f) + : d.type == 2 ? (location - FPSMaster.fontManager.s14.getStringWidth(d.text) / 2f) + : (location - FPSMaster.fontManager.s22.getStringWidth(d.text) / 2f); - if (d.type == 3) { - GlStateManager.color(1, 1, 1, 1); - FPSMaster.fontManager.s22.drawString(d.text, completeLocation, - -75 + 100 + FPSMaster.fontManager.s28.getHeight() / 2 - FPSMaster.fontManager.s22.getHeight() / 2, - opacity(sr, completeLocation)); - } + if (d.type == 1) { + GlStateManager.color(1, 1, 1, 1); + FPSMaster.fontManager.s28.drawString(d.text, completeLocation, -75 + 100, opacity(sr, completeLocation)); + } - count++; + if (d.type == 2) { + GlStateManager.color(1, 1, 1, 1); + Gui.drawRect((int) (location - 0.5), -75 + 100 + 4, (int) (location + 0.5), -75 + 105 + 4, + opacity(sr, completeLocation)); + GlStateManager.color(1, 1, 1, 1); + FPSMaster.fontManager.s14.drawString(d.text, completeLocation, -75 + 105 + 3.5f + 4, opacity(sr, completeLocation)); } - for (Degree d : degrees) { - - float location = center + (count * 30) - yaaahhrewindTime; - float completeLocation = d.type == 1 ? (location - FPSMaster.fontManager.s28.getStringWidth(d.text) / 2f) - : d.type == 2 ? (location - FPSMaster.fontManager.s14.getStringWidth(d.text) / 2f) - : (location - FPSMaster.fontManager.s22.getStringWidth(d.text) / 2f); - - if (d.type == 1) { - GlStateManager.color(1, 1, 1, 1); - FPSMaster.fontManager.s28.drawString(d.text, completeLocation, -75 + 100, opacity(sr, completeLocation)); - } - - if (d.type == 2) { - GlStateManager.color(1, 1, 1, 1); - Gui.drawRect((int) (location - 0.5), -75 + 100 + 4, (int) (location + 0.5), -75 + 105 + 4, - opacity(sr, completeLocation)); - GlStateManager.color(1, 1, 1, 1); - FPSMaster.fontManager.s14.drawString(d.text, completeLocation, -75 + 105 + 3.5f + 4, opacity(sr, completeLocation)); - } - - if (d.type == 3) { - GlStateManager.color(1, 1, 1, 1); - FPSMaster.fontManager.s22.drawString(d.text, completeLocation, - -75 + 100 + FPSMaster.fontManager.s28.getHeight() / 2 - FPSMaster.fontManager.s22.getHeight() / 2, - opacity(sr, completeLocation)); - } - - count++; + + if (d.type == 3) { + GlStateManager.color(1, 1, 1, 1); + FPSMaster.fontManager.s22.drawString(d.text, completeLocation, + -75 + 100 + FPSMaster.fontManager.s28.getHeight() / 2 - FPSMaster.fontManager.s22.getHeight() / 2, + opacity(sr, completeLocation)); } - } catch (Exception e){ - e.printStackTrace(); + count++; } + GL11.glDisable(3089); GL11.glPopMatrix(); } diff --git a/shared/java/top/fpsmaster/utils/awt/AWTUtils.java b/shared/java/top/fpsmaster/utils/awt/AWTUtils.java index 93ade31f..7dda72d7 100644 --- a/shared/java/top/fpsmaster/utils/awt/AWTUtils.java +++ b/shared/java/top/fpsmaster/utils/awt/AWTUtils.java @@ -3,6 +3,7 @@ import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.texture.DynamicTexture; import net.minecraft.util.ResourceLocation; +import top.fpsmaster.modules.logger.ClientLogger; import java.awt.*; import java.awt.geom.RoundRectangle2D; @@ -44,6 +45,7 @@ public static ResourceLocation generateRoundImage(int width, int height, int rad return mc.getTextureManager() .getDynamicTextureLocation(r + "_full", new DynamicTexture(bufferedImage)); } catch (Exception e) { + ClientLogger.error("An error occurred while generating round texture: " + r); e.printStackTrace(); return null; } diff --git a/shared/java/top/fpsmaster/utils/os/FileUtils.java b/shared/java/top/fpsmaster/utils/os/FileUtils.java index c325bca2..01fb3fac 100644 --- a/shared/java/top/fpsmaster/utils/os/FileUtils.java +++ b/shared/java/top/fpsmaster/utils/os/FileUtils.java @@ -136,6 +136,7 @@ public static void release(String file) { } } } catch (IOException e) { + ClientLogger.error("An error occurred while releasing language file: " + file + ".lang"); e.printStackTrace(); } } diff --git a/shared/java/top/fpsmaster/utils/render/shader/Shader.java b/shared/java/top/fpsmaster/utils/render/shader/Shader.java index 5a16d7c6..f0b4f9e6 100644 --- a/shared/java/top/fpsmaster/utils/render/shader/Shader.java +++ b/shared/java/top/fpsmaster/utils/render/shader/Shader.java @@ -2,6 +2,7 @@ import org.apache.commons.io.IOUtils; import org.lwjgl.opengl.*; +import top.fpsmaster.modules.logger.ClientLogger; import top.fpsmaster.utils.Utility; import java.io.InputStream; @@ -25,7 +26,8 @@ public Shader(final String shader) { IOUtils.closeQuietly(vertexStream); fragmentShaderID = createShader(shader, ARBFragmentShader.GL_FRAGMENT_SHADER_ARB); - } catch (final Exception e) { + } catch (Exception e) { + ClientLogger.error("An error occurred while loading shader: " + shader); e.printStackTrace(); return; } From ba622122fe4dbc4670bb8e0ad437744303dd36af Mon Sep 17 00:00:00 2001 From: SuperSkidder Date: Thu, 17 Jul 2025 09:37:12 +0800 Subject: [PATCH 114/193] fix: compile bug --- shared/java/top/fpsmaster/modules/music/JLayerHelper.java | 1 - 1 file changed, 1 deletion(-) diff --git a/shared/java/top/fpsmaster/modules/music/JLayerHelper.java b/shared/java/top/fpsmaster/modules/music/JLayerHelper.java index 387ff97c..09162d27 100644 --- a/shared/java/top/fpsmaster/modules/music/JLayerHelper.java +++ b/shared/java/top/fpsmaster/modules/music/JLayerHelper.java @@ -1,6 +1,5 @@ package top.fpsmaster.modules.music; -import com.sun.security.ntlm.Client; import edu.emory.mathcs.jtransforms.fft.DoubleFFT_1D; import javazoom.jl.converter.Converter; import javazoom.jl.decoder.JavaLayerException; From 43492a9686b3be4fc6cbd37e3bf0c906bebf03b3 Mon Sep 17 00:00:00 2001 From: SuperSkidder Date: Thu, 17 Jul 2025 09:41:42 +0800 Subject: [PATCH 115/193] fix: draw client logo before tags that may not be nametag --- shared/java/top/fpsmaster/features/impl/utility/LevelTag.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/shared/java/top/fpsmaster/features/impl/utility/LevelTag.java b/shared/java/top/fpsmaster/features/impl/utility/LevelTag.java index 80b150d3..995cdaf7 100644 --- a/shared/java/top/fpsmaster/features/impl/utility/LevelTag.java +++ b/shared/java/top/fpsmaster/features/impl/utility/LevelTag.java @@ -85,7 +85,7 @@ else if (mc.gameSettings.thirdPersonView == 1) i = -10; } - boolean isMate = entityIn == mc.thePlayer; + boolean isMate = (entityIn == mc.thePlayer) && str.contains(entityIn.getName()); int j = fontRenderer.getStringWidth(str) / 2; if (isMate) { From 75af8404e3191b3961560589e1cde6e56fd242e8 Mon Sep 17 00:00:00 2001 From: SuperSkidder Date: Thu, 17 Jul 2025 12:46:12 +0800 Subject: [PATCH 116/193] feat: add clientmate display --- .../fpsmaster/features/GlobalListener.java | 27 ++++++++++++++----- .../features/impl/utility/LevelTag.java | 5 +++- .../modules/client/ClientUsersManager.java | 8 ++++++ 3 files changed, 32 insertions(+), 8 deletions(-) diff --git a/shared/java/top/fpsmaster/features/GlobalListener.java b/shared/java/top/fpsmaster/features/GlobalListener.java index 6a2cb297..918030c7 100644 --- a/shared/java/top/fpsmaster/features/GlobalListener.java +++ b/shared/java/top/fpsmaster/features/GlobalListener.java @@ -2,6 +2,7 @@ import net.minecraft.client.Minecraft; import net.minecraft.client.gui.ScaledResolution; +import net.minecraft.client.network.NetworkPlayerInfo; import org.lwjgl.input.Mouse; import top.fpsmaster.FPSMaster; import top.fpsmaster.event.EventDispatcher; @@ -9,6 +10,7 @@ import top.fpsmaster.event.events.*; import top.fpsmaster.features.impl.interfaces.ClientSettings; import top.fpsmaster.interfaces.ProviderManager; +import top.fpsmaster.modules.account.AccountManager; import top.fpsmaster.modules.music.MusicPlayer; import top.fpsmaster.ui.notification.NotificationManager; import top.fpsmaster.utils.Utility; @@ -18,6 +20,9 @@ import top.fpsmaster.websocket.client.WsClient; import java.net.URISyntaxException; +import java.util.ArrayList; + +import static top.fpsmaster.utils.Utility.mc; public class GlobalListener { @@ -45,16 +50,24 @@ public void onChatSend(EventSendChatMessage e) { PlayerInformation playerInformation = null; + ArrayList playerInfos = new ArrayList<>(); + @Subscribe public void onTick(EventTick e) throws URISyntaxException { if (musicSwitchTimer.delay(500)) { -// if (playerInformation == null) { -// playerInformation = new PlayerInformation(ProviderManager.mcProvider.getPlayer().getName(), ProviderManager.mcProvider.getPlayer().getUniqueID().toString(), ProviderManager.mcProvider.getServerAddress(), "", AccountManager.skin); -// FPSMaster.INSTANCE.wsClient.sendInformation(AccountManager.skin, "", ProviderManager.mcProvider.getPlayer().getName(), ProviderManager.mcProvider.getServerAddress()); -// } else if (!playerInformation.serverAddress.equals(ProviderManager.mcProvider.getServerAddress()) || !playerInformation.name.equals(ProviderManager.mcProvider.getPlayer().getName()) || !playerInformation.skin.equals(AccountManager.skin) || !playerInformation.uuid.equals(ProviderManager.mcProvider.getPlayer().getUniqueID().toString())) { -// playerInformation = new PlayerInformation(ProviderManager.mcProvider.getPlayer().getName(), ProviderManager.mcProvider.getPlayer().getUniqueID().toString(), ProviderManager.mcProvider.getServerAddress(), "", AccountManager.skin); -// FPSMaster.INSTANCE.wsClient.sendInformation(AccountManager.skin, "", ProviderManager.mcProvider.getPlayer().getName(), ProviderManager.mcProvider.getServerAddress()); -// } + for (NetworkPlayerInfo networkPlayerInfo : mc.getNetHandler().getPlayerInfoMap()) { + if (!playerInfos.contains(networkPlayerInfo)){ + FPSMaster.INSTANCE.wsClient.fetchPlayer(networkPlayerInfo.getGameProfile().getId().toString(), networkPlayerInfo.getGameProfile().getName()); + playerInfos.add(networkPlayerInfo); + } + } + if (playerInformation == null) { + playerInformation = new PlayerInformation(ProviderManager.mcProvider.getPlayer().getName(), ProviderManager.mcProvider.getPlayer().getUniqueID().toString(), ProviderManager.mcProvider.getServerAddress(), "", AccountManager.skin); + FPSMaster.INSTANCE.wsClient.sendInformation(AccountManager.skin, "", ProviderManager.mcProvider.getPlayer().getName(), ProviderManager.mcProvider.getServerAddress()); + } else if (!playerInformation.serverAddress.equals(ProviderManager.mcProvider.getServerAddress()) || !playerInformation.name.equals(ProviderManager.mcProvider.getPlayer().getName()) || !playerInformation.skin.equals(AccountManager.skin) || !playerInformation.uuid.equals(ProviderManager.mcProvider.getPlayer().getUniqueID().toString())) { + playerInformation = new PlayerInformation(ProviderManager.mcProvider.getPlayer().getName(), ProviderManager.mcProvider.getPlayer().getUniqueID().toString(), ProviderManager.mcProvider.getServerAddress(), "", AccountManager.skin); + FPSMaster.INSTANCE.wsClient.sendInformation(AccountManager.skin, "", ProviderManager.mcProvider.getPlayer().getName(), ProviderManager.mcProvider.getServerAddress()); + } FPSMaster.async.runnable(() -> { if (MusicPlayer.isPlaying && MusicPlayer.getPlayProgress() > 0.999) { diff --git a/shared/java/top/fpsmaster/features/impl/utility/LevelTag.java b/shared/java/top/fpsmaster/features/impl/utility/LevelTag.java index 995cdaf7..ec26a4ed 100644 --- a/shared/java/top/fpsmaster/features/impl/utility/LevelTag.java +++ b/shared/java/top/fpsmaster/features/impl/utility/LevelTag.java @@ -8,10 +8,12 @@ import net.minecraft.entity.Entity; import net.minecraft.util.ResourceLocation; import org.lwjgl.opengl.GL11; +import top.fpsmaster.FPSMaster; import top.fpsmaster.features.manager.Category; import top.fpsmaster.features.manager.Module; import top.fpsmaster.features.settings.impl.BooleanSetting; import top.fpsmaster.interfaces.ProviderManager; +import top.fpsmaster.modules.client.ClientUsersManager; import top.fpsmaster.utils.render.Render2DUtils; import static top.fpsmaster.utils.Utility.mc; @@ -85,7 +87,8 @@ else if (mc.gameSettings.thirdPersonView == 1) i = -10; } - boolean isMate = (entityIn == mc.thePlayer) && str.contains(entityIn.getName()); + boolean isMate = ((entityIn == mc.thePlayer) && str.contains(entityIn.getName())) || FPSMaster.clientUsersManager.isClientUser(entityIn); + int j = fontRenderer.getStringWidth(str) / 2; if (isMate) { diff --git a/shared/java/top/fpsmaster/modules/client/ClientUsersManager.java b/shared/java/top/fpsmaster/modules/client/ClientUsersManager.java index 36705061..9e515195 100644 --- a/shared/java/top/fpsmaster/modules/client/ClientUsersManager.java +++ b/shared/java/top/fpsmaster/modules/client/ClientUsersManager.java @@ -1,5 +1,6 @@ package top.fpsmaster.modules.client; +import net.minecraft.entity.Entity; import top.fpsmaster.websocket.data.message.server.SFetchPlayerPacket; import java.util.ArrayList; @@ -15,4 +16,11 @@ public void addFromFetch(SFetchPlayerPacket packet) { } users.add(clientUser); } + + public boolean isClientUser(Entity entityIn) { + for (ClientUser user : users) + if (user.uuid.equals(entityIn.getUniqueID().toString())) + return true; + return false; + } } From 80b9aa6f4b826a48b92299a1104007685f0e903c Mon Sep 17 00:00:00 2001 From: SuperSkidder Date: Thu, 17 Jul 2025 14:46:50 +0800 Subject: [PATCH 117/193] add: performance values registry --- .../top/fpsmaster/features/impl/optimizes/Performance.java | 2 +- shared/resources/assets/minecraft/client/lang/zh_cn.lang | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/shared/java/top/fpsmaster/features/impl/optimizes/Performance.java b/shared/java/top/fpsmaster/features/impl/optimizes/Performance.java index 28f13535..98a46f06 100644 --- a/shared/java/top/fpsmaster/features/impl/optimizes/Performance.java +++ b/shared/java/top/fpsmaster/features/impl/optimizes/Performance.java @@ -30,7 +30,7 @@ public class Performance extends Module { public Performance() { super("Performance", Category.OPTIMIZE); - addSettings(ignoreStands, entitiesOptimize, fastLoad, entityLimit, fpsLimit, particlesLimit, fontOptimize, staticParticleColor,limitChunks,chunkUpdateLimit); + addSettings(ignoreStands, entitiesOptimize, fastLoad, batchModelRendering, lowAnimationTick, entityLimit, fpsLimit, particlesLimit, fontOptimize, staticParticleColor,limitChunks,chunkUpdateLimit); } diff --git a/shared/resources/assets/minecraft/client/lang/zh_cn.lang b/shared/resources/assets/minecraft/client/lang/zh_cn.lang index 5b66acb9..12724f8a 100644 --- a/shared/resources/assets/minecraft/client/lang/zh_cn.lang +++ b/shared/resources/assets/minecraft/client/lang/zh_cn.lang @@ -176,7 +176,8 @@ performance.fontoptimize=字体优化 performance.staticparticlecolor=静态粒子颜色 performance.limitchunks=限制区块加载 performance.chunkupdatelimit=区块更新限制 - +performance.batchmodelrendering=渲染批处理 +performance.lowanimationtick=低动画帧率 fullbright=保持亮度 fullbright.desc=保持视野明亮 From eabd509a41f2550570cd15a4d69b15ad2edaae8e Mon Sep 17 00:00:00 2001 From: SuperSkidder Date: Thu, 17 Jul 2025 15:37:40 +0800 Subject: [PATCH 118/193] feat: clientmates --- docs/tasks.md | 7 ++++ .../fpsmaster/features/GlobalListener.java | 33 ++++++++++--------- .../features/command/impl/IRCChat.java | 7 +++- 3 files changed, 30 insertions(+), 17 deletions(-) diff --git a/docs/tasks.md b/docs/tasks.md index 2a19ffc3..dc960ff6 100644 --- a/docs/tasks.md +++ b/docs/tasks.md @@ -19,6 +19,13 @@ - [ ] 添加界面自动对齐 - [ ] 添加翻译功能 - [ ] Waypoint +- [ ] 攻击音效 +- [ ] 更加自定义话的组件(大小调整、按键显示) +- [ ] 修改notification,添加更多样式和自定义 +- [ ] RawInput兼容和优化 +- [ ] FPS Hurt Cam +- [ ] World Color + ## 长期改进任务 diff --git a/shared/java/top/fpsmaster/features/GlobalListener.java b/shared/java/top/fpsmaster/features/GlobalListener.java index 918030c7..e8598ecd 100644 --- a/shared/java/top/fpsmaster/features/GlobalListener.java +++ b/shared/java/top/fpsmaster/features/GlobalListener.java @@ -55,26 +55,12 @@ public void onChatSend(EventSendChatMessage e) { @Subscribe public void onTick(EventTick e) throws URISyntaxException { if (musicSwitchTimer.delay(500)) { - for (NetworkPlayerInfo networkPlayerInfo : mc.getNetHandler().getPlayerInfoMap()) { - if (!playerInfos.contains(networkPlayerInfo)){ - FPSMaster.INSTANCE.wsClient.fetchPlayer(networkPlayerInfo.getGameProfile().getId().toString(), networkPlayerInfo.getGameProfile().getName()); - playerInfos.add(networkPlayerInfo); - } - } - if (playerInformation == null) { - playerInformation = new PlayerInformation(ProviderManager.mcProvider.getPlayer().getName(), ProviderManager.mcProvider.getPlayer().getUniqueID().toString(), ProviderManager.mcProvider.getServerAddress(), "", AccountManager.skin); - FPSMaster.INSTANCE.wsClient.sendInformation(AccountManager.skin, "", ProviderManager.mcProvider.getPlayer().getName(), ProviderManager.mcProvider.getServerAddress()); - } else if (!playerInformation.serverAddress.equals(ProviderManager.mcProvider.getServerAddress()) || !playerInformation.name.equals(ProviderManager.mcProvider.getPlayer().getName()) || !playerInformation.skin.equals(AccountManager.skin) || !playerInformation.uuid.equals(ProviderManager.mcProvider.getPlayer().getUniqueID().toString())) { - playerInformation = new PlayerInformation(ProviderManager.mcProvider.getPlayer().getName(), ProviderManager.mcProvider.getPlayer().getUniqueID().toString(), ProviderManager.mcProvider.getServerAddress(), "", AccountManager.skin); - FPSMaster.INSTANCE.wsClient.sendInformation(AccountManager.skin, "", ProviderManager.mcProvider.getPlayer().getName(), ProviderManager.mcProvider.getServerAddress()); - } - FPSMaster.async.runnable(() -> { if (MusicPlayer.isPlaying && MusicPlayer.getPlayProgress() > 0.999) { MusicPlayer.curPlayProgress = 0f; MusicPlayer.playList.next(); } - if (ProviderManager.mcProvider.getWorld() != null){ + if (ProviderManager.mcProvider.getWorld() != null) { Utility.flush(); } if (FPSMaster.INSTANCE.loggedIn) { @@ -89,8 +75,23 @@ public void onTick(EventTick e) throws URISyntaxException { FPSMaster.INSTANCE.wsClient.close(); FPSMaster.INSTANCE.wsClient.connect(); Utility.sendClientDebug("尝试重连"); + } else { + FPSMaster.INSTANCE.wsClient.sendPing(); } } + for (NetworkPlayerInfo networkPlayerInfo : mc.getNetHandler().getPlayerInfoMap()) { + if (!playerInfos.contains(networkPlayerInfo)) { + FPSMaster.INSTANCE.wsClient.fetchPlayer(networkPlayerInfo.getGameProfile().getId().toString(), networkPlayerInfo.getGameProfile().getName()); + playerInfos.add(networkPlayerInfo); + } + } + if (playerInformation == null) { + playerInformation = new PlayerInformation(ProviderManager.mcProvider.getPlayer().getName(), ProviderManager.mcProvider.getPlayer().getUniqueID().toString(), ProviderManager.mcProvider.getServerAddress(), "", AccountManager.skin); + FPSMaster.INSTANCE.wsClient.sendInformation(AccountManager.skin, "", ProviderManager.mcProvider.getPlayer().getName(), ProviderManager.mcProvider.getServerAddress()); + } else if (!playerInformation.serverAddress.equals(ProviderManager.mcProvider.getServerAddress()) || !playerInformation.name.equals(ProviderManager.mcProvider.getPlayer().getName()) || !playerInformation.skin.equals(AccountManager.skin) || !playerInformation.uuid.equals(ProviderManager.mcProvider.getPlayer().getUniqueID().toString())) { + playerInformation = new PlayerInformation(ProviderManager.mcProvider.getPlayer().getName(), ProviderManager.mcProvider.getPlayer().getUniqueID().toString(), ProviderManager.mcProvider.getServerAddress(), "", AccountManager.skin); + FPSMaster.INSTANCE.wsClient.sendInformation(AccountManager.skin, "", ProviderManager.mcProvider.getPlayer().getName(), ProviderManager.mcProvider.getServerAddress()); + } }); } } @@ -113,7 +114,7 @@ public void onRender(EventRender2D e) { NotificationManager.drawNotifications(); } - class PlayerInformation{ + class PlayerInformation { String name; String uuid; String serverAddress; diff --git a/shared/java/top/fpsmaster/features/command/impl/IRCChat.java b/shared/java/top/fpsmaster/features/command/impl/IRCChat.java index 5c82cadc..8b6ed037 100644 --- a/shared/java/top/fpsmaster/features/command/impl/IRCChat.java +++ b/shared/java/top/fpsmaster/features/command/impl/IRCChat.java @@ -1,5 +1,6 @@ package top.fpsmaster.features.command.impl; +import net.minecraft.client.network.NetworkPlayerInfo; import top.fpsmaster.FPSMaster; import top.fpsmaster.features.command.Command; import top.fpsmaster.features.impl.utility.IRC; @@ -7,6 +8,8 @@ import top.fpsmaster.modules.account.AccountManager; import top.fpsmaster.utils.Utility; +import static top.fpsmaster.utils.Utility.mc; + public class IRCChat extends Command { public IRCChat() { @@ -45,7 +48,9 @@ public void execute(String[] args) { } else if ("update".equals(args[0])) { FPSMaster.INSTANCE.wsClient.sendInformation(AccountManager.skin, "", ProviderManager.mcProvider.getPlayer().getName(), ProviderManager.mcProvider.getServerAddress()); } else if ("fetch".equals(args[0])) { - FPSMaster.INSTANCE.wsClient.fetchPlayer(ProviderManager.mcProvider.getPlayer().getGameProfile().getId().toString(), ProviderManager.mcProvider.getPlayer().getName()); + for (NetworkPlayerInfo networkPlayerInfo : mc.getNetHandler().getPlayerInfoMap()) { + FPSMaster.INSTANCE.wsClient.fetchPlayer(networkPlayerInfo.getGameProfile().getId().toString(), networkPlayerInfo.getGameProfile().getName()); + } } else { for (String arg : args) { if (arg.equals(args[args.length - 1])) { From fcc20aa6f6810ac9b41fcbad5fa68ca7b32c09c2 Mon Sep 17 00:00:00 2001 From: SuperSkidder Date: Thu, 17 Jul 2025 16:12:53 +0800 Subject: [PATCH 119/193] fix: wrong click through --- shared/java/top/fpsmaster/ui/click/MainPanel.java | 3 ++- shared/java/top/fpsmaster/ui/custom/Component.java | 2 ++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/shared/java/top/fpsmaster/ui/click/MainPanel.java b/shared/java/top/fpsmaster/ui/click/MainPanel.java index f3175831..95c084e1 100644 --- a/shared/java/top/fpsmaster/ui/click/MainPanel.java +++ b/shared/java/top/fpsmaster/ui/click/MainPanel.java @@ -298,7 +298,8 @@ public void onClick(int mouseX, int mouseY, int mouseButton) { // sizeDragX = x + width - mouseX; // sizeDragY = y + height - mouseY; // } - + if (!dragLock.equals("null")) + return; float my = y + 60f; for (Category c : Category.values()) { if (Render2DUtils.isHoveredWithoutScale(x, my - 8, leftWidth, 24f, mouseX, mouseY)) { diff --git a/shared/java/top/fpsmaster/ui/custom/Component.java b/shared/java/top/fpsmaster/ui/custom/Component.java index 82885ecc..f82eb3a7 100644 --- a/shared/java/top/fpsmaster/ui/custom/Component.java +++ b/shared/java/top/fpsmaster/ui/custom/Component.java @@ -110,6 +110,8 @@ public void display(int mouseX, int mouseY) { FPSMaster.componentsManager.dragLock = ""; } if (Render2DUtils.isHovered(rX, rY, scaledWidth, scaledHeight, mouseX, mouseY) || drag) { + if (!MainPanel.dragLock.equals("null")) + return; if (allowScale) { int dWheel = Mouse.getDWheel(); if (dWheel > 0) scaleUp(); From d9f3ab4592dcc001a0ba9649cad4af54526e97d4 Mon Sep 17 00:00:00 2001 From: SuperSkidder Date: Thu, 17 Jul 2025 16:26:46 +0800 Subject: [PATCH 120/193] fix: a nullptr in reach display --- .../top/fpsmaster/features/impl/interfaces/ReachDisplay.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/shared/java/top/fpsmaster/features/impl/interfaces/ReachDisplay.java b/shared/java/top/fpsmaster/features/impl/interfaces/ReachDisplay.java index e2cc5d11..4ebe9c3e 100644 --- a/shared/java/top/fpsmaster/features/impl/interfaces/ReachDisplay.java +++ b/shared/java/top/fpsmaster/features/impl/interfaces/ReachDisplay.java @@ -41,8 +41,10 @@ public void onAttack(EventAttack e) { d1 = 6.0; d0 = d1; } - if (rayTrace != null) { + if (rayTrace != null && rayTrace.hitVec != null) { d1 = rayTrace.hitVec.distanceTo(vec3d); + } else { + return; } WrapperVec3 vec3d1 = new WrapperVec3(entity.getLook(1.0f)); Vec3 vec3d2 = new WrapperVec3(vec3d).addVector(vec3d1.x() * d0, vec3d1.y() * d0, vec3d1.z() * d0); From 0e29668d90ddeca7d14f77661d7f9232e3ed1710 Mon Sep 17 00:00:00 2001 From: SuperSkidder Date: Thu, 17 Jul 2025 16:54:22 +0800 Subject: [PATCH 121/193] fix: reachdisplay accuracy problem --- .../impl/interfaces/ReachDisplay.java | 43 +------------------ 1 file changed, 2 insertions(+), 41 deletions(-) diff --git a/shared/java/top/fpsmaster/features/impl/interfaces/ReachDisplay.java b/shared/java/top/fpsmaster/features/impl/interfaces/ReachDisplay.java index 4ebe9c3e..f211ffec 100644 --- a/shared/java/top/fpsmaster/features/impl/interfaces/ReachDisplay.java +++ b/shared/java/top/fpsmaster/features/impl/interfaces/ReachDisplay.java @@ -33,50 +33,11 @@ public ReachDisplay() { public void onAttack(EventAttack e) { Entity entity = mc.getRenderViewEntity(); if (entity != null && ProviderManager.mcProvider.getWorld() != null) { - double d0 = mc.playerController.getBlockReachDistance(); - MovingObjectPosition rayTrace = entity.rayTrace(d0, ProviderManager.timerProvider.getRenderPartialTicks()); Vec3 vec3d = entity.getPositionEyes(ProviderManager.timerProvider.getRenderPartialTicks()); - double d1 = d0; - if (mc.playerController.extendedReach()) { - d1 = 6.0; - d0 = d1; - } - if (rayTrace != null && rayTrace.hitVec != null) { - d1 = rayTrace.hitVec.distanceTo(vec3d); - } else { + if (mc.objectMouseOver == null || mc.objectMouseOver.entityHit == null) return; - } - WrapperVec3 vec3d1 = new WrapperVec3(entity.getLook(1.0f)); - Vec3 vec3d2 = new WrapperVec3(vec3d).addVector(vec3d1.x() * d0, vec3d1.y() * d0, vec3d1.z() * d0); - Vec3 vec3d3 = null; - if (ProviderManager.mcProvider.getWorld() == null) - return; - List list = ProviderManager.mcProvider.getWorld().getEntitiesInAABBexcluding( - entity, - new WrapperAxisAlignedBB(entity.getEntityBoundingBox()).addCoord(vec3d1.x() * d0, vec3d1.y() * d0, vec3d1.z() * d0) - .expand(1.0, 1.0, 1.0).getAxisAlignedBB(), - Predicates.and(EntitySelectors.NOT_SPECTATING, entity1 -> entity1 != null && entity1.canBeCollidedWith()) - ); - double d2 = d1; - for (int j = 0; j < list.size(); j++) { - Entity entity1 = list.get(j); - AxisAlignedBB axisalignedbb = new WrapperAxisAlignedBB(entity1.getEntityBoundingBox()).expand(entity1.getCollisionBorderSize()); - MovingObjectPosition raytraceresult = axisalignedbb.calculateIntercept(vec3d, vec3d2); - if (axisalignedbb.isVecInside(vec3d)) { - if (d2 >= 0.0) { - vec3d3 = raytraceresult.hitVec; - d2 = 0.0; - } - } else if (raytraceresult != null) { - double d3 = vec3d.distanceTo(raytraceresult.hitVec); - if (d3 < d2 || d2 == 0.0) { - vec3d3 = raytraceresult.hitVec; - } - } - } - double distance = new WrapperVec3(vec3d).distanceTo(vec3d3); + double distance = mc.objectMouseOver.hitVec.distanceTo(vec3d); reach = Double.parseDouble(String.format("%.2f", distance)); - } } } From 61b2a647556bad566da72538da09db82fcf2aa78 Mon Sep 17 00:00:00 2001 From: SuperSkidder Date: Thu, 17 Jul 2025 22:37:42 +0800 Subject: [PATCH 122/193] fix: logo doesn't show if health is not enabled in leveltag --- .../main/java/top/fpsmaster/forge/mixin/MixinRender.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinRender.java b/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinRender.java index b3d15f89..dcc2affa 100644 --- a/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinRender.java +++ b/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinRender.java @@ -35,11 +35,11 @@ public void doRender(Entity entity, double x, double y, double z, float entityYa } - @Inject(method = "renderLivingLabel", at = @At("HEAD"), cancellable = true) protected void renderLivingLabel(Entity entityIn, String str, double x, double y, double z, int maxDistance, CallbackInfo ci) { - if (LevelTag.using && LevelTag.health.getValue()) { - LevelTag.renderHealth(entityIn, str, x, y, z, maxDistance); + if (LevelTag.using) { + if (LevelTag.health.getValue()) + LevelTag.renderHealth(entityIn, str, x, y, z, maxDistance); LevelTag.renderName(entityIn, str, x, y, z, maxDistance); ci.cancel(); } From 2b1d72379d0990648e3048e5dc14dc9cb7138b33 Mon Sep 17 00:00:00 2001 From: TeAnli <159260777+TeAnli@users.noreply.github.com> Date: Fri, 18 Jul 2025 01:02:29 +0800 Subject: [PATCH 123/193] Add lyric animation setting and more component spacing (#102) * feat: add spacing language support * feat: Add spacing setting and rendering * chore: add language and scale utility * feat: Add a scale animation to the lyrics * style: lyric finished still scale --- .../impl/interfaces/ArmorDisplay.java | 2 +- .../features/impl/interfaces/Keystrokes.java | 1 - .../impl/interfaces/LyricsDisplay.java | 4 +- .../features/impl/interfaces/ModsList.java | 2 +- .../impl/interfaces/PotionDisplay.java | 2 +- .../top/fpsmaster/modules/music/Line.java | 11 +++-- .../top/fpsmaster/ui/custom/Component.java | 8 ++-- .../ui/custom/impl/ArmorDisplayComponent.java | 8 ++-- .../ui/custom/impl/LyricsComponent.java | 45 +++++++++++++------ .../ui/custom/impl/ModsListComponent.java | 42 +++++++++-------- .../custom/impl/PotionDisplayComponent.java | 17 ++++--- .../ui/custom/impl/TargetHUDComponent.java | 1 - .../top/fpsmaster/ui/mc/ServerListEntry.java | 4 +- .../fpsmaster/utils/render/Render2DUtils.java | 9 ++++ .../assets/minecraft/client/lang/en_us.lang | 5 ++- .../assets/minecraft/client/lang/zh_cn.lang | 7 +-- 16 files changed, 107 insertions(+), 61 deletions(-) diff --git a/shared/java/top/fpsmaster/features/impl/interfaces/ArmorDisplay.java b/shared/java/top/fpsmaster/features/impl/interfaces/ArmorDisplay.java index 7d540d83..dcbbc73c 100644 --- a/shared/java/top/fpsmaster/features/impl/interfaces/ArmorDisplay.java +++ b/shared/java/top/fpsmaster/features/impl/interfaces/ArmorDisplay.java @@ -9,6 +9,6 @@ public class ArmorDisplay extends InterfaceModule { public ArmorDisplay() { super("ArmorDisplay", Category.Interface); - addSettings(rounded, backgroundColor, fontShadow, betterFont, mode, bg, rounded, roundRadius); + addSettings(rounded, backgroundColor, fontShadow, betterFont, spacing, mode, bg, rounded, roundRadius); } } \ No newline at end of file diff --git a/shared/java/top/fpsmaster/features/impl/interfaces/Keystrokes.java b/shared/java/top/fpsmaster/features/impl/interfaces/Keystrokes.java index 9e15b306..d54d9938 100644 --- a/shared/java/top/fpsmaster/features/impl/interfaces/Keystrokes.java +++ b/shared/java/top/fpsmaster/features/impl/interfaces/Keystrokes.java @@ -3,7 +3,6 @@ import top.fpsmaster.features.impl.InterfaceModule; import top.fpsmaster.features.manager.Category; import top.fpsmaster.features.settings.impl.ColorSetting; -import top.fpsmaster.features.settings.impl.NumberSetting; import java.awt.*; diff --git a/shared/java/top/fpsmaster/features/impl/interfaces/LyricsDisplay.java b/shared/java/top/fpsmaster/features/impl/interfaces/LyricsDisplay.java index 722adea3..4158139f 100644 --- a/shared/java/top/fpsmaster/features/impl/interfaces/LyricsDisplay.java +++ b/shared/java/top/fpsmaster/features/impl/interfaces/LyricsDisplay.java @@ -2,6 +2,7 @@ import top.fpsmaster.features.impl.InterfaceModule; import top.fpsmaster.features.manager.Category; +import top.fpsmaster.features.settings.impl.BooleanSetting; import top.fpsmaster.features.settings.impl.ColorSetting; import java.awt.*; @@ -9,9 +10,10 @@ public class LyricsDisplay extends InterfaceModule { public static ColorSetting textColor = new ColorSetting("TextColor", new Color(255, 255, 255)); public static ColorSetting textBG = new ColorSetting("TextColorBG", new Color(255, 255, 255)); + public BooleanSetting scale = new BooleanSetting("Scale", true); public LyricsDisplay() { super("LyricsDisplay", Category.Interface); - addSettings(backgroundColor, rounded, betterFont, textColor, textBG, bg, rounded, roundRadius); + addSettings(backgroundColor, rounded, betterFont, textColor, textBG, bg, rounded, roundRadius, scale); } } \ No newline at end of file diff --git a/shared/java/top/fpsmaster/features/impl/interfaces/ModsList.java b/shared/java/top/fpsmaster/features/impl/interfaces/ModsList.java index d862d8b9..43a29992 100644 --- a/shared/java/top/fpsmaster/features/impl/interfaces/ModsList.java +++ b/shared/java/top/fpsmaster/features/impl/interfaces/ModsList.java @@ -18,6 +18,6 @@ public class ModsList extends InterfaceModule { public ModsList() { super("ModsList", Category.Interface); - addSettings(showLogo, text, english, color, rainbow, betterFont, backgroundColor, bg); + addSettings(showLogo, text, english, color, rainbow, betterFont, spacing, backgroundColor, bg); } } diff --git a/shared/java/top/fpsmaster/features/impl/interfaces/PotionDisplay.java b/shared/java/top/fpsmaster/features/impl/interfaces/PotionDisplay.java index 1bf31913..182236e8 100644 --- a/shared/java/top/fpsmaster/features/impl/interfaces/PotionDisplay.java +++ b/shared/java/top/fpsmaster/features/impl/interfaces/PotionDisplay.java @@ -8,7 +8,7 @@ public class PotionDisplay extends InterfaceModule { public PotionDisplay() { super("PotionDisplay", Category.Interface); - addSettings(backgroundColor, fontShadow, betterFont, bg, rounded, roundRadius); + addSettings(backgroundColor, fontShadow, betterFont, spacing, bg, rounded, roundRadius); } @Override diff --git a/shared/java/top/fpsmaster/modules/music/Line.java b/shared/java/top/fpsmaster/modules/music/Line.java index 70da3d93..eba601da 100644 --- a/shared/java/top/fpsmaster/modules/music/Line.java +++ b/shared/java/top/fpsmaster/modules/music/Line.java @@ -1,15 +1,19 @@ package top.fpsmaster.modules.music; +import top.fpsmaster.utils.math.animation.Animation; + import java.util.ArrayList; public class Line { public ArrayList words = new ArrayList<>(); + public int type = 0; public long time = 0; + public float alpha = 0f; public long duration = 0; - public String timeTick = null; - public int type = 0; public float animation = 0f; - public float alpha = 0f; + public boolean finished = false; + public String timeTick = null; + public Animation scaleAnimation = new Animation(); public void addWord(Word word) { words.add(word); @@ -22,4 +26,5 @@ public String getContent() { } return stringBuilder.toString(); } + } diff --git a/shared/java/top/fpsmaster/ui/custom/Component.java b/shared/java/top/fpsmaster/ui/custom/Component.java index f82eb3a7..110b2c57 100644 --- a/shared/java/top/fpsmaster/ui/custom/Component.java +++ b/shared/java/top/fpsmaster/ui/custom/Component.java @@ -3,7 +3,6 @@ import net.minecraft.client.Minecraft; import net.minecraft.client.gui.GuiChat; import net.minecraft.client.gui.ScaledResolution; -import net.minecraft.client.renderer.GlStateManager; import org.lwjgl.input.Mouse; import org.lwjgl.opengl.GL11; import top.fpsmaster.FPSMaster; @@ -18,9 +17,6 @@ import java.awt.*; -import static org.lwjgl.opengl.GL11.*; -import static org.lwjgl.opengl.GL11.GL_BLEND; - public class Component { private float dragX = 0f; @@ -236,4 +232,8 @@ public float getStringWidth(int fontSize, String name) { UFontRenderer font = FPSMaster.fontManager.getFont(fontSize); return mod.betterFont.getValue() ? font.getStringWidth(name) : ProviderManager.mcProvider.getFontRenderer().getStringWidth(name); } + public float getStringHeight(int fontSize) { + UFontRenderer font = FPSMaster.fontManager.getFont(fontSize); + return mod.betterFont.getValue() ? font.getHeight() : ProviderManager.mcProvider.getFontRenderer().FONT_HEIGHT; + } } diff --git a/shared/java/top/fpsmaster/ui/custom/impl/ArmorDisplayComponent.java b/shared/java/top/fpsmaster/ui/custom/impl/ArmorDisplayComponent.java index 5ad85e3e..cfc13a46 100644 --- a/shared/java/top/fpsmaster/ui/custom/impl/ArmorDisplayComponent.java +++ b/shared/java/top/fpsmaster/ui/custom/impl/ArmorDisplayComponent.java @@ -26,7 +26,7 @@ public void draw(float x, float y) { for (int i = 0; i < armorInventory.size(); i++) { ItemStack itemStack = armorInventory.get(i); - int x1 = (int) (x + i * 18); + int x1 = (int) (x + i * (mod.spacing.getValue().intValue() + 18)) - mod.spacing.getValue().intValue(); int y1 = (int) y; switch (ArmorDisplay.mode.getValue()) { @@ -37,7 +37,7 @@ public void draw(float x, float y) { case 2: itemStack = armorInventory.get(armorInventory.size() - 1 - i); x1 = (int) x; - y1 = (int) y + i * 18; + y1 = (int) (y + i * (mod.spacing.getValue().intValue() + 18)) - mod.spacing.getValue().intValue(); break; } @@ -89,13 +89,13 @@ public void draw(float x, float y) { switch (ArmorDisplay.mode.getValue()) { case 0: - width = 70f; + width = 70f + mod.spacing.getValue().intValue(); height = 18f; break; case 1: case 2: width = 70f; - height = 4 + armorInventory.size() * 16; + height = 4 + mod.spacing.getValue().intValue() + armorInventory.size() * 16; break; } } diff --git a/shared/java/top/fpsmaster/ui/custom/impl/LyricsComponent.java b/shared/java/top/fpsmaster/ui/custom/impl/LyricsComponent.java index beb0fa91..7cdbbc2d 100644 --- a/shared/java/top/fpsmaster/ui/custom/impl/LyricsComponent.java +++ b/shared/java/top/fpsmaster/ui/custom/impl/LyricsComponent.java @@ -4,7 +4,9 @@ import top.fpsmaster.modules.music.*; import top.fpsmaster.ui.custom.Component; import top.fpsmaster.ui.custom.Position; +import top.fpsmaster.utils.math.animation.Animation; import top.fpsmaster.utils.math.animation.AnimationUtils; +import top.fpsmaster.utils.math.animation.Type; import top.fpsmaster.utils.render.Render2DUtils; import java.util.List; @@ -12,7 +14,6 @@ public class LyricsComponent extends Component { private long duration = 0; - public LyricsComponent() { super(LyricsDisplay.class); x = 0.5f; @@ -42,6 +43,7 @@ public void draw(float x, float y) { List lines = current.lyrics.lines; for (int i = 0; i < lines.size(); i++) { Line line = lines.get(i); + line.finished = false; if (MusicPlayer.isPlaying && JLayerHelper.clip != null) { duration = (long) (JLayerHelper.getDuration() * 60 * 1000 * JLayerHelper.getProgress()); } @@ -58,26 +60,28 @@ public void draw(float x, float y) { } if ((duration >= time && duration < nextTime) || duration > time) { curLine = i; + //get previous line and set finished + if(i != 0) lines.get(i - 1).finished = true; } } if (curLine != -1) { - for (int i = curLine - 2; i <= curLine + 2; i++) { - if (i >= 0 && i < lines.size()) { - Line line = lines.get(i); + for (int j = curLine - 2; j <= curLine + 2; j++) { + if (j >= 0 && j < lines.size()) { + Line line = lines.get(j); String content = line.getContent(); float xOffset = x + (width - getStringWidth(20, content)) / 2; - if (i == curLine) { + if (j == curLine) { line.animation = (float) AnimationUtils.base(line.animation, 0.0, 0.1f); line.alpha = (float) AnimationUtils.base(line.alpha, 1.0, 0.1f); } else { - line.animation = (float) AnimationUtils.base(line.animation, i - curLine, 0.1f); - line.alpha = (float) (Math.abs(i - curLine) == 1 ? + line.animation = (float) AnimationUtils.base(line.animation, j - curLine, 0.1f); + line.alpha = (float) (Math.abs(j - curLine) == 1 ? AnimationUtils.base(line.alpha, 1.0, 0.1f) : AnimationUtils.base(line.alpha, 0.0, 0.1f)); } - if (Math.abs(i - curLine) <= 1) { - drawLine(line, xOffset, y + line.animation * 20 + 20, 20, i == curLine); + if (Math.abs(j - curLine) <= 1) { + drawLine(line, xOffset, y + line.animation * 20 + 20, 20,j == curLine); } } } @@ -85,24 +89,39 @@ public void draw(float x, float y) { } } - private void drawLine(Line line, float xOffset, float y, int lfont, boolean current) { + private void drawLine(Line line, float xOffset, float y, int font, boolean current) { + LyricsDisplay lyrics = (LyricsDisplay) mod; + //lyric line has been play finished or is playing + if (lyrics.scale.getValue()) { + //default scale ratio + float scaleRatio = 1.0f; + if(line.finished || current) { + line.scaleAnimation.start(1.0,1.3,0.3f,Type.LINEAR); + line.scaleAnimation.update(); + scaleRatio = (float) line.scaleAnimation.value; + } + Render2DUtils.scaleStart(xOffset + (getStringWidth(20, line.getContent()) / 2.0f), y + (getStringHeight(20) / 2.0f), scaleRatio); + } for (Word word : line.words) { xOffset += current ? drawWord(word, xOffset, y, line) : drawWordBG(word, xOffset, y, line); } + if (lyrics.scale.getValue()) { + Render2DUtils.scaleEnd(); + } } + private float drawWord(Word word, float xOffset, float y, Line line) { if (duration >= word.time) { float animation = 0.3f + (float) (duration - word.time) / word.duration; float animation2 = (float) (duration - word.time) / word.duration; drawString(20, word.content, xOffset, y + 7 - Math.min(animation2, 1f) * 3, Render2DUtils.reAlpha(LyricsDisplay.textColor.getColor(), (int) Math.min(animation * 255, 255)).getRGB()); - return getStringWidth(20, word.content); - }else{ + }else { drawString(20, word.content, xOffset, y + 7, Render2DUtils.reAlpha(LyricsDisplay.textColor.getColor(), (int) Math.min(line.alpha * 120, 255)).getRGB()); - return getStringWidth(20, word.content); } + return getStringWidth(20, word.content); } private float drawWordBG(Word word, float xOffset, float y, Line line) { diff --git a/shared/java/top/fpsmaster/ui/custom/impl/ModsListComponent.java b/shared/java/top/fpsmaster/ui/custom/impl/ModsListComponent.java index a8489861..19a435c2 100644 --- a/shared/java/top/fpsmaster/ui/custom/impl/ModsListComponent.java +++ b/shared/java/top/fpsmaster/ui/custom/impl/ModsListComponent.java @@ -17,7 +17,8 @@ public class ModsListComponent extends Component { List modules = new ArrayList<>(); - + //default background rectangle height + public static final float MODULE_HEIGHT = 14f; public ModsListComponent() { super(ModsList.class); this.x = 1f; @@ -38,9 +39,8 @@ public void draw(float x, float y) { modY = 20f; } - float width2 = 40f; + float maxWidth = 40f; x += this.width; - if (ProviderManager.mcProvider.getPlayer().ticksExisted % 20 == 0) modules = FPSMaster.moduleManager.modules.stream() .sorted((m1, m2) -> { @@ -53,10 +53,10 @@ public void draw(float x, float y) { return Float.compare(w2, w1); }).collect(Collectors.toList()); - int ls = 0; + int index = 0; for (Module module : modules) { - Color col = Color.getHSBColor( - ls / (float) modules.size() - ProviderManager.mcProvider.getPlayer().ticksExisted % 50 / 50f, + Color textColor = Color.getHSBColor( + index / (float) modules.size() - ProviderManager.mcProvider.getPlayer().ticksExisted % 50 / 50f, 0.7f, 1f ); @@ -69,30 +69,36 @@ public void draw(float x, float y) { name = module.name; } - float width = mod.betterFont.getValue() + float textWidth = mod.betterFont.getValue() ? font.getStringWidth(name) : ProviderManager.mcProvider.getFontRenderer().getStringWidth(name); - if (width2 < width) { - width2 = width + 5; + if (maxWidth < textWidth) { + maxWidth = textWidth + 5; + } + if(modlist.bg.getValue()) { + Render2DUtils.drawRect(x - textWidth - 4, y + modY, textWidth + 4, MODULE_HEIGHT + modlist.spacing.getValue().intValue() , modlist.backgroundColor.getColor()); } - - Render2DUtils.drawRect(x - width - 4, y + modY, width + 4, 14f, modlist.backgroundColor.getColor()); Color color = modlist.color.getColor(); if (modlist.rainbow.getValue()) { - color = col; + color = textColor; } - + //text y position centered offset + int yOffset; if (mod.betterFont.getValue()) { - font.drawStringWithShadow(name, x - width - 2, y + modY + 2, color.getRGB()); + yOffset = (int) ((MODULE_HEIGHT - font.getHeight()) / 2); + font.drawStringWithShadow(name, x - textWidth - 2, y + modY + yOffset, color.getRGB()); } else { - ProviderManager.mcProvider.getFontRenderer().drawStringWithShadow(name, x - width - 2, y + modY, color.getRGB()); + // Problem: yOffset = (BG_HEIGHT - ProviderManager.mcProvider.getFontRenderer().FONT_HEIGHT) / 2; + // this is the only way to center the text y position + yOffset = ProviderManager.mcProvider.getFontRenderer().FONT_HEIGHT / 2; + ProviderManager.mcProvider.getFontRenderer().drawStringWithShadow(name, x - textWidth - 2, y + modY + yOffset, color.getRGB()); } - ls++; - modY += 14f; + index++; + modY += MODULE_HEIGHT + modlist.spacing.getValue().intValue(); } - this.width = width2; + this.width = maxWidth; height = modY; } } diff --git a/shared/java/top/fpsmaster/ui/custom/impl/PotionDisplayComponent.java b/shared/java/top/fpsmaster/ui/custom/impl/PotionDisplayComponent.java index 64ab4199..df299a55 100644 --- a/shared/java/top/fpsmaster/ui/custom/impl/PotionDisplayComponent.java +++ b/shared/java/top/fpsmaster/ui/custom/impl/PotionDisplayComponent.java @@ -3,6 +3,7 @@ import net.minecraft.client.gui.Gui; import net.minecraft.client.renderer.GlStateManager; import net.minecraft.client.resources.I18n; +import net.minecraft.potion.PotionEffect; import net.minecraft.util.ResourceLocation; import top.fpsmaster.features.impl.interfaces.PotionDisplay; import top.fpsmaster.interfaces.ProviderManager; @@ -17,14 +18,15 @@ public PotionDisplayComponent() { super(PotionDisplay.class); } + public static final float POTION_HEIGHT = 36f; + @Override public void draw(float x, float y) { super.draw(x, y); - float dY = y; - + float dY = y - mod.spacing.getValue().intValue(); GlStateManager.pushMatrix(); - - for (net.minecraft.potion.PotionEffect effect : ProviderManager.mcProvider.getPlayer().getActivePotionEffects()) { + int index = 0; + for (PotionEffect effect : ProviderManager.mcProvider.getPlayer().getActivePotionEffects()) { String title = I18n.format(effect.getEffectName()) + " lv." + (effect.getAmplifier() + 1); String duration = (effect.getDuration() / 20 / 60) + "min" + effect.getDuration() / 20 % 60 + "s"; float width = Math.max(getStringWidth(18, title), getStringWidth(16, duration)) + 36; @@ -43,16 +45,17 @@ public void draw(float x, float y) { Gui.drawModalRectWithCustomSizedTexture( (int) (x + 8), (int) (dY + 8), - (potion % 8 * 18), - (198 + potion / 8 * 18), + (potion % 8 * 18) + 1, + (198 + potion / 8 * 18) + 1, 16, 16, 256f, 256f ); - dY += 36f; + dY += (index * mod.spacing.getValue().intValue()) + POTION_HEIGHT + mod.spacing.getValue().intValue(); this.width = width + 12; + index++; } GlStateManager.popMatrix(); diff --git a/shared/java/top/fpsmaster/ui/custom/impl/TargetHUDComponent.java b/shared/java/top/fpsmaster/ui/custom/impl/TargetHUDComponent.java index fd91712a..7ebb202b 100644 --- a/shared/java/top/fpsmaster/ui/custom/impl/TargetHUDComponent.java +++ b/shared/java/top/fpsmaster/ui/custom/impl/TargetHUDComponent.java @@ -1,6 +1,5 @@ package top.fpsmaster.ui.custom.impl; -import net.minecraft.entity.Entity; import net.minecraft.entity.player.EntityPlayer; import top.fpsmaster.FPSMaster; import top.fpsmaster.features.impl.interfaces.TargetDisplay; diff --git a/shared/java/top/fpsmaster/ui/mc/ServerListEntry.java b/shared/java/top/fpsmaster/ui/mc/ServerListEntry.java index bc874d84..9da77721 100644 --- a/shared/java/top/fpsmaster/ui/mc/ServerListEntry.java +++ b/shared/java/top/fpsmaster/ui/mc/ServerListEntry.java @@ -134,7 +134,7 @@ public void drawEntry(int slotIndex, int x, int y, int listWidth, int slotHeight } } else { k = 1; - l = (int) (Minecraft.getSystemTime() / 100L + (long) (slotIndex * 2L) & 7L); + l = (int) (Minecraft.getSystemTime() / 100L + (slotIndex * 2L) & 7L); if (l > 4) { l = 8 - l; } @@ -168,7 +168,7 @@ public void drawEntry(int slotIndex, int x, int y, int listWidth, int slotHeight // this.owner.setHoveringText(s); // } - if (Render2DUtils.isHovered(x + listWidth - text.getStringWidth(s1), y + 4,10,10,mouseX,mouseY)) { + if (Render2DUtils.isHovered(x + listWidth - text.getStringWidth(s1), y + 4, 10, 10, mouseX, mouseY)) { text.drawString(s1, x + listWidth - text.getStringWidth(s1) + 12, y + 4, -1); } diff --git a/shared/java/top/fpsmaster/utils/render/Render2DUtils.java b/shared/java/top/fpsmaster/utils/render/Render2DUtils.java index efae8f84..261616ec 100644 --- a/shared/java/top/fpsmaster/utils/render/Render2DUtils.java +++ b/shared/java/top/fpsmaster/utils/render/Render2DUtils.java @@ -212,6 +212,15 @@ public static int getFixedScale() { return scaleFactor; } + public static void scaleStart(float x, float y, float scale) { + glPushMatrix(); + glTranslatef(x, y, 0); + glScalef(scale, scale, 1); + glTranslatef(-x, -y, 0); + } + public static void scaleEnd() { + glPopMatrix(); + } public static float[] getFixedBounds() { ScaledResolution sr = new ScaledResolution(mc); int scaleFactor; diff --git a/shared/resources/assets/minecraft/client/lang/en_us.lang b/shared/resources/assets/minecraft/client/lang/en_us.lang index 4406714a..181ea0f2 100644 --- a/shared/resources/assets/minecraft/client/lang/en_us.lang +++ b/shared/resources/assets/minecraft/client/lang/en_us.lang @@ -57,6 +57,7 @@ armordisplay.mode.simplevertical=Simple Vertical armordisplay.mode.vertical=Detailed Vertical armordisplay.roundradius=Corner Radius armordisplay.background=Show Background +armordisplay.spacing=Spacing betterchat=Chat Customizer betterchat.desc=Customize the chat background, font, and animations @@ -124,6 +125,7 @@ potiondisplay.fontshadow=Font Shadow potiondisplay.betterfont=Clean Font potiondisplay.roundradius=Corner Radius potiondisplay.background=Show Background +potiondisplay.spacing=Spacing pingdisplay=Ping Display pingdisplay.desc=Shows your ping to the server @@ -276,7 +278,7 @@ lyricsdisplay.fontshadow=Font Shadow lyricsdisplay.betterfont=Clean Font lyricsdisplay.roundradius=Corner Radius lyricsdisplay.background=Show Background - +lyricsdisplay.scale=Play Text Scale crosshair=Custom Crosshair crosshair.desc=Replaces the default crosshair crosshair.dynamic=Dynamic @@ -437,6 +439,7 @@ modslist.backgroundcolor=Background Color modslist.betterfont=Clean Font modslist.roundradius=Corner Radius modslist.background=Show Background +modslist.spacing=Spacing betterscreen=Enhanced UI betterscreen.desc=Improves vanilla UI visuals diff --git a/shared/resources/assets/minecraft/client/lang/zh_cn.lang b/shared/resources/assets/minecraft/client/lang/zh_cn.lang index 12724f8a..dc57f7db 100644 --- a/shared/resources/assets/minecraft/client/lang/zh_cn.lang +++ b/shared/resources/assets/minecraft/client/lang/zh_cn.lang @@ -57,6 +57,7 @@ armordisplay.mode.simplevertical=垂直简单 armordisplay.mode.vertical=垂直详细 armordisplay.roundradius=圆角半径 armordisplay.background=背景 +armordisplay.spacing=间距 betterchat=聊天框 betterchat.desc=修改聊天框的背景、字体,以及添加动画等 @@ -124,6 +125,7 @@ potiondisplay.fontshadow=字体阴影 potiondisplay.betterfont=更好的字体 potiondisplay.roundradius=圆角半径 potiondisplay.background=背景 +potiondisplay.spacing=间距 pingdisplay=延迟显示 pingdisplay.desc=显示玩家到服务器的延迟(Ping) @@ -145,7 +147,6 @@ reachdisplay.roundradius=圆角半径 reachdisplay.textcolor=文字颜色 reachdisplay.background=背景 - scoreboard=计分板 scoreboard.desc=自定义计分板的样式 scoreboard.textcolor=文字颜色 @@ -157,7 +158,6 @@ scoreboard.betterfont=更好的字体 scoreboard.roundradius=圆角半径 scoreboard.background=背景 - performance=性能 performance.desc=优化MC帧数 performance.entitiesoptimize=实体渲染优化 @@ -258,7 +258,6 @@ oldanimations.animationmode.jigsaw=Jigsaw oldanimations.animationmode.jello=Jello oldanimations.animationmode.push=Push - irc=客户端聊天 irc.desc=与相同客户端的用户聊天 irc.enable=IRC功能已启用,输入%sirc <消息>发送消息 @@ -281,6 +280,7 @@ lyricsdisplay.fontshadow=字体阴影 lyricsdisplay.betterfont=更好的字体 lyricsdisplay.roundradius=圆角半径 lyricsdisplay.background=背景 +lyricsdisplay.scale=播放文字缩放 crosshair=自定义准心 crosshair.desc=使用一个自定义的准星替代原版的准星 @@ -444,6 +444,7 @@ modslist.backgroundcolor=功能列表背景颜色 modslist.betterfont=更好的字体 modslist.roundradius=圆角半径 modslist.background=背景 +modslist.spacing=间距 betterscreen=更好的界面 betterscreen.desc=让原版的部分界面看起来更好 From aee2e98bee1014834aa2536233121e940e34f4f4 Mon Sep 17 00:00:00 2001 From: SuperSkidder Date: Fri, 18 Jul 2025 12:40:27 +0800 Subject: [PATCH 124/193] feat: third person blocking animation --- .../impl/optimizes/OldAnimations.java | 6 ++-- .../assets/minecraft/client/lang/en_us.lang | 1 + .../assets/minecraft/client/lang/zh_cn.lang | 1 + .../forge/mixin/MixinLayerHeldItem.java | 30 +++++++++++++++++++ .../src/main/resources/mixins.fpsmaster.json | 1 + 5 files changed, 37 insertions(+), 2 deletions(-) create mode 100644 v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinLayerHeldItem.java diff --git a/shared/java/top/fpsmaster/features/impl/optimizes/OldAnimations.java b/shared/java/top/fpsmaster/features/impl/optimizes/OldAnimations.java index 426c5bb9..006a01ba 100644 --- a/shared/java/top/fpsmaster/features/impl/optimizes/OldAnimations.java +++ b/shared/java/top/fpsmaster/features/impl/optimizes/OldAnimations.java @@ -28,6 +28,8 @@ public class OldAnimations extends Module { public static BooleanSetting oldUsing = new BooleanSetting("OldUsing", true); public static BooleanSetting blockSwing = new BooleanSetting("BlockSwing", true); public static BooleanSetting oldDamage = new BooleanSetting("OldDamage", true); + public static BooleanSetting oldThirdPerson = new BooleanSetting("OldThirdPerson", true); + ; public static NumberSetting x = new NumberSetting("X", 0, -1, 1, 0.01); public static NumberSetting y = new NumberSetting("Y", 0, -1, 1, 0.01); public static NumberSetting z = new NumberSetting("Z", 0, -1, 1, 0.01); @@ -42,7 +44,7 @@ public class OldAnimations extends Module { public OldAnimations() { super("OldAnimations", Category.OPTIMIZE); - addSettings(noShield, animationSneak, oldRod, oldBow, oldSwing, blockSwing, oldDamage, oldUsing, oldBlock, animationMode, x, y, z); + addSettings(noShield, animationSneak, oldRod, oldBow, oldSwing, oldThirdPerson, blockSwing, oldDamage, oldUsing, oldBlock, animationMode, x, y, z); } @Override @@ -103,7 +105,7 @@ public void swingItem() { mc.thePlayer.swingProgressInt = -1; mc.thePlayer.isSwingInProgress = true; if (mc.thePlayer.worldObj instanceof WorldServer) { - ((WorldServer)mc.thePlayer.worldObj).getEntityTracker().sendToAllTrackingEntity(mc.thePlayer, new S0BPacketAnimation(mc.thePlayer, 0)); + ((WorldServer) mc.thePlayer.worldObj).getEntityTracker().sendToAllTrackingEntity(mc.thePlayer, new S0BPacketAnimation(mc.thePlayer, 0)); } } } diff --git a/shared/resources/assets/minecraft/client/lang/en_us.lang b/shared/resources/assets/minecraft/client/lang/en_us.lang index 181ea0f2..d1dee38d 100644 --- a/shared/resources/assets/minecraft/client/lang/en_us.lang +++ b/shared/resources/assets/minecraft/client/lang/en_us.lang @@ -235,6 +235,7 @@ oldanimations.oldblock=Old Blocking oldanimations.olddamage=Old Damage Anim oldanimations.oldusing=Old Use Anim oldanimations.blockhit=Block Hit +oldanimations.oldthirdperson=Old Third Person Animation oldanimations.x=X oldanimations.y=Y oldanimations.z=Z diff --git a/shared/resources/assets/minecraft/client/lang/zh_cn.lang b/shared/resources/assets/minecraft/client/lang/zh_cn.lang index dc57f7db..04b9e00d 100644 --- a/shared/resources/assets/minecraft/client/lang/zh_cn.lang +++ b/shared/resources/assets/minecraft/client/lang/zh_cn.lang @@ -237,6 +237,7 @@ oldanimations.oldblock=旧格挡 oldanimations.olddamage=旧伤害动画 oldanimations.oldusing=旧使用动画 oldanimations.blockhit=格挡挥手 +oldanimations.oldthirdperson=旧第三人称动画 oldanimations.x=X oldanimations.y=Y oldanimations.z=Z diff --git a/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinLayerHeldItem.java b/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinLayerHeldItem.java new file mode 100644 index 00000000..ae86a387 --- /dev/null +++ b/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinLayerHeldItem.java @@ -0,0 +1,30 @@ +package top.fpsmaster.forge.mixin; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.entity.AbstractClientPlayer; +import net.minecraft.client.renderer.GlStateManager; +import net.minecraft.client.renderer.entity.layers.LayerHeldItem; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.*; +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; +import org.spongepowered.asm.mixin.injection.callback.LocalCapture; +import top.fpsmaster.features.impl.optimizes.OldAnimations; + +@Mixin(LayerHeldItem.class) +public class MixinLayerHeldItem { + @Inject(method = "doRenderLayer", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/ItemRenderer;renderItem(Lnet/minecraft/entity/EntityLivingBase;Lnet/minecraft/item/ItemStack;Lnet/minecraft/client/renderer/block/model/ItemCameraTransforms$TransformType;)V")) + private void blockPosition(EntityLivingBase entitylivingbaseIn, float f, float g, float partialTicks, float h, float i, float j, float scale, CallbackInfo ci) { + if (OldAnimations.using) { + if (OldAnimations.oldThirdPerson.getValue() && entitylivingbaseIn instanceof AbstractClientPlayer && ((AbstractClientPlayer) entitylivingbaseIn).isBlocking()) { + GlStateManager.translate(0.05F, 0.0F, -0.1F); + GlStateManager.rotate(-50.0F, 0.0F, 1.0F, 0.0F); + GlStateManager.rotate(-10.0F, 1.0F, 0.0F, 0.0F); + GlStateManager.rotate(-60.0F, 0.0F, 0.0F, 1.0F); + } + } + } +} diff --git a/v1.8.9/src/main/resources/mixins.fpsmaster.json b/v1.8.9/src/main/resources/mixins.fpsmaster.json index e170c89f..1c9f6c75 100644 --- a/v1.8.9/src/main/resources/mixins.fpsmaster.json +++ b/v1.8.9/src/main/resources/mixins.fpsmaster.json @@ -33,6 +33,7 @@ "MixinItemRenderer", "MixinKeybinding", "MixinLayerArmorBase", + "MixinLayerHeldItem", "MixinMainMenu", "MixinMinecraft", "MixinNetworkPlayerInfo", From 34ce88c48b1d8565f4703eec9b78029d261d58d5 Mon Sep 17 00:00:00 2001 From: TeAnli <159260777+TeAnli@users.noreply.github.com> Date: Fri, 18 Jul 2025 17:18:10 +0800 Subject: [PATCH 125/193] feature: AutoGG module (#103) * feat: add spacing language support * feat: Add spacing setting and rendering * chore: add language and scale utility * feat: Add a scale animation to the lyrics * style: lyric finished still scale * feat: AutoGG language support * feat: add AutoGG module and message send utility * feat: add autoplay and icon * fix: bug * fix: bugs --------- Co-authored-by: SuperSkidder --- .../features/impl/utility/AutoGG.java | 50 ++++++++++++++++++ .../features/impl/utility/ChatBot.java | 3 +- .../features/manager/ModuleManager.java | 1 + .../interfaces/packets/IPacketChat.java | 3 ++ shared/java/top/fpsmaster/utils/Utility.java | 5 ++ .../assets/minecraft/client/lang/en_us.lang | 7 +++ .../assets/minecraft/client/lang/zh_cn.lang | 7 +++ .../client/textures/modules/autogg.png | Bin 0 -> 648 bytes .../wrapper/packets/SPacketChatProvider.java | 14 +++-- 9 files changed, 84 insertions(+), 6 deletions(-) create mode 100644 shared/java/top/fpsmaster/features/impl/utility/AutoGG.java create mode 100644 shared/resources/assets/minecraft/client/textures/modules/autogg.png diff --git a/shared/java/top/fpsmaster/features/impl/utility/AutoGG.java b/shared/java/top/fpsmaster/features/impl/utility/AutoGG.java new file mode 100644 index 00000000..66c922a4 --- /dev/null +++ b/shared/java/top/fpsmaster/features/impl/utility/AutoGG.java @@ -0,0 +1,50 @@ +package top.fpsmaster.features.impl.utility; + +import net.minecraft.util.StringUtils; +import top.fpsmaster.event.Subscribe; +import top.fpsmaster.event.events.EventPacket; +import top.fpsmaster.features.manager.Category; +import top.fpsmaster.features.manager.Module; +import top.fpsmaster.features.settings.impl.BooleanSetting; +import top.fpsmaster.features.settings.impl.ModeSetting; +import top.fpsmaster.features.settings.impl.TextSetting; +import top.fpsmaster.interfaces.ProviderManager; +import top.fpsmaster.modules.logger.ClientLogger; +import top.fpsmaster.ui.notification.Notification; +import top.fpsmaster.ui.notification.NotificationManager; +import top.fpsmaster.utils.Utility; + +public class AutoGG extends Module { + public BooleanSetting autoPlay = new BooleanSetting("AutoPlay", false); + public TextSetting message = new TextSetting("Message", "gg"); + public ModeSetting servers = new ModeSetting("Servers", 0, "hypxiel"); + + public AutoGG() { + super("AutoGG", Category.Utility); + this.addSettings(autoPlay, message, servers); + } + + @Subscribe + public void onPacket(EventPacket event) { + if (event.type == EventPacket.PacketType.RECEIVE && ProviderManager.packetChat.isPacket(event.packet)) { + switch (servers.getValue()) { + case 0: + String componentValue = ProviderManager.packetChat.getChatComponent(event.packet).toString(); + boolean hasPlayCommand = componentValue.contains("ClickEvent{action=RUN_COMMAND, value='/play "); + String chatMessage = ProviderManager.packetChat.getUnformattedText(event.packet); + boolean hasEndInformation = StringUtils.stripControlCodes(chatMessage).contains(" 胜利者 ") || StringUtils.stripControlCodes(chatMessage).startsWith(" Winner "); + if (hasEndInformation) { + Utility.sendChatMessage("/ac " + message.getValue()); + } + if (hasPlayCommand) { + if (autoPlay.getValue()) { + Utility.sendChatMessage(componentValue.substring(componentValue.indexOf("value='") + 7, componentValue.indexOf("'}"))); + } + } + break; + default: + + } + } + } +} diff --git a/shared/java/top/fpsmaster/features/impl/utility/ChatBot.java b/shared/java/top/fpsmaster/features/impl/utility/ChatBot.java index 06cf1e82..50eaa118 100644 --- a/shared/java/top/fpsmaster/features/impl/utility/ChatBot.java +++ b/shared/java/top/fpsmaster/features/impl/utility/ChatBot.java @@ -100,8 +100,7 @@ public void onChat(EventPacket e) { } catch (InterruptedException e1) { e1.printStackTrace(); } - if (ProviderManager.mcProvider.getPlayer() == null) return; - ProviderManager.mcProvider.getPlayer().sendChatMessage(s); + Utility.sendChatMessage(s); } }); } diff --git a/shared/java/top/fpsmaster/features/manager/ModuleManager.java b/shared/java/top/fpsmaster/features/manager/ModuleManager.java index b7e38446..b6bfd515 100644 --- a/shared/java/top/fpsmaster/features/manager/ModuleManager.java +++ b/shared/java/top/fpsmaster/features/manager/ModuleManager.java @@ -93,6 +93,7 @@ public void init() { modules.add(new DragonWings()); modules.add(new FireModifier()); modules.add(new FreeLook()); + modules.add(new AutoGG()); modules.add(new LyricsDisplay()); modules.add(new SkinChanger()); modules.add(new TimeChanger()); diff --git a/shared/java/top/fpsmaster/interfaces/packets/IPacketChat.java b/shared/java/top/fpsmaster/interfaces/packets/IPacketChat.java index ec05c951..2260c37a 100644 --- a/shared/java/top/fpsmaster/interfaces/packets/IPacketChat.java +++ b/shared/java/top/fpsmaster/interfaces/packets/IPacketChat.java @@ -1,7 +1,10 @@ package top.fpsmaster.interfaces.packets; +import net.minecraft.util.IChatComponent; + public interface IPacketChat extends IPacket { String getUnformattedText(Object packet); + IChatComponent getChatComponent(Object packet); int getType(Object p); void appendTranslation(Object p); } diff --git a/shared/java/top/fpsmaster/utils/Utility.java b/shared/java/top/fpsmaster/utils/Utility.java index ce4dd7f3..93b73ccb 100644 --- a/shared/java/top/fpsmaster/utils/Utility.java +++ b/shared/java/top/fpsmaster/utils/Utility.java @@ -12,6 +12,11 @@ public class Utility { static ArrayList messages = new ArrayList<>(); + public static void sendChatMessage(String message) { + if (ProviderManager.mcProvider.getPlayer() == null) return; + ProviderManager.mcProvider.getPlayer().sendChatMessage(message); + } + public static void sendClientMessage(String msg) { if (ProviderManager.mcProvider.getWorld() != null) { ProviderManager.mcProvider.printChatMessage(ProviderManager.utilityProvider.makeChatComponent(msg)); diff --git a/shared/resources/assets/minecraft/client/lang/en_us.lang b/shared/resources/assets/minecraft/client/lang/en_us.lang index d1dee38d..e5566a61 100644 --- a/shared/resources/assets/minecraft/client/lang/en_us.lang +++ b/shared/resources/assets/minecraft/client/lang/en_us.lang @@ -213,6 +213,13 @@ sprint.desc=Stay sprinting at all times sprint.togglesprint=Toggle Sprint sprint.betterfont=Clean Font +autogg=AutoGG +autogg.desc=Automatically send a custom message after a game has ended. +autogg.servers=Servers +autogg.servers.hypxiel=Hypxiel +autogg.message=Custom Message +autogg.autoplay=Auto Play + musicdisplay=Music HUD musicdisplay.desc=Displays current playing music musicdisplay.backgroundcolor=Background Color diff --git a/shared/resources/assets/minecraft/client/lang/zh_cn.lang b/shared/resources/assets/minecraft/client/lang/zh_cn.lang index 04b9e00d..8dcee8af 100644 --- a/shared/resources/assets/minecraft/client/lang/zh_cn.lang +++ b/shared/resources/assets/minecraft/client/lang/zh_cn.lang @@ -215,6 +215,13 @@ sprint.desc=保持疾跑 sprint.togglesprint=保持疾跑 sprint.betterfont=更好的字体 +autogg=自动GG +autogg.desc=游戏结束后自动地在发送你自定义的消息 +autogg.servers=服务器列表 +autogg.servers.hypxiel=Hypxiel +autogg.message=自定义消息 +autogg.autoplay=自动重开 + musicdisplay=音乐显示 musicdisplay.desc=显示你正在播放的音乐 musicdisplay.backgroundcolor=歌曲显示背景颜色 diff --git a/shared/resources/assets/minecraft/client/textures/modules/autogg.png b/shared/resources/assets/minecraft/client/textures/modules/autogg.png new file mode 100644 index 0000000000000000000000000000000000000000..8c65b6accf9f31346b27ee6aa5dde2ce36ad95b1 GIT binary patch literal 648 zcmV;30(bq1P)Px#1am@3R0s$N2z&@+hyVZrGD$>1R7i=vR_$?{KoEWF@&AwxNChSp>nkJDyS>xi zss|=plEvhPaUF$vXj0{XK8($^L?ikd=V>_xFsrtoC38BrMw%{IDEnK&I6+vrsMUU< zJ^Oh-(%O3|T1hQ{qlkPT*$@C!0KQ?Qxivo(fF}Td0c=F%m|!}@f$`HPca?zBYBPCp zm?h5#Lzkw7v4>+Zy2LIM(8@qOHF{&p^t;z5STwvrK1!;qg|o0syo-R0kbFr!p1_vo z{Ue5h*uZ)Tj5ECT#FwPI6cL$A4B!{yh^jC= iVGf96@J&bJr2GTrCaUY(5bh!X0000 5) { From 5ff612a7e1bab16cfaaa092922beeff5a705f425 Mon Sep 17 00:00:00 2001 From: SuperSkidder Date: Fri, 18 Jul 2025 16:27:52 +0800 Subject: [PATCH 126/193] fix: add some exceptions handling --- .../fpsmaster/exception/NetworkException.java | 8 +- .../modules/account/AccountManager.java | 43 ++++---- .../modules/music/netease/NeteaseApi.java | 68 ++++++++++-- .../top/fpsmaster/ui/mc/GuiMultiplayer.java | 8 +- .../ui/screens/oobe/impls/Login.java | 7 +- .../top/fpsmaster/utils/os/HttpRequest.java | 104 ++++++++++-------- .../thirdparty/github/UpdateChecker.java | 8 +- .../thirdparty/microsoft/MicrosoftLogin.java | 10 +- .../utils/thirdparty/openai/OpenAI.java | 6 +- .../top/fpsmaster/wrapper/SkinProvider.java | 15 ++- 10 files changed, 183 insertions(+), 94 deletions(-) diff --git a/shared/java/top/fpsmaster/exception/NetworkException.java b/shared/java/top/fpsmaster/exception/NetworkException.java index 6460414c..dc3dc3cc 100644 --- a/shared/java/top/fpsmaster/exception/NetworkException.java +++ b/shared/java/top/fpsmaster/exception/NetworkException.java @@ -4,14 +4,15 @@ * Exception thrown when there is an error related to network operations. */ public class NetworkException extends Exception { - + int code; /** * Constructs a new NetworkException with the specified detail message. * * @param message the detail message */ - public NetworkException(String message) { + public NetworkException(int code, String message) { super(message); + this.code = code; } /** @@ -20,7 +21,8 @@ public NetworkException(String message) { * @param message the detail message * @param cause the cause */ - public NetworkException(String message, Throwable cause) { + public NetworkException(int code, String message, Throwable cause) { super(message, cause); + this.code = code; } } \ No newline at end of file diff --git a/shared/java/top/fpsmaster/modules/account/AccountManager.java b/shared/java/top/fpsmaster/modules/account/AccountManager.java index be55ba8f..4a8c30ea 100644 --- a/shared/java/top/fpsmaster/modules/account/AccountManager.java +++ b/shared/java/top/fpsmaster/modules/account/AccountManager.java @@ -11,6 +11,7 @@ import top.fpsmaster.utils.os.FileUtils; import top.fpsmaster.utils.os.HttpRequest; +import java.io.IOException; import java.util.HashMap; public class AccountManager { @@ -50,42 +51,44 @@ private void doAutoLogin() throws FileException, AccountException, NetworkExcept } } - private boolean attemptLogin(String username, String token) throws NetworkException { + private boolean attemptLogin(String username, String token) throws AccountException { if (username.isEmpty() || token.isEmpty()) { return false; } try { HashMap headers = new HashMap<>(); - headers.put("Authorization","Bearer " + token); - String s = HttpRequest.get(FPSMaster.SERVICE_API + "/api/auth/validate-jwt", headers); - JsonObject json = parser.parse(s).getAsJsonObject(); + headers.put("Authorization", "Bearer " + token); + HttpRequest.HttpResponseResult s = HttpRequest.get(FPSMaster.SERVICE_API + "/api/auth/validate-jwt", headers); + JsonObject json = parser.parse(s.getBody()).getAsJsonObject(); + if (!s.isSuccess()){ + throw new AccountException("Failed to login via token " + s.getStatusCode()); + } this.username = username; this.token = token; return json.get("data").getAsJsonObject().get("success").getAsBoolean(); } catch (Exception e) { - throw new NetworkException("Failed to login via token", e); + throw new AccountException("Failed to login via token"); } } - public static JsonObject login(String username, String password) throws NetworkException { + public static JsonObject login(String username, String password) throws AccountException { + JsonObject body = new JsonObject(); + body.addProperty("username", username); + body.addProperty("password", password); + HttpRequest.HttpResponseResult s = null; try { - JsonObject body = new JsonObject(); - body.addProperty("username", username); - body.addProperty("password", password); - String s = HttpRequest.post(FPSMaster.SERVICE_API + "/api/auth/login", body.toString()); + s = HttpRequest.post(FPSMaster.SERVICE_API + "/api/auth/login", body.toString()); + } catch (IOException e) { + throw new RuntimeException(e); + } - JsonObject jsonObject = parser.parse(s).getAsJsonObject(); - if (!jsonObject.get("data").getAsJsonObject().get("success").getAsBoolean()) { - throw new NetworkException("Login failed: " + jsonObject.get("message").getAsString()); - } - return jsonObject; - } catch (Exception e) { - if (e instanceof NetworkException) { - throw (NetworkException) e; - } - throw new NetworkException("Login failed", e); + JsonObject jsonObject = parser.parse(s.getBody()).getAsJsonObject(); + if (jsonObject.get("data") == null || !jsonObject.get("data").getAsJsonObject().get("success").getAsBoolean()) { + throw new AccountException("登录失败: " + jsonObject.get("message").getAsString()); } + return jsonObject; + } // Getter and Setter methods diff --git a/shared/java/top/fpsmaster/modules/music/netease/NeteaseApi.java b/shared/java/top/fpsmaster/modules/music/netease/NeteaseApi.java index 16afa015..541db674 100644 --- a/shared/java/top/fpsmaster/modules/music/netease/NeteaseApi.java +++ b/shared/java/top/fpsmaster/modules/music/netease/NeteaseApi.java @@ -2,6 +2,8 @@ import top.fpsmaster.utils.os.HttpRequest; +import java.io.IOException; + public class NeteaseApi { private static final String BASE_URL = "https://music.skidder.top/"; @@ -9,56 +11,100 @@ public class NeteaseApi { public static String getVerbatimLyrics(String id) { String url = BASE_URL + "lyric/new?id=" + id; - return HttpRequest.getWithCookie(url, cookies); + try { + return HttpRequest.getWithCookie(url, cookies).getBody(); + } catch (IOException e) { + throw new RuntimeException(e); + } } public static String searchSongs(String keywords) { String url = BASE_URL + "cloudsearch?keywords=" + keywords; - return HttpRequest.getWithCookie(url, cookies); + try { + return HttpRequest.getWithCookie(url, cookies).getBody(); + } catch (IOException e) { + throw new RuntimeException(e); + } } public static String checkMusic(String id) { String url = BASE_URL + "check/music?id=" + id; - return HttpRequest.getWithCookie(url, cookies); + try { + return HttpRequest.getWithCookie(url, cookies).getBody(); + } catch (IOException e) { + throw new RuntimeException(e); + } } public static String getUserData() { String url = BASE_URL + "user/level"; - return HttpRequest.getWithCookie(url, cookies); + try { + return HttpRequest.getWithCookie(url, cookies).getBody(); + } catch (IOException e) { + throw new RuntimeException(e); + } } public static String getPlayURL(String id) { String url = BASE_URL + "song/url/v1?id=" + id + "&level=higher"; - return HttpRequest.getWithCookie(url, cookies); + try { + return HttpRequest.getWithCookie(url, cookies).getBody(); + } catch (IOException e) { + throw new RuntimeException(e); + } } public static String getPlayList(String id) { String url = BASE_URL + "playlist/track/all?id=" + id + "&limit=50"; - return HttpRequest.getWithCookie(url, cookies); + try { + return HttpRequest.getWithCookie(url, cookies).getBody(); + } catch (IOException e) { + throw new RuntimeException(e); + } } public static String getDailyList() { String url = BASE_URL + "recommend/songs?timestamp=" + System.currentTimeMillis(); - return HttpRequest.getWithCookie(url, cookies); + try { + return HttpRequest.getWithCookie(url, cookies).getBody(); + } catch (IOException e) { + throw new RuntimeException(e); + } } public static String getUniKey() { String url = BASE_URL + "login/qr/key?timestamp=" + System.currentTimeMillis(); - return HttpRequest.getWithCookie(url, ""); + try { + return HttpRequest.getWithCookie(url, "").getBody(); + } catch (IOException e) { + throw new RuntimeException(e); + } } public static String generateQRCode(String key) { String url = BASE_URL + "login/qr/create?key=" + key + "&qrimg=true×tamp=" + System.currentTimeMillis(); - return HttpRequest.getWithCookie(url, ""); + try { + return HttpRequest.getWithCookie(url, "").getBody(); + } catch (IOException e) { + throw new RuntimeException(e); + } } public static String checkLoginStatus(String key) { String url = BASE_URL + "login/qr/check?key=" + key + "&noCookie=true×tamp=" + System.currentTimeMillis(); - return HttpRequest.getWithCookie(url, ""); + try { + return HttpRequest.getWithCookie(url, "").getBody(); + } catch (IOException e) { + throw new RuntimeException(e); + } } public static String getAnonymous() { String url = BASE_URL + "register/anonimous?timestamp=" + System.currentTimeMillis(); - return HttpRequest.getWithCookie(url, ""); + try { + return HttpRequest.getWithCookie(url, "").getBody(); + } catch (IOException e) { + throw new RuntimeException(e); + } } } diff --git a/shared/java/top/fpsmaster/ui/mc/GuiMultiplayer.java b/shared/java/top/fpsmaster/ui/mc/GuiMultiplayer.java index 9b141b81..4acc6753 100644 --- a/shared/java/top/fpsmaster/ui/mc/GuiMultiplayer.java +++ b/shared/java/top/fpsmaster/ui/mc/GuiMultiplayer.java @@ -30,6 +30,7 @@ import java.awt.*; import java.io.File; +import java.io.IOException; import java.util.List; public class GuiMultiplayer extends ScaledGuiScreen { @@ -102,7 +103,12 @@ public void initGui() { if (serverListRecommended.isEmpty()) { ClientThreadPool clientThreadPool = new ClientThreadPool(100); clientThreadPool.runnable(() -> { - String s = HttpRequest.get("https://service.fpsmaster.top/api/client/servers"); + String s = null; + try { + s = HttpRequest.get("https://service.fpsmaster.top/api/client/servers").getBody(); + } catch (IOException e) { + throw new RuntimeException(e); + } JsonObject jsonObject = gson.fromJson(s, JsonObject.class); jsonObject.get("data").getAsJsonArray().forEach(e -> { serverListRecommended.add(new ServerListEntry(this, new ServerData(e.getAsJsonObject().get("name").getAsString() + " - " + e.getAsJsonObject().get("description").getAsString(), e.getAsJsonObject().get("address").getAsString(), false))); diff --git a/shared/java/top/fpsmaster/ui/screens/oobe/impls/Login.java b/shared/java/top/fpsmaster/ui/screens/oobe/impls/Login.java index d682fb60..44010d2d 100644 --- a/shared/java/top/fpsmaster/ui/screens/oobe/impls/Login.java +++ b/shared/java/top/fpsmaster/ui/screens/oobe/impls/Login.java @@ -4,6 +4,7 @@ import net.minecraft.client.Minecraft; import net.minecraft.client.gui.ScaledResolution; import top.fpsmaster.FPSMaster; +import top.fpsmaster.exception.AccountException; import top.fpsmaster.exception.ExceptionHandler; import top.fpsmaster.exception.FileException; import top.fpsmaster.exception.NetworkException; @@ -57,11 +58,7 @@ public Login(boolean isOOBE) { } else { Minecraft.getMinecraft().displayGuiScreen(new MainMenu()); } - } catch (NetworkException e) { - ExceptionHandler.handleNetworkException(e, "登录失败"); - msg = "网络错误: " + e.getMessage(); - msgbox = true; - } catch (Exception e) { + } catch (AccountException e) { ExceptionHandler.handle(e, "登录失败"); msg = "未知错误: " + e.getMessage(); msgbox = true; diff --git a/shared/java/top/fpsmaster/utils/os/HttpRequest.java b/shared/java/top/fpsmaster/utils/os/HttpRequest.java index 2bd76039..6a2d2a60 100644 --- a/shared/java/top/fpsmaster/utils/os/HttpRequest.java +++ b/shared/java/top/fpsmaster/utils/os/HttpRequest.java @@ -28,46 +28,70 @@ import java.util.Map; public final class HttpRequest { - // 共享线程安全的HTTP客户端 + // Shared thread-safe HTTP client private static final CloseableHttpClient HTTP_CLIENT = HttpClients.createDefault(); - // 默认超时设置(15秒) + // Default timeout settings (15 seconds) private static final int DEFAULT_TIMEOUT = 15000; - private HttpRequest() {} // 防止实例化 + // Response wrapper class + public static class HttpResponseResult { + private final int statusCode; + private final String body; + + public HttpResponseResult(int statusCode, String body) { + this.statusCode = statusCode; + this.body = body; + } + + public int getStatusCode() { + return statusCode; + } + + public String getBody() { + return body; + } + + public boolean isSuccess() { + return statusCode >= 200 && statusCode < 300; + } + } + + private HttpRequest() { + } // Prevent instantiation public static Gson gson() { return new GsonBuilder().setPrettyPrinting().disableHtmlEscaping().create(); } - // ================== GET 请求 ================== // - public static String get(String url) { + // ================== GET Requests ================== // + public static HttpResponseResult get(String url) throws IOException { return executeRequest(new HttpGet(url), null); } - public static String getWithCookie(String url, String cookie) { + public static HttpResponseResult getWithCookie(String url, String cookie) throws IOException { HttpGet request = new HttpGet(url); request.setHeader("Cookie", cookie.replace("\n", "")); return executeRequest(request, null); } - public static String get(String url, Map headers) { + public static HttpResponseResult get(String url, Map headers) throws IOException { return executeRequest(new HttpGet(url), headers); } - // ================== POST 请求 ================== // - public static String post(String url, String body) { + // ================== POST Requests ================== // + public static HttpResponseResult post(String url, String body) throws IOException { return post(url, body, "application/json"); } - public static String postJson(String url, JsonObject json) { + public static HttpResponseResult postJson(String url, JsonObject json) throws IOException { return post(url, json.toString(), "application/json"); } - public static String postJson(String url, JsonObject json, Map headers) { + public static HttpResponseResult postJson(String url, JsonObject json, Map headers) throws IOException { return post(url, json.toString(), "application/json", headers); } - public static String postForm(String url, Map params) { + public static HttpResponseResult postForm(String url, Map params) throws IOException { HttpPost request = new HttpPost(url); if (params != null && !params.isEmpty()) { List formData = new ArrayList<>(); @@ -77,10 +101,11 @@ public static String postForm(String url, Map params) { return executeRequest(request, null); } - private static String post(String url, String body, String contentType) { + private static HttpResponseResult post(String url, String body, String contentType) throws IOException { return post(url, body, contentType, null); } - private static String post(String url, String body, String contentType, Map headers) { + + private static HttpResponseResult post(String url, String body, String contentType, Map headers) throws IOException { HttpPost request = new HttpPost(url); if (headers != null) { headers.forEach(request::setHeader); @@ -93,8 +118,8 @@ private static String post(String url, String body, String contentType, Map { - downloadFile(url, filepath); - callback.run(); + boolean success = downloadFile(url, filepath); + if (success && callback != null) { + callback.run(); + } }).start(); } - // ================== 核心执行方法 ================== // - private static String executeRequest(HttpRequestBase request, Map headers) { - try { - // 设置请求配置和默认头 - request.setConfig(buildRequestConfig()); - addDefaultHeaders(request); + // ================== Core Execution Method ================== // + private static HttpResponseResult executeRequest(HttpRequestBase request, Map headers) throws IOException { + // Set request configuration and default headers + request.setConfig(buildRequestConfig()); + addDefaultHeaders(request); - // 添加自定义头部 - if (headers != null) { - headers.forEach(request::addHeader); - } - - // 执行请求并处理响应 - try (CloseableHttpResponse response = HTTP_CLIENT.execute(request)) { - return handleResponse(response, request.getURI().toString()); - } - } catch (Exception e) { - ClientLogger.error("Request failed: " + e.getMessage()); - return ""; + // Add custom headers + if (headers != null) { + headers.forEach(request::addHeader); } + CloseableHttpResponse response = HTTP_CLIENT.execute(request); + return handleResponse(response, request.getURI().toString()); } - // ================== 工具方法 ================== // + // ================== Utility Methods ================== // private static RequestConfig buildRequestConfig() { return RequestConfig.custom() .setConnectTimeout(DEFAULT_TIMEOUT) @@ -152,14 +173,11 @@ private static void addDefaultHeaders(HttpRequestBase request) { request.setHeader("Accept-Language", "en-US,en;q=0.9"); } - private static String handleResponse(HttpResponse response, String url) throws IOException { + private static HttpResponseResult handleResponse(HttpResponse response, String url) throws IOException { int statusCode = response.getStatusLine().getStatusCode(); HttpEntity entity = response.getEntity(); - if (statusCode < 200 || statusCode >= 300) { - throw new IOException("HTTP Error: " + statusCode + " for URL: " + url); - } - - return entity != null ? EntityUtils.toString(entity, StandardCharsets.UTF_8) : ""; + String body = entity != null ? EntityUtils.toString(entity, StandardCharsets.UTF_8) : ""; + return new HttpResponseResult(statusCode, body); } } \ No newline at end of file diff --git a/shared/java/top/fpsmaster/utils/thirdparty/github/UpdateChecker.java b/shared/java/top/fpsmaster/utils/thirdparty/github/UpdateChecker.java index 20b01930..7ab78870 100644 --- a/shared/java/top/fpsmaster/utils/thirdparty/github/UpdateChecker.java +++ b/shared/java/top/fpsmaster/utils/thirdparty/github/UpdateChecker.java @@ -3,8 +3,14 @@ import top.fpsmaster.utils.GitInfo; import top.fpsmaster.utils.os.HttpRequest; +import java.io.IOException; + public class UpdateChecker { public static String getLatestVersion() { - return HttpRequest.get("https://service.fpsmaster.top/api/github/latest/commit?branch=refs/heads/"+ GitInfo.getBranch()); + try { + return HttpRequest.get("https://service.fpsmaster.top/api/github/latest/commit?branch=refs/heads/"+ GitInfo.getBranch()).getBody(); + } catch (IOException e) { + throw new RuntimeException(e); + } } } \ No newline at end of file diff --git a/shared/java/top/fpsmaster/utils/thirdparty/microsoft/MicrosoftLogin.java b/shared/java/top/fpsmaster/utils/thirdparty/microsoft/MicrosoftLogin.java index 2719d3c3..318bbab7 100644 --- a/shared/java/top/fpsmaster/utils/thirdparty/microsoft/MicrosoftLogin.java +++ b/shared/java/top/fpsmaster/utils/thirdparty/microsoft/MicrosoftLogin.java @@ -76,7 +76,7 @@ public static void startLocalHttpServer() { tokenRequestParams.put("grant_type", "authorization_code"); tokenRequestParams.put("redirect_uri", REDIRECT_URI); - String oauthResponse = HttpRequest.postForm("https://login.live.com/oauth20_token.srf", tokenRequestParams); + String oauthResponse = HttpRequest.postForm("https://login.live.com/oauth20_token.srf", tokenRequestParams).getBody(); logDebug("OAuth Response: " + oauthResponse); JsonObject oauthJson = HttpRequest.gson().fromJson(oauthResponse, JsonObject.class); String accessToken = getJsonString(oauthJson, "access_token", "OAuth access token"); @@ -175,7 +175,7 @@ private static void continueMinecraftAuthentication(String xboxAccessToken) thro xboxAuthPayload.addProperty("RelyingParty", "http://auth.xboxlive.com"); xboxAuthPayload.addProperty("TokenType", "JWT"); - String xboxAuthResponse = HttpRequest.postJson("https://user.auth.xboxlive.com/user/authenticate", xboxAuthPayload); + String xboxAuthResponse = HttpRequest.postJson("https://user.auth.xboxlive.com/user/authenticate", xboxAuthPayload).getBody(); logDebug("Xbox Auth Response: " + xboxAuthResponse); JsonObject xboxAuthJson = HttpRequest.gson().fromJson(xboxAuthResponse, JsonObject.class); String xblToken = getJsonString(xboxAuthJson, "Token", "XBL Token"); @@ -195,7 +195,7 @@ private static void continueMinecraftAuthentication(String xboxAccessToken) thro xstsPayload.addProperty("RelyingParty", "rp://api.minecraftservices.com/"); xstsPayload.addProperty("TokenType", "JWT"); - String xstsResponse = HttpRequest.postJson("https://xsts.auth.xboxlive.com/xsts/authorize", xstsPayload); + String xstsResponse = HttpRequest.postJson("https://xsts.auth.xboxlive.com/xsts/authorize", xstsPayload).getBody(); logDebug("XSTS Response: " + xstsResponse); JsonObject xstsJson = HttpRequest.gson().fromJson(xstsResponse, JsonObject.class); @@ -222,7 +222,7 @@ private static void continueMinecraftAuthentication(String xboxAccessToken) thro JsonObject minecraftAuthPayload = new JsonObject(); minecraftAuthPayload.addProperty("identityToken", "XBL3.0 x=" + xstsUserhash + ";" + xstsToken); - String minecraftAuthResponse = HttpRequest.postJson("https://api.minecraftservices.com/authentication/login_with_xbox", minecraftAuthPayload); + String minecraftAuthResponse = HttpRequest.postJson("https://api.minecraftservices.com/authentication/login_with_xbox", minecraftAuthPayload).getBody(); logDebug("Minecraft Auth Response: " + minecraftAuthResponse); JsonObject minecraftAuthJson = HttpRequest.gson().fromJson(minecraftAuthResponse, JsonObject.class); String mcAccessToken = getJsonString(minecraftAuthJson, "access_token", "Minecraft access token"); @@ -235,7 +235,7 @@ private static void continueMinecraftAuthentication(String xboxAccessToken) thro Map profileHeaders = new HashMap<>(); profileHeaders.put("Authorization", "Bearer " + mcAccessToken); - String profileResponse = HttpRequest.get("https://api.minecraftservices.com/minecraft/profile", profileHeaders); + String profileResponse = HttpRequest.get("https://api.minecraftservices.com/minecraft/profile", profileHeaders).getBody(); logDebug("Minecraft Profile Response: " + profileResponse); JsonObject profileJson = HttpRequest.gson().fromJson(profileResponse, JsonObject.class); diff --git a/shared/java/top/fpsmaster/utils/thirdparty/openai/OpenAI.java b/shared/java/top/fpsmaster/utils/thirdparty/openai/OpenAI.java index a2fbdfeb..fed737b5 100644 --- a/shared/java/top/fpsmaster/utils/thirdparty/openai/OpenAI.java +++ b/shared/java/top/fpsmaster/utils/thirdparty/openai/OpenAI.java @@ -43,7 +43,7 @@ public String requestNewAnswer(String question, JsonArray msgs) { String text; try { - text = HttpRequest.postJson(baseUrl + "/chat/completions", body, hashMap); + text = HttpRequest.postJson(baseUrl + "/chat/completions", body, hashMap).getBody(); } catch (Exception e) { throw new RuntimeException(e); } @@ -74,7 +74,7 @@ public String requestNewAnswer(String question) { String text; try { - text = HttpRequest.postJson(baseUrl + "/chat/completions", body, hashMap); + text = HttpRequest.postJson(baseUrl + "/chat/completions", body, hashMap).getBody(); } catch (Exception e) { ClientLogger.error("Translator", e.toString()); return ""; @@ -105,7 +105,7 @@ public static String[] requestClientAI(String prompt, String model, JsonArray me put("model", model); put("prompt", prompt); }} - ); + ).getBody(); if (!sendPostRequest.isEmpty()) { JsonObject json = new JsonParser().parse(sendPostRequest).getAsJsonObject(); diff --git a/v1.8.9/src/main/java/top/fpsmaster/wrapper/SkinProvider.java b/v1.8.9/src/main/java/top/fpsmaster/wrapper/SkinProvider.java index 1d190050..61e5f2dc 100644 --- a/v1.8.9/src/main/java/top/fpsmaster/wrapper/SkinProvider.java +++ b/v1.8.9/src/main/java/top/fpsmaster/wrapper/SkinProvider.java @@ -10,6 +10,7 @@ import top.fpsmaster.forge.api.INetworkPlayerInfo; import top.fpsmaster.interfaces.ProviderManager; import top.fpsmaster.interfaces.game.ISkinProvider; +import top.fpsmaster.modules.logger.ClientLogger; import top.fpsmaster.utils.os.HttpRequest; import java.io.IOException; @@ -28,8 +29,18 @@ public void updateSkin(String name, String uuid, String skin) { } } - String json = null; - json = HttpRequest.get("https://api.mojang.com/users/profiles/minecraft/" + skin); + HttpRequest.HttpResponseResult httpResponseResult = null; + try { + httpResponseResult = HttpRequest.get("https://api.mojang.com/users/profiles/minecraft/" + skin); + } catch (IOException e) { + throw new RuntimeException(e); + } + if (!httpResponseResult.isSuccess()) { + ClientLogger.error("Failed to get skin " + skin + " for player " + name + " " + httpResponseResult.getStatusCode() + " " + httpResponseResult.getBody()); + return; + } + + String json = httpResponseResult.getBody(); Gson gson = new GsonBuilder().create(); JsonObject jsonObject = gson.fromJson(json, JsonObject.class); if (jsonObject != null && jsonObject.has("id")) { From 2910799aef35662f957ed9e91837f8a4b2316fb2 Mon Sep 17 00:00:00 2001 From: SuperSkidder Date: Fri, 18 Jul 2025 17:24:40 +0800 Subject: [PATCH 127/193] fix: leveltag health duplicated render --- shared/java/top/fpsmaster/features/impl/utility/LevelTag.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/shared/java/top/fpsmaster/features/impl/utility/LevelTag.java b/shared/java/top/fpsmaster/features/impl/utility/LevelTag.java index ec26a4ed..28c1f897 100644 --- a/shared/java/top/fpsmaster/features/impl/utility/LevelTag.java +++ b/shared/java/top/fpsmaster/features/impl/utility/LevelTag.java @@ -30,6 +30,8 @@ public LevelTag() { } public static void renderHealth(Entity entityIn, String str, double x, double y, double z, int maxDistance) { + if(!str.contains(entityIn.getName())) + return; double d = entityIn.getDistanceSqToEntity(mc.getRenderManager().livingPlayer); if (d < 100) { float f = 1.6F; From 8bfb25bf39107a8bc336193603d9752a4a6e7a81 Mon Sep 17 00:00:00 2001 From: SuperSkidder Date: Fri, 18 Jul 2025 17:31:57 +0800 Subject: [PATCH 128/193] fix: draw health of bots --- .../java/top/fpsmaster/features/impl/utility/LevelTag.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/shared/java/top/fpsmaster/features/impl/utility/LevelTag.java b/shared/java/top/fpsmaster/features/impl/utility/LevelTag.java index 28c1f897..bf9603ef 100644 --- a/shared/java/top/fpsmaster/features/impl/utility/LevelTag.java +++ b/shared/java/top/fpsmaster/features/impl/utility/LevelTag.java @@ -6,6 +6,7 @@ import net.minecraft.client.renderer.WorldRenderer; import net.minecraft.client.renderer.vertex.DefaultVertexFormats; import net.minecraft.entity.Entity; +import net.minecraft.entity.player.EntityPlayer; import net.minecraft.util.ResourceLocation; import org.lwjgl.opengl.GL11; import top.fpsmaster.FPSMaster; @@ -30,7 +31,9 @@ public LevelTag() { } public static void renderHealth(Entity entityIn, String str, double x, double y, double z, int maxDistance) { - if(!str.contains(entityIn.getName())) + if(!str.contains(entityIn.getName()) || !(entityIn instanceof EntityPlayer)) + return; + if (str.contains("[NPC]")) return; double d = entityIn.getDistanceSqToEntity(mc.getRenderManager().livingPlayer); if (d < 100) { From 437f91ff76f9b53799d617242274a078d1fa36db Mon Sep 17 00:00:00 2001 From: SuperSkidder Date: Fri, 18 Jul 2025 17:38:31 +0800 Subject: [PATCH 129/193] fix: auto gg english doesn't work --- shared/java/top/fpsmaster/features/impl/utility/AutoGG.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/shared/java/top/fpsmaster/features/impl/utility/AutoGG.java b/shared/java/top/fpsmaster/features/impl/utility/AutoGG.java index 66c922a4..cd005626 100644 --- a/shared/java/top/fpsmaster/features/impl/utility/AutoGG.java +++ b/shared/java/top/fpsmaster/features/impl/utility/AutoGG.java @@ -32,7 +32,7 @@ public void onPacket(EventPacket event) { String componentValue = ProviderManager.packetChat.getChatComponent(event.packet).toString(); boolean hasPlayCommand = componentValue.contains("ClickEvent{action=RUN_COMMAND, value='/play "); String chatMessage = ProviderManager.packetChat.getUnformattedText(event.packet); - boolean hasEndInformation = StringUtils.stripControlCodes(chatMessage).contains(" 胜利者 ") || StringUtils.stripControlCodes(chatMessage).startsWith(" Winner "); + boolean hasEndInformation = StringUtils.stripControlCodes(chatMessage).contains(" 胜利者 ") || StringUtils.stripControlCodes(chatMessage).startsWith(" Winner "); if (hasEndInformation) { Utility.sendChatMessage("/ac " + message.getValue()); } From b58634a8b9d6ceffd5664d826d1e412e5f2b941c Mon Sep 17 00:00:00 2001 From: SuperSkidder Date: Fri, 18 Jul 2025 18:08:00 +0800 Subject: [PATCH 130/193] feat: add a new style for target display --- .../impl/interfaces/TargetDisplay.java | 2 +- .../ui/custom/impl/TargetHUDComponent.java | 73 ++++++++++++------- .../top/fpsmaster/utils/awt/AWTUtils.java | 71 ++++++++++++++++++ .../fpsmaster/utils/render/Render2DUtils.java | 7 ++ .../assets/minecraft/client/lang/en_us.lang | 1 + .../assets/minecraft/client/lang/zh_cn.lang | 1 + 6 files changed, 126 insertions(+), 29 deletions(-) diff --git a/shared/java/top/fpsmaster/features/impl/interfaces/TargetDisplay.java b/shared/java/top/fpsmaster/features/impl/interfaces/TargetDisplay.java index f3788100..3a87c3f5 100644 --- a/shared/java/top/fpsmaster/features/impl/interfaces/TargetDisplay.java +++ b/shared/java/top/fpsmaster/features/impl/interfaces/TargetDisplay.java @@ -19,7 +19,7 @@ public class TargetDisplay extends InterfaceModule { private final ModeSetting targetESP = new ModeSetting("TargetESP", 0, "glow", "none"); private final ColorSetting espColor = new ColorSetting("EspColor", new Color(255, 255, 255, 255), () -> !targetESP.isMode("none")); - public static ModeSetting targetHUD = new ModeSetting("TargetHUD", 0, "simple", "none"); + public static ModeSetting targetHUD = new ModeSetting("TargetHUD", 0, "simple", "fancy", "none"); public static BooleanSetting omit = new BooleanSetting("OmitName", true); public static EntityPlayer target; public static long lastHit; diff --git a/shared/java/top/fpsmaster/ui/custom/impl/TargetHUDComponent.java b/shared/java/top/fpsmaster/ui/custom/impl/TargetHUDComponent.java index 7ebb202b..079c2c2f 100644 --- a/shared/java/top/fpsmaster/ui/custom/impl/TargetHUDComponent.java +++ b/shared/java/top/fpsmaster/ui/custom/impl/TargetHUDComponent.java @@ -15,7 +15,7 @@ public class TargetHUDComponent extends Component { private float animation = 0f; - private float healthWidth = 0f; + private float healthPer = 0f; private final ColorAnimation colorAnimation = new ColorAnimation(); public TargetHUDComponent() { @@ -25,8 +25,6 @@ public TargetHUDComponent() { @Override public void draw(float x, float y) { super.draw(x, y); - - if (TargetDisplay.targetHUD.getMode() != 0) return; if (TargetDisplay.target == null) return; // Get the target or player if chat is open @@ -34,43 +32,62 @@ public void draw(float x, float y) { if (Utility.mc.ingameGUI.getChatGUI().getChatOpen()) { target1 = ProviderManager.mcProvider.getPlayer(); } - if (target1 == null) return; - // Set width and height String name = target1.getDisplayName().getFormattedText(); - - if (name.length() > 12 && TargetDisplay.omit.getValue()) { - name = name.substring(0, 10) + ".."; + if (name.length() > 20 && TargetDisplay.omit.getValue()) { + name = name.substring(0, 20) + ".."; } - width = (30 + FPSMaster.fontManager.s16.getStringWidth(name)); - height = 30f; - // Update animation based on target's health and last hit time animation = (TargetDisplay.target.isDead || (System.currentTimeMillis() - TargetDisplay.lastHit > 5000 && target1 != ProviderManager.mcProvider.getPlayer())) ? (float) AnimationUtils.base(animation, 0.0, 0.1) - : (float) AnimationUtils.base(animation, 80.0, 0.1); + : (float) AnimationUtils.base(animation, 1, 0.1); - // Health width float health = target1.getHealth(); float maxHealth = target1.getMaxHealth(); - healthWidth = (float) AnimationUtils.base(healthWidth, (health / maxHealth), 0.1); - // Set color based on health percentage - if (health >= maxHealth * 0.8) { - colorAnimation.base(new Color(50, 255, 55, (int) animation)); - } else if (health > maxHealth * 0.5) { - colorAnimation.base(new Color(255, 255, 55, (int) animation)); - } else { - colorAnimation.base(new Color(255, 55, 55, (int) animation)); - } + healthPer = (float) AnimationUtils.base(healthPer, (health / maxHealth), 0.1); + + if (TargetDisplay.targetHUD.getMode() == 0) { + width = (30 + FPSMaster.fontManager.s16.getStringWidth(name)); + height = 30f; + + // Set color based on health percentage + if (health >= maxHealth * 0.8) { + colorAnimation.base(new Color(50, 255, 55, (int) (animation * 80))); + } else if (health > maxHealth * 0.5) { + colorAnimation.base(new Color(255, 255, 55, (int) (animation * 80))); + } else { + colorAnimation.base(new Color(255, 55, 55, (int) (animation * 80))); + } + + // Draw elements if animation is greater than 1 + if (animation > 0.05) { + Render2DUtils.drawOptimizedRoundedRect(x, y, width, height, new Color(0, 0, 0, (int) animation * 80)); + Render2DUtils.drawOptimizedRoundedRect(x, y, healthPer * width, height, colorAnimation.getColor()); + FPSMaster.fontManager.s16.drawStringWithShadow(name, x + 27, y + 5, -1); + Render2DUtils.drawPlayerHead(target1, x + 5, y + 5, 20, 20); + } + } else if (TargetDisplay.targetHUD.getValue() == 1) { + width = (50 + FPSMaster.fontManager.s16.getStringWidth(name)); + height = 40f; + + // Set color based on health percentage + if (health >= maxHealth * 0.8) { + colorAnimation.base(new Color(50, 255, 155, (int) (animation * 220))); + } else if (health > maxHealth * 0.5) { + colorAnimation.base(new Color(255, 255, 85, (int) (animation * 220))); + } else { + colorAnimation.base(new Color(255, 75, 75, (int) (animation * 220))); + } - // Draw elements if animation is greater than 1 - if (animation > 1) { - Render2DUtils.drawOptimizedRoundedRect(x, y, width, height, new Color(0, 0, 0, (int) animation)); - Render2DUtils.drawOptimizedRoundedRect(x, y, healthWidth * width, height, colorAnimation.getColor()); - FPSMaster.fontManager.s16.drawStringWithShadow(name, x + 27, y + 5, -1); - Render2DUtils.drawPlayerHead(target1, x + 5, y + 5, 20, 20); + // Draw elements if animation is greater than 1 + if (animation > 0.05) { + Render2DUtils.drawRoundedRectImage(x, y, width, height, 8, new Color(0, 0, 0, (int) (animation * 120))); + Render2DUtils.drawRoundedRectImage(x + 10, y + 30, healthPer * (width - 20), 4, 2, colorAnimation.getColor()); + FPSMaster.fontManager.s18.drawStringWithShadow(name, x + 24, y + 8, new Color(255, 255, 255, (int) (animation * 255)).getRGB()); + Render2DUtils.drawPlayerHead(target1, x + 10, y + 8, 12, 12); + } } } } diff --git a/shared/java/top/fpsmaster/utils/awt/AWTUtils.java b/shared/java/top/fpsmaster/utils/awt/AWTUtils.java index 7dda72d7..536194a6 100644 --- a/shared/java/top/fpsmaster/utils/awt/AWTUtils.java +++ b/shared/java/top/fpsmaster/utils/awt/AWTUtils.java @@ -14,6 +14,77 @@ public class AWTUtils { private static final HashMap generated = new HashMap<>(); private static final HashMap generatedFull = new HashMap<>(); + public static ResourceLocation generateRoundImage(int width, int height, int radius, Color borderColor, int borderWidth) { + if (width <= 0 || height <= 0 || radius < 0 || borderWidth < 0) { + throw new IllegalArgumentException("Width, height must be positive; radius and borderWidth must be non-negative"); + } + + String key = width + "/" + height + "/" + radius + "/" + borderWidth + "/" + borderColor.getRGB(); + return generatedFull.computeIfAbsent(key, r -> { + int scaledWidth = width * 2; + int scaledHeight = height * 2; + int scaledRadius = radius * 2; + int scaledBorderWidth = borderWidth * 2; + + try { + BufferedImage bufferedImage = new BufferedImage(scaledWidth, scaledHeight, BufferedImage.TYPE_INT_ARGB); + Graphics2D graphics2D = bufferedImage.createGraphics(); + + graphics2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + + // Clear with transparent background + graphics2D.setColor(new Color(0, 0, 0, 0)); + graphics2D.fillRect(0, 0, scaledWidth, scaledHeight); + + graphics2D.setComposite(AlphaComposite.SrcOver); + + // Draw the border if borderWidth > 0 + if (borderWidth > 0 && borderColor != null) { + graphics2D.setColor(borderColor); + RoundRectangle2D borderRect = new RoundRectangle2D.Float( + 0, + 0, + scaledWidth, + scaledHeight, + scaledRadius, + scaledRadius + ); + graphics2D.fill(borderRect); + } + + // Draw the inner white rectangle (accounting for border) + int innerX = scaledBorderWidth; + int innerY = scaledBorderWidth; + int innerWidth = scaledWidth - (scaledBorderWidth * 2); + int innerHeight = scaledHeight - (scaledBorderWidth * 2); + int innerRadius = Math.max(0, scaledRadius - (scaledBorderWidth * 2)); + + graphics2D.setColor(Color.WHITE); + RoundRectangle2D innerRect = new RoundRectangle2D.Float( + innerX, + innerY, + innerWidth, + innerHeight, + innerRadius, + innerRadius + ); + graphics2D.fill(innerRect); + + Minecraft mc = Minecraft.getMinecraft(); + if (mc == null || mc.getTextureManager() == null) { + return null; + } + graphics2D.dispose(); + + return mc.getTextureManager() + .getDynamicTextureLocation(r + "_full", new DynamicTexture(bufferedImage)); + } catch (Exception e) { + ClientLogger.error("An error occurred while generating round texture: " + r); + e.printStackTrace(); + return null; + } + }); + } public static ResourceLocation generateRoundImage(int width, int height, int radius) { if (width <= 0 || height <= 0 || radius < 0) { diff --git a/shared/java/top/fpsmaster/utils/render/Render2DUtils.java b/shared/java/top/fpsmaster/utils/render/Render2DUtils.java index 261616ec..c3ecd745 100644 --- a/shared/java/top/fpsmaster/utils/render/Render2DUtils.java +++ b/shared/java/top/fpsmaster/utils/render/Render2DUtils.java @@ -103,6 +103,11 @@ public static void drawRoundedRectImage(float x, float y, float width, float hei Render2DUtils.drawImage(res, x, y, width, height, color); } + public static void drawRoundedRectImage(float x, float y, float width, float height, int radius, Color color, int borderWidth, Color borderColor) { + ResourceLocation res = AWTUtils.generateRoundImage((int) width, (int) height, radius, borderColor, borderWidth); + Render2DUtils.drawImage(res, x, y, width, height, color); + } + public static void drawRect(float x, float y, float width, float height, Color color) { drawRect(x, y, width, height, color.getRGB()); } @@ -218,9 +223,11 @@ public static void scaleStart(float x, float y, float scale) { glScalef(scale, scale, 1); glTranslatef(-x, -y, 0); } + public static void scaleEnd() { glPopMatrix(); } + public static float[] getFixedBounds() { ScaledResolution sr = new ScaledResolution(mc); int scaleFactor; diff --git a/shared/resources/assets/minecraft/client/lang/en_us.lang b/shared/resources/assets/minecraft/client/lang/en_us.lang index e5566a61..f91b1afd 100644 --- a/shared/resources/assets/minecraft/client/lang/en_us.lang +++ b/shared/resources/assets/minecraft/client/lang/en_us.lang @@ -371,6 +371,7 @@ targetdisplay.targetesp.none=None targetdisplay.targethud=Target HUD targetdisplay.targethud.none=None targetdisplay.targethud.simple=Simple +targetdisplay.targethud.fancy=Fancy targetdisplay.espcolor=ESP Color targetdisplay.roundradius=Corner Radius targetdisplay.background=Show Background diff --git a/shared/resources/assets/minecraft/client/lang/zh_cn.lang b/shared/resources/assets/minecraft/client/lang/zh_cn.lang index 8dcee8af..99495b04 100644 --- a/shared/resources/assets/minecraft/client/lang/zh_cn.lang +++ b/shared/resources/assets/minecraft/client/lang/zh_cn.lang @@ -374,6 +374,7 @@ targetdisplay.targetesp.none=不显示 targetdisplay.targethud=目标显示 targetdisplay.targethud.none=不显示 targetdisplay.targethud.simple=简单 +targetdisplay.targethud.fancy=华丽 targetdisplay.espcolor=ESP颜色 targetdisplay.roundradius=圆角半径 targetdisplay.background=背景 From f6307ef8471a2801e6139a7dea7206267649aa3d Mon Sep 17 00:00:00 2001 From: SuperSkidder Date: Fri, 18 Jul 2025 18:13:14 +0800 Subject: [PATCH 131/193] fix: autogg --- shared/java/top/fpsmaster/features/impl/utility/AutoGG.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/shared/java/top/fpsmaster/features/impl/utility/AutoGG.java b/shared/java/top/fpsmaster/features/impl/utility/AutoGG.java index cd005626..deb07f00 100644 --- a/shared/java/top/fpsmaster/features/impl/utility/AutoGG.java +++ b/shared/java/top/fpsmaster/features/impl/utility/AutoGG.java @@ -32,7 +32,7 @@ public void onPacket(EventPacket event) { String componentValue = ProviderManager.packetChat.getChatComponent(event.packet).toString(); boolean hasPlayCommand = componentValue.contains("ClickEvent{action=RUN_COMMAND, value='/play "); String chatMessage = ProviderManager.packetChat.getUnformattedText(event.packet); - boolean hasEndInformation = StringUtils.stripControlCodes(chatMessage).contains(" 胜利者 ") || StringUtils.stripControlCodes(chatMessage).startsWith(" Winner "); + boolean hasEndInformation = StringUtils.stripControlCodes(chatMessage).contains(" 胜利者 ") || StringUtils.stripControlCodes(chatMessage).contains(" Winner - "); if (hasEndInformation) { Utility.sendChatMessage("/ac " + message.getValue()); } From 50192e5491af785ae7a652aa9518bc7a11cf24c4 Mon Sep 17 00:00:00 2001 From: SuperSkidder Date: Fri, 18 Jul 2025 18:46:34 +0800 Subject: [PATCH 132/193] feat: add scaling for some components fix: fix a render bug of components fix: fix font shadow value display logic --- .../features/impl/InterfaceModule.java | 2 +- .../top/fpsmaster/ui/custom/Component.java | 14 +++++++++----- .../custom/impl/InventoryDisplayComponent.java | 15 ++++++++++++--- .../ui/custom/impl/PotionDisplayComponent.java | 18 ++++++++++++------ .../ui/custom/impl/ReachDisplayComponent.java | 1 + .../ui/custom/impl/SprintComponent.java | 1 + 6 files changed, 36 insertions(+), 15 deletions(-) diff --git a/shared/java/top/fpsmaster/features/impl/InterfaceModule.java b/shared/java/top/fpsmaster/features/impl/InterfaceModule.java index ae1b4810..4498dbad 100644 --- a/shared/java/top/fpsmaster/features/impl/InterfaceModule.java +++ b/shared/java/top/fpsmaster/features/impl/InterfaceModule.java @@ -13,7 +13,7 @@ public class InterfaceModule extends Module { public BooleanSetting rounded = new BooleanSetting("Round", true); public NumberSetting roundRadius = new NumberSetting("RoundRadius", 3, 0, 30, 1, () -> rounded.getValue()); public BooleanSetting betterFont = new BooleanSetting("BetterFont", false); - public BooleanSetting fontShadow = new BooleanSetting("FontShadow", true, () -> betterFont.getValue()); + public BooleanSetting fontShadow = new BooleanSetting("FontShadow", true); public BooleanSetting bg = new BooleanSetting("Background", true); public ColorSetting backgroundColor = new ColorSetting("BackgroundColor", new Color(0, 0, 0, 0), () -> bg.getValue()); public NumberSetting spacing = new NumberSetting("Spacing",0,0,3,1); diff --git a/shared/java/top/fpsmaster/ui/custom/Component.java b/shared/java/top/fpsmaster/ui/custom/Component.java index 110b2c57..45129d7b 100644 --- a/shared/java/top/fpsmaster/ui/custom/Component.java +++ b/shared/java/top/fpsmaster/ui/custom/Component.java @@ -99,7 +99,7 @@ public void display(int mouseX, int mouseY) { AnimationUtils.base(alpha, 50.0, 0.1f) : AnimationUtils.base(alpha, 0.0, 0.1f)); Render2DUtils.drawOptimizedRoundedRect(rX - 2, rY - 2, scaledWidth + 4, scaledHeight + 4, new Color(0, 0, 0, (int) alpha)); - GL11.glColor4f(1,1,1,1); + GL11.glColor4f(1, 1, 1, 1); if (!Mouse.isButtonDown(0)) { @@ -131,11 +131,11 @@ public void display(int mouseX, int mouseY) { } public void scaleUp() { - if (scale < 2.5f) scale += 0.1f; + if (scale < 2.5f) scale = (int) (scale * 10 + 1) / 10f; } public void scaleDown() { - if (scale > 0.5f) scale -= 0.1f; + if (scale > 0.5f) scale = (int) (scale * 10 - 1) / 10f; } private void move(int x, int y) { @@ -221,9 +221,12 @@ public void drawString(int fontSize, boolean bold, String text, float x, float y GL11.glPushMatrix(); GL11.glTranslated(x, y, 0.0); GL11.glScaled(scaled, scaled, 1.0); - if (mod.fontShadow.getValue()) + if (mod.fontShadow.getValue()) { ProviderManager.mcProvider.getFontRenderer().drawStringWithShadow(text, 0f, 0f, color); - else ProviderManager.mcProvider.drawString(text, 0f, 0f, color); + } else { + GL11.glColor4f(1,1,1,1); + ProviderManager.mcProvider.drawString(text, 0f, 0f, color); + } GL11.glPopMatrix(); } } @@ -232,6 +235,7 @@ public float getStringWidth(int fontSize, String name) { UFontRenderer font = FPSMaster.fontManager.getFont(fontSize); return mod.betterFont.getValue() ? font.getStringWidth(name) : ProviderManager.mcProvider.getFontRenderer().getStringWidth(name); } + public float getStringHeight(int fontSize) { UFontRenderer font = FPSMaster.fontManager.getFont(fontSize); return mod.betterFont.getValue() ? font.getHeight() : ProviderManager.mcProvider.getFontRenderer().FONT_HEIGHT; diff --git a/shared/java/top/fpsmaster/ui/custom/impl/InventoryDisplayComponent.java b/shared/java/top/fpsmaster/ui/custom/impl/InventoryDisplayComponent.java index 6d3d9142..099e5757 100644 --- a/shared/java/top/fpsmaster/ui/custom/impl/InventoryDisplayComponent.java +++ b/shared/java/top/fpsmaster/ui/custom/impl/InventoryDisplayComponent.java @@ -4,6 +4,7 @@ import net.minecraft.client.renderer.RenderHelper; import net.minecraft.inventory.Slot; import net.minecraft.item.ItemStack; +import org.lwjgl.opengl.GL11; import top.fpsmaster.features.impl.interfaces.InventoryDisplay; import top.fpsmaster.interfaces.ProviderManager; import top.fpsmaster.ui.custom.Component; @@ -14,6 +15,7 @@ public class InventoryDisplayComponent extends Component { public InventoryDisplayComponent() { super(InventoryDisplay.class); + allowScale = true; } @Override @@ -24,7 +26,10 @@ public void draw(float x, float y) { int count = 0; int count2 = 0; int linecount = 0; - + GlStateManager.pushMatrix(); + GL11.glTranslated(x, y, 0); + if (scale != 1) + GL11.glScaled(scale, scale, 0); for (Slot slot : ProviderManager.mcProvider.getPlayer().inventoryContainer.inventorySlots) { count2++; @@ -34,10 +39,11 @@ public void draw(float x, float y) { if (slot.getStack() != null) { ItemStack itemStack = slot.getStack(); - int x1 = (int) (x + count * 18); - int y1 = (int) (y + linecount * 20); + int x1 = count * 18; + int y1 = linecount * 20; GlStateManager.disableCull(); + GlStateManager.enableBlend(); GlStateManager.disableBlend(); RenderHelper.enableGUIStandardItemLighting(); mc.getRenderItem().renderItemAndEffectIntoGUI(itemStack, x1, y1); @@ -57,6 +63,9 @@ public void draw(float x, float y) { linecount++; } } + if (scale != 1) + GL11.glScaled(1 / scale, 1 / scale, 0); + GlStateManager.popMatrix(); width = 164f; height = 64f; diff --git a/shared/java/top/fpsmaster/ui/custom/impl/PotionDisplayComponent.java b/shared/java/top/fpsmaster/ui/custom/impl/PotionDisplayComponent.java index df299a55..d72ff46a 100644 --- a/shared/java/top/fpsmaster/ui/custom/impl/PotionDisplayComponent.java +++ b/shared/java/top/fpsmaster/ui/custom/impl/PotionDisplayComponent.java @@ -5,6 +5,7 @@ import net.minecraft.client.resources.I18n; import net.minecraft.potion.PotionEffect; import net.minecraft.util.ResourceLocation; +import org.lwjgl.opengl.GL11; import top.fpsmaster.features.impl.interfaces.PotionDisplay; import top.fpsmaster.interfaces.ProviderManager; import top.fpsmaster.ui.custom.Component; @@ -16,6 +17,7 @@ public class PotionDisplayComponent extends Component { public PotionDisplayComponent() { super(PotionDisplay.class); + allowScale = true; } public static final float POTION_HEIGHT = 36f; @@ -31,8 +33,8 @@ public void draw(float x, float y) { String duration = (effect.getDuration() / 20 / 60) + "min" + effect.getDuration() / 20 % 60 + "s"; float width = Math.max(getStringWidth(18, title), getStringWidth(16, duration)) + 36; drawRect(x, dY, width + 10, 32f, mod.backgroundColor.getColor()); - drawString(18, title, x + 34, dY + 5, -1); - drawString(16, duration, x + 34, dY + 18, new Color(200, 200, 200).getRGB()); + drawString(18, title, x + 34 * scale, dY + 5, -1); + drawString(16, duration, x + 34 * scale, dY + 5 + 13 * scale, new Color(200, 200, 200).getRGB()); // Draw potion image ResourceLocation res = new ResourceLocation("textures/gui/container/inventory.png"); @@ -42,9 +44,11 @@ public void draw(float x, float y) { int potion = ProviderManager.utilityProvider.getPotionIconIndex(effect); // Draw potion + GL11.glTranslatef((int) (x + 8), (int) (dY + 8), 0); + GL11.glScalef(scale, scale, 0); Gui.drawModalRectWithCustomSizedTexture( - (int) (x + 8), - (int) (dY + 8), + 0, + 0, (potion % 8 * 18) + 1, (198 + potion / 8 * 18) + 1, 16, @@ -52,13 +56,15 @@ public void draw(float x, float y) { 256f, 256f ); + GL11.glScalef(1 / scale, 1 / scale, 0); + GL11.glTranslatef(-(int) (x + 8), -(int) (dY + 8), 0); - dY += (index * mod.spacing.getValue().intValue()) + POTION_HEIGHT + mod.spacing.getValue().intValue(); + dY += (index * mod.spacing.getValue().intValue() * 2 + POTION_HEIGHT) * scale; this.width = width + 12; index++; } GlStateManager.popMatrix(); - height = dY - y - 4; + height = index * (mod.spacing.getValue().intValue() + POTION_HEIGHT); } } diff --git a/shared/java/top/fpsmaster/ui/custom/impl/ReachDisplayComponent.java b/shared/java/top/fpsmaster/ui/custom/impl/ReachDisplayComponent.java index b929be6a..db9ff037 100644 --- a/shared/java/top/fpsmaster/ui/custom/impl/ReachDisplayComponent.java +++ b/shared/java/top/fpsmaster/ui/custom/impl/ReachDisplayComponent.java @@ -7,6 +7,7 @@ public class ReachDisplayComponent extends Component { public ReachDisplayComponent() { super(ReachDisplay.class); + allowScale = true; } @Override diff --git a/shared/java/top/fpsmaster/ui/custom/impl/SprintComponent.java b/shared/java/top/fpsmaster/ui/custom/impl/SprintComponent.java index 8afe7b79..31b12410 100644 --- a/shared/java/top/fpsmaster/ui/custom/impl/SprintComponent.java +++ b/shared/java/top/fpsmaster/ui/custom/impl/SprintComponent.java @@ -8,6 +8,7 @@ public class SprintComponent extends Component{ public SprintComponent() { super(Sprint.class); + allowScale = true; } @Override From 0d4c962c8fc7a7075a2a8f6a0690fc9afe086652 Mon Sep 17 00:00:00 2001 From: SuperSkidder Date: Sat, 19 Jul 2025 00:43:13 +0800 Subject: [PATCH 133/193] fix: optifine capes doesn't show --- .../fpsmaster/forge/mixin/MixinAbstractClientPlayer.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinAbstractClientPlayer.java b/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinAbstractClientPlayer.java index c2bcb548..d530de9f 100644 --- a/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinAbstractClientPlayer.java +++ b/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinAbstractClientPlayer.java @@ -18,7 +18,6 @@ @Mixin(AbstractClientPlayer.class) public abstract class MixinAbstractClientPlayer extends MixinEntityPlayer { - private ResourceLocation fpsmasterCape; @Inject(method = "getFovModifier", at = @At("HEAD"), cancellable = true) public void customFov(CallbackInfoReturnable cir) { @@ -65,7 +64,8 @@ public void customFov(CallbackInfoReturnable cir) { public void getLocationCape(CallbackInfoReturnable cir) { EventCapeLoading event = new EventCapeLoading(playerInfo.getGameProfile().getName(), (AbstractClientPlayer) (Object) this); EventDispatcher.dispatchEvent(event); - fpsmasterCape = event.cape; - cir.setReturnValue(fpsmasterCape); + if (event.cape != null) { + cir.setReturnValue(event.cape); + } } } From 44f11db8081e94ace0d7052b676597dfbfc82d53 Mon Sep 17 00:00:00 2001 From: SuperSkidder Date: Sat, 19 Jul 2025 00:59:58 +0800 Subject: [PATCH 134/193] fix: skin changer doesn't update when reload world --- .../features/impl/utility/SkinChanger.java | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/shared/java/top/fpsmaster/features/impl/utility/SkinChanger.java b/shared/java/top/fpsmaster/features/impl/utility/SkinChanger.java index 393c7c15..9cceace2 100644 --- a/shared/java/top/fpsmaster/features/impl/utility/SkinChanger.java +++ b/shared/java/top/fpsmaster/features/impl/utility/SkinChanger.java @@ -1,7 +1,12 @@ package top.fpsmaster.features.impl.utility; +import net.minecraft.client.multiplayer.WorldClient; +import net.minecraft.network.login.server.S02PacketLoginSuccess; +import net.minecraft.network.play.server.S0CPacketSpawnPlayer; +import net.minecraft.world.World; import top.fpsmaster.FPSMaster; import top.fpsmaster.event.Subscribe; +import top.fpsmaster.event.events.EventPacket; import top.fpsmaster.event.events.EventTick; import top.fpsmaster.features.manager.Category; import top.fpsmaster.features.manager.Module; @@ -9,6 +14,8 @@ import top.fpsmaster.interfaces.ProviderManager; import top.fpsmaster.modules.account.AccountManager; +import static top.fpsmaster.utils.Utility.mc; + public class SkinChanger extends Module { private final TextSetting skinName = new TextSetting("Skin", ""); @@ -24,6 +31,7 @@ public class SkinChanger extends Module { }); public static boolean using = false; + private WorldClient world; public SkinChanger() { super("SkinChanger", Category.Utility); @@ -42,14 +50,15 @@ public void onEnable() { } } + @Subscribe public void onTick(EventTick e) { if (ProviderManager.mcProvider.getPlayer() != null && ProviderManager.mcProvider.getPlayer().ticksExisted % 30 == 0) { - if (AccountManager.skin.equals(skinName.getValue())) + if (AccountManager.skin.equals(skinName.getValue()) && world == mc.theWorld) return; - FPSMaster.async.runnable(this::update); + world = mc.theWorld; AccountManager.skin = skinName.getValue(); - + FPSMaster.async.runnable(this::update); } } From 773e2a5d7e1c0f65cc3435be05284b69777ee2dc Mon Sep 17 00:00:00 2001 From: SuperSkidder Date: Sat, 19 Jul 2025 01:16:28 +0800 Subject: [PATCH 135/193] fix: possible memory leak --- .../fpsmaster/features/GlobalListener.java | 28 +++++++++++++++---- 1 file changed, 23 insertions(+), 5 deletions(-) diff --git a/shared/java/top/fpsmaster/features/GlobalListener.java b/shared/java/top/fpsmaster/features/GlobalListener.java index e8598ecd..7e69c81a 100644 --- a/shared/java/top/fpsmaster/features/GlobalListener.java +++ b/shared/java/top/fpsmaster/features/GlobalListener.java @@ -21,6 +21,11 @@ import java.net.URISyntaxException; import java.util.ArrayList; +import java.util.Map; +import java.util.Set; +import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; +import java.util.stream.Collectors; import static top.fpsmaster.utils.Utility.mc; @@ -50,7 +55,7 @@ public void onChatSend(EventSendChatMessage e) { PlayerInformation playerInformation = null; - ArrayList playerInfos = new ArrayList<>(); + Map playerInfos = new ConcurrentHashMap<>(); @Subscribe public void onTick(EventTick e) throws URISyntaxException { @@ -79,12 +84,25 @@ public void onTick(EventTick e) throws URISyntaxException { FPSMaster.INSTANCE.wsClient.sendPing(); } } - for (NetworkPlayerInfo networkPlayerInfo : mc.getNetHandler().getPlayerInfoMap()) { - if (!playerInfos.contains(networkPlayerInfo)) { - FPSMaster.INSTANCE.wsClient.fetchPlayer(networkPlayerInfo.getGameProfile().getId().toString(), networkPlayerInfo.getGameProfile().getName()); - playerInfos.add(networkPlayerInfo); + Set currentPlayers = mc.getNetHandler().getPlayerInfoMap().stream() + .map(info -> info.getGameProfile().getId()) + .collect(Collectors.toSet()); + + playerInfos.keySet().retainAll(currentPlayers); + + for (NetworkPlayerInfo info : mc.getNetHandler().getPlayerInfoMap()) { + UUID uuid = info.getGameProfile().getId(); + if (!playerInfos.containsKey(uuid)) { + playerInfos.put(uuid, info); + FPSMaster.INSTANCE.wsClient.fetchPlayer(uuid.toString(), info.getGameProfile().getName()); } } +// for (NetworkPlayerInfo networkPlayerInfo : mc.getNetHandler().getPlayerInfoMap()) { +// if (!playerInfos.contains(networkPlayerInfo)) { +// FPSMaster.INSTANCE.wsClient.fetchPlayer(networkPlayerInfo.getGameProfile().getId().toString(), networkPlayerInfo.getGameProfile().getName()); +// playerInfos.add(networkPlayerInfo); +// } +// } if (playerInformation == null) { playerInformation = new PlayerInformation(ProviderManager.mcProvider.getPlayer().getName(), ProviderManager.mcProvider.getPlayer().getUniqueID().toString(), ProviderManager.mcProvider.getServerAddress(), "", AccountManager.skin); FPSMaster.INSTANCE.wsClient.sendInformation(AccountManager.skin, "", ProviderManager.mcProvider.getPlayer().getName(), ProviderManager.mcProvider.getServerAddress()); From b2d974a28f619552077dc6e514da395a00885a98 Mon Sep 17 00:00:00 2001 From: SuperSkidder Date: Sat, 19 Jul 2025 10:24:32 +0800 Subject: [PATCH 136/193] fix: improve capability of RawInputMod --- .../thirdparty/rawinput/RawInputMod.java | 45 ++++++++++++++++--- 1 file changed, 38 insertions(+), 7 deletions(-) diff --git a/shared/java/top/fpsmaster/utils/thirdparty/rawinput/RawInputMod.java b/shared/java/top/fpsmaster/utils/thirdparty/rawinput/RawInputMod.java index bf98a006..01abb5c6 100644 --- a/shared/java/top/fpsmaster/utils/thirdparty/rawinput/RawInputMod.java +++ b/shared/java/top/fpsmaster/utils/thirdparty/rawinput/RawInputMod.java @@ -6,14 +6,32 @@ import net.minecraft.client.Minecraft; import net.minecraft.util.MouseHelper; +import java.io.File; + public class RawInputMod { private Thread inputThread; + public static Mouse mouse = null; + public static Controller[] controllers; + public static int dx = 0; + public static int dy = 0; + private String environment; public void start() { try { Minecraft.getMinecraft().mouseHelper = new RawMouseHelper(); - controllers = ControllerEnvironment.getDefaultEnvironment().getControllers(); + if (checkLibrary("jinput-dx8")){ + environment = "DirectInputEnvironmentPlugin"; + }else if (checkLibrary("jinput-raw")){ + environment = "DirectAndRawInputEnvironmentPlugin"; + }else{ + return; + } + + Class aClass = Class.forName("net.java.games.input." + environment); + aClass.getDeclaredConstructor().setAccessible(true); + ControllerEnvironment env = (ControllerEnvironment) aClass.newInstance(); + controllers = env.getControllers(); inputThread = new Thread(() -> { while (true) { int i = 0; @@ -28,8 +46,8 @@ public void start() { } if (mouse != null) { mouse.poll(); - dx += mouse.getX().getPollData(); - dy += mouse.getY().getPollData(); + dx += (int) mouse.getX().getPollData(); + dy += (int) mouse.getY().getPollData(); if (Minecraft.getMinecraft().currentScreen != null) { dx = 0; dy = 0; @@ -60,8 +78,21 @@ public void stop() { } } - public static Mouse mouse = null; - public static Controller[] controllers; - public static int dx = 0; - public static int dy = 0; + public static boolean checkLibrary(String name) { + try { + String path = System.getProperty("java.library.path"); + if (path != null) { + String mapped = System.mapLibraryName(name); + String[] paths = path.split(File.pathSeparator); + for (String libPath : paths) { + if (new File(libPath, mapped).exists()) { + return true; + } + } + } + return false; + } catch (Exception e) { + return false; + } + } } From db15dbf8c262acc0907d4b600fa34b4f4a092c0b Mon Sep 17 00:00:00 2001 From: SuperSkidder Date: Sat, 19 Jul 2025 10:41:00 +0800 Subject: [PATCH 137/193] feat: scoreboard support scaling --- .../ui/custom/impl/ScoreboardComponent.java | 1 + .../wrapper/mods/WrapperScoreboard.java | 37 ++++--------------- 2 files changed, 8 insertions(+), 30 deletions(-) diff --git a/shared/java/top/fpsmaster/ui/custom/impl/ScoreboardComponent.java b/shared/java/top/fpsmaster/ui/custom/impl/ScoreboardComponent.java index 6a464612..1bf31c2b 100644 --- a/shared/java/top/fpsmaster/ui/custom/impl/ScoreboardComponent.java +++ b/shared/java/top/fpsmaster/ui/custom/impl/ScoreboardComponent.java @@ -8,6 +8,7 @@ public class ScoreboardComponent extends Component { public ScoreboardComponent() { super(Scoreboard.class); + allowScale = true; } @Override diff --git a/v1.8.9/src/main/java/top/fpsmaster/wrapper/mods/WrapperScoreboard.java b/v1.8.9/src/main/java/top/fpsmaster/wrapper/mods/WrapperScoreboard.java index 07b18e6f..1f18d992 100644 --- a/v1.8.9/src/main/java/top/fpsmaster/wrapper/mods/WrapperScoreboard.java +++ b/v1.8.9/src/main/java/top/fpsmaster/wrapper/mods/WrapperScoreboard.java @@ -23,8 +23,6 @@ public static float[] render(ScoreboardComponent scoreboardComponent, InterfaceM ScoreObjective scoreobjective = null; ScorePlayerTeam scoreplayerteam = scoreboard.getPlayersTeam(ProviderManager.mcProvider.getPlayer().getName()); - UFontRenderer s16 = FPSMaster.fontManager.s16; - if (scoreplayerteam != null) { int i1 = scoreboard.getPlayersTeamColorIndex(ProviderManager.mcProvider.getPlayer().getName()); @@ -46,25 +44,17 @@ public static float[] render(ScoreboardComponent scoreboardComponent, InterfaceM collection = list; } - int i; - if (mod.betterFont.getValue()) { - i = s16.getStringWidth(objective.getDisplayName()); - } else { - i = ProviderManager.mcProvider.getFontRenderer().getStringWidth(objective.getDisplayName()); - } + int i = (int) scoreboardComponent.getStringWidth(16, objective.getDisplayName()); + for (Score score : collection) { ScorePlayerTeam scoreteam = scoreboard.getPlayersTeam(score.getPlayerName()); String s = filterHypixelIllegalCharacters(ScorePlayerTeam.formatPlayerName(scoreteam, score.getPlayerName()) + ": " + TextFormattingProvider.getRed() + score.getScorePoints()); - if (mod.betterFont.getValue()) { - i = Math.max(i, s16.getStringWidth(s)); - } else { - i = Math.max(i, ProviderManager.mcProvider.getFontRenderer().getStringWidth(s)); - } + i = (int) Math.max(i, scoreboardComponent.getStringWidth(16, s)); } i += 6; - int height1 = 10; + int height1 = (int) scoreboardComponent.getStringHeight(16) + 2; int j = 0; float h = collection.size() * height1 + 10; scoreboardComponent.drawRect(x, y, i, h, mod.backgroundColor.getColor()); @@ -79,25 +69,13 @@ public static float[] render(ScoreboardComponent scoreboardComponent, InterfaceM if (j == collection.size()) { String s3 = objective.getDisplayName(); scoreboardComponent.drawRect(x, y, i, height1 + 1, mod.backgroundColor.getColor()); - if (mod.betterFont.getValue()) { - scoreboardComponent.drawString(16, s3, (int) (x + 2 + (float) i / 2 - s16.getStringWidth(s3) / 2f), y, -1); - } else { - ProviderManager.mcProvider.getFontRenderer().drawStringWithShadow(s3, (int) (x + 2 + (float) i / 2 - ProviderManager.mcProvider.getFontRenderer().getStringWidth(s3) / 2f), y, -1); - } - } - if (mod.betterFont.getValue()) { - scoreboardComponent.drawString(16, s1, ((int) x) + 2, (int) (y + h - k), -1); - } else { - ProviderManager.mcProvider.getFontRenderer().drawStringWithShadow(s1, ((int) x) + 2, (int) (y + h - k), -1); + scoreboardComponent.drawString(16, s3, (int) (x + 2 + (float) i / 2 - scoreboardComponent.getStringWidth(16, s3) / 2f), y, -1); } + scoreboardComponent.drawString(16, s1, ((int) x) + 2, (int) (y + (h - k) * scoreboardComponent.scale), -1); // 红字 if (Scoreboard.score.getValue()) { String s2 = TextFormattingProvider.getRed() + String.valueOf(score1.getScorePoints()); - if (mod.betterFont.getValue()) { - scoreboardComponent.drawString(16, s2, x + i - 2 - s16.getStringWidth(s2), y + k, -1); - } else { - ProviderManager.mcProvider.getFontRenderer().drawStringWithShadow(s2, x + i - 2 - ProviderManager.mcProvider.getFontRenderer().getStringWidth(s2), y + k, -1); - } + scoreboardComponent.drawString(16, s2, x + (i - 2 - scoreboardComponent.getStringWidth(16, s2)) * scoreboardComponent.scale, y + k * scoreboardComponent.scale, -1); } } return new float[]{i, h}; @@ -106,7 +84,6 @@ public static float[] render(ScoreboardComponent scoreboardComponent, InterfaceM } - public static String filterHypixelIllegalCharacters(String text) { boolean dangerous = false; StringBuilder stringBuilder = new StringBuilder(); From 1baaff858553ad0adcc4a9d61e28234154ebb1c2 Mon Sep 17 00:00:00 2001 From: SuperSkidder Date: Sat, 19 Jul 2025 11:01:43 +0800 Subject: [PATCH 138/193] fix: stuck when close client --- shared/java/top/fpsmaster/FPSMaster.java | 1 + 1 file changed, 1 insertion(+) diff --git a/shared/java/top/fpsmaster/FPSMaster.java b/shared/java/top/fpsmaster/FPSMaster.java index ec21b9ad..ef5b6f7e 100644 --- a/shared/java/top/fpsmaster/FPSMaster.java +++ b/shared/java/top/fpsmaster/FPSMaster.java @@ -198,6 +198,7 @@ public void shutdown() { try { ClientLogger.info("Saving configs"); configManager.saveConfig("default"); + wsClient.close(200, "Shutdown"); } catch (FileException e) { throw new RuntimeException(e); } From 5874d53f2ae0c07be239cf020a916c0f94edd516 Mon Sep 17 00:00:00 2001 From: SuperSkidder Date: Sat, 19 Jul 2025 11:02:05 +0800 Subject: [PATCH 139/193] feat: add move border limit to components --- .../top/fpsmaster/ui/custom/Component.java | 83 ++++++++++--------- 1 file changed, 45 insertions(+), 38 deletions(-) diff --git a/shared/java/top/fpsmaster/ui/custom/Component.java b/shared/java/top/fpsmaster/ui/custom/Component.java index 45129d7b..af3bcacb 100644 --- a/shared/java/top/fpsmaster/ui/custom/Component.java +++ b/shared/java/top/fpsmaster/ui/custom/Component.java @@ -88,45 +88,45 @@ public float[] getRealPosition() { public void display(int mouseX, int mouseY) { float rX = getRealPosition()[0]; float rY = getRealPosition()[1]; - draw(rX, rY); - if (!(Utility.mc.currentScreen instanceof GuiChat || Utility.mc.currentScreen instanceof MainPanel)) return; - - float scaledWidth = width * scale; - float scaledHeight = height * scale; - boolean drag = FPSMaster.componentsManager.dragLock.equals(mod.name); - - alpha = (float) ((Render2DUtils.isHovered(rX, rY, scaledWidth, scaledHeight, mouseX, mouseY) || drag) ? - AnimationUtils.base(alpha, 50.0, 0.1f) : AnimationUtils.base(alpha, 0.0, 0.1f)); - - Render2DUtils.drawOptimizedRoundedRect(rX - 2, rY - 2, scaledWidth + 4, scaledHeight + 4, new Color(0, 0, 0, (int) alpha)); - GL11.glColor4f(1, 1, 1, 1); - - - if (!Mouse.isButtonDown(0)) { - FPSMaster.componentsManager.dragLock = ""; - } - if (Render2DUtils.isHovered(rX, rY, scaledWidth, scaledHeight, mouseX, mouseY) || drag) { - if (!MainPanel.dragLock.equals("null")) - return; - if (allowScale) { - int dWheel = Mouse.getDWheel(); - if (dWheel > 0) scaleUp(); - else if (dWheel < 0) scaleDown(); + if ((Utility.mc.currentScreen instanceof GuiChat || Utility.mc.currentScreen instanceof MainPanel)) { + float scaledWidth = width * scale; + float scaledHeight = height * scale; + boolean drag = FPSMaster.componentsManager.dragLock.equals(mod.name); + + alpha = (float) ((Render2DUtils.isHovered(rX, rY, scaledWidth, scaledHeight, mouseX, mouseY) || drag) ? + AnimationUtils.base(alpha, 1f, 0.2f) : AnimationUtils.base(alpha, 0.0f, 0.2f)); + + Render2DUtils.drawRect(rX - 2, rY - 2, scaledWidth + 4, scaledHeight + 4, new Color(0, 0, 0, (int) (alpha * 80))); + draw(rX, rY); + GL11.glColor4f(1, 1, 1, 1); + if (!Mouse.isButtonDown(0)) { + FPSMaster.componentsManager.dragLock = ""; } - FPSMaster.fontManager.s14.drawString(FPSMaster.i18n.get(mod.name.toLowerCase()) + " " + (scale * 10) / 10f + "x", rX, rY - 10, -1); - - if (!Mouse.isButtonDown(0)) return; - - if (!drag && FPSMaster.componentsManager.dragLock.isEmpty()) { - dragX = mouseX - rX; - dragY = mouseY - rY; - FPSMaster.componentsManager.dragLock = mod.name; - } - - if (FPSMaster.componentsManager.dragLock.equals(mod.name)) { - move(mouseX, mouseY); - FPSMaster.componentsManager.dragLock = mod.name; + if (Render2DUtils.isHovered(rX, rY, scaledWidth, scaledHeight, mouseX, mouseY) || drag) { + if (!MainPanel.dragLock.equals("null")) + return; + if (allowScale) { + int dWheel = Mouse.getDWheel(); + if (dWheel > 0) scaleUp(); + else if (dWheel < 0) scaleDown(); + } + FPSMaster.fontManager.s14.drawString(FPSMaster.i18n.get(mod.name.toLowerCase()) + " " + (scale * 10) / 10f + "x", rX, rY - 10, new Color(255, 255, 255, (int) (alpha * 255)).getRGB()); + + if (!Mouse.isButtonDown(0)) return; + + if (!drag && FPSMaster.componentsManager.dragLock.isEmpty()) { + dragX = mouseX - rX; + dragY = mouseY - rY; + FPSMaster.componentsManager.dragLock = mod.name; + } + + if (FPSMaster.componentsManager.dragLock.equals(mod.name)) { + move(mouseX, mouseY); + FPSMaster.componentsManager.dragLock = mod.name; + } } + } else { + draw(rX, rY); } } @@ -189,6 +189,13 @@ else if (y < guiHeight / 2f) } } + if (changeX < 0f || changeX + width * scale > guiWidth) { + changeX = Math.min(Math.max(changeX, 0f), guiWidth - width * scale); + } + if (changeY < 0f || changeY + height * scale > guiHeight) { + changeY = Math.min(Math.max(changeY, 0f), guiHeight - height * scale); + } + this.x = changeX / guiWidth * 2f; this.y = changeY / guiHeight * 2f; } @@ -224,7 +231,7 @@ public void drawString(int fontSize, boolean bold, String text, float x, float y if (mod.fontShadow.getValue()) { ProviderManager.mcProvider.getFontRenderer().drawStringWithShadow(text, 0f, 0f, color); } else { - GL11.glColor4f(1,1,1,1); + GL11.glColor4f(1, 1, 1, 1); ProviderManager.mcProvider.drawString(text, 0f, 0f, color); } GL11.glPopMatrix(); From acf15f3de90f5cd92b49218f1cafb215323b83f1 Mon Sep 17 00:00:00 2001 From: SuperSkidder Date: Sat, 19 Jul 2025 14:50:07 +0800 Subject: [PATCH 140/193] =?UTF-8?q?feat:=20=E6=8C=87=E5=93=AA=E7=88=86?= =?UTF-8?q?=E5=93=AA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../features/impl/render/MoreParticles.java | 24 ++++++++++++------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/shared/java/top/fpsmaster/features/impl/render/MoreParticles.java b/shared/java/top/fpsmaster/features/impl/render/MoreParticles.java index 3aa260a8..f88eabb8 100644 --- a/shared/java/top/fpsmaster/features/impl/render/MoreParticles.java +++ b/shared/java/top/fpsmaster/features/impl/render/MoreParticles.java @@ -3,6 +3,7 @@ import net.minecraft.client.Minecraft; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityLivingBase; +import net.minecraft.util.BlockPos; import net.minecraft.util.EnumParticleTypes; import top.fpsmaster.event.Subscribe; import top.fpsmaster.event.events.EventAttack; @@ -16,6 +17,8 @@ import top.fpsmaster.wrapper.WrapperEntityLightningBolt; import top.fpsmaster.wrapper.blockpos.WrapperBlockPos; +import static top.fpsmaster.utils.Utility.mc; + public class MoreParticles extends Module { private Entity target = null; private Entity lastEffect = null; @@ -99,15 +102,18 @@ public void onAttack(EventAttack event) { } else if (special.getValue() == 2) { Minecraft.getMinecraft().effectRenderer.emitParticleAtEntity(event.target, EnumParticleTypes.FLAME); } else if (special.getValue() == 3) { - ProviderManager.soundProvider.playRedStoneBreak( - event.target.posX, - event.target.posY, - event.target.posZ, - 1f, - 1f, - true - ); - ProviderManager.effectManager.addRedStoneBreak(new WrapperBlockPos(event.target.getPosition())); + if (mc.objectMouseOver.hitVec != null && event.target.hurtResistantTime <= 10) { + System.out.println(); + ProviderManager.soundProvider.playRedStoneBreak( + mc.objectMouseOver.hitVec.xCoord, + mc.objectMouseOver.hitVec.yCoord, + mc.objectMouseOver.hitVec.zCoord, + 1f, + 1f, + true + ); + ProviderManager.effectManager.addRedStoneBreak(new WrapperBlockPos(new BlockPos(mc.objectMouseOver.hitVec))); + } } } } From c4f23496fae490268390e306da626ac7430d521f Mon Sep 17 00:00:00 2001 From: SuperSkidder Date: Sat, 19 Jul 2025 18:06:38 +0800 Subject: [PATCH 141/193] fix: duplicated play --- .../java/top/fpsmaster/modules/music/MusicPlayer.java | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/shared/java/top/fpsmaster/modules/music/MusicPlayer.java b/shared/java/top/fpsmaster/modules/music/MusicPlayer.java index 967b0f84..0b34253a 100644 --- a/shared/java/top/fpsmaster/modules/music/MusicPlayer.java +++ b/shared/java/top/fpsmaster/modules/music/MusicPlayer.java @@ -16,6 +16,8 @@ public class MusicPlayer { public static float volume = 1f; public static float curPlayProgress = 0f; + private static Thread playThread; + public static float getPlayProgress() { if (isPlaying && JLayerHelper.clip != null) { curPlayProgress = JLayerHelper.getProgress(); @@ -34,9 +36,7 @@ public static double[] getCurve() { } public static void pause() { - isPlaying = false; - if (JLayerHelper.clip == null) return; - JLayerHelper.stop(); + stop(); } public static void stop() { @@ -54,7 +54,9 @@ public static void playFile(String path) { JLayerHelper.clip.close(); } float v = Float.parseFloat(FPSMaster.configManager.configure.getOrCreate("volume", "1")); - FPSMaster.async.runnable(() -> { + if (playThread != null && playThread.isAlive()) + playThread.interrupt(); + playThread = new Thread(() -> { try { JLayerHelper.playWAV(path.replace(".mp3", ".wav")); } catch (IOException e) { @@ -64,6 +66,7 @@ public static void playFile(String path) { } setVolume(v); }); + playThread.start(); } } From 9e4fa2c0dddd313da86952686eb3017b4f3bdf72 Mon Sep 17 00:00:00 2001 From: SuperSkidder Date: Sat, 19 Jul 2025 21:41:19 +0800 Subject: [PATCH 142/193] feat: cosmetics --- .../fpsmaster/features/GlobalListener.java | 14 +++- .../features/manager/ModuleManager.java | 5 +- .../modules/account/AccountManager.java | 52 ++++++++++++- .../fpsmaster/modules/account/Cosmetic.java | 41 ++++++++++ .../fpsmaster/ui/click/CosmeticScreen.java | 75 +++++++++++++++++++ .../top/fpsmaster/ui/click/MainPanel.java | 27 ++++++- .../top/fpsmaster/utils/os/HttpRequest.java | 30 ++++++++ 7 files changed, 236 insertions(+), 8 deletions(-) create mode 100644 shared/java/top/fpsmaster/modules/account/Cosmetic.java create mode 100644 shared/java/top/fpsmaster/ui/click/CosmeticScreen.java diff --git a/shared/java/top/fpsmaster/features/GlobalListener.java b/shared/java/top/fpsmaster/features/GlobalListener.java index 7e69c81a..e563adc8 100644 --- a/shared/java/top/fpsmaster/features/GlobalListener.java +++ b/shared/java/top/fpsmaster/features/GlobalListener.java @@ -104,16 +104,22 @@ public void onTick(EventTick e) throws URISyntaxException { // } // } if (playerInformation == null) { - playerInformation = new PlayerInformation(ProviderManager.mcProvider.getPlayer().getName(), ProviderManager.mcProvider.getPlayer().getUniqueID().toString(), ProviderManager.mcProvider.getServerAddress(), "", AccountManager.skin); - FPSMaster.INSTANCE.wsClient.sendInformation(AccountManager.skin, "", ProviderManager.mcProvider.getPlayer().getName(), ProviderManager.mcProvider.getServerAddress()); + playerInformation = new PlayerInformation(ProviderManager.mcProvider.getPlayer().getName(), ProviderManager.mcProvider.getPlayer().getUniqueID().toString(), ProviderManager.mcProvider.getServerAddress(), AccountManager.cosmeticsUsing, AccountManager.skin); + FPSMaster.INSTANCE.wsClient.sendInformation(AccountManager.skin, AccountManager.cosmeticsUsing, ProviderManager.mcProvider.getPlayer().getName(), ProviderManager.mcProvider.getServerAddress()); } else if (!playerInformation.serverAddress.equals(ProviderManager.mcProvider.getServerAddress()) || !playerInformation.name.equals(ProviderManager.mcProvider.getPlayer().getName()) || !playerInformation.skin.equals(AccountManager.skin) || !playerInformation.uuid.equals(ProviderManager.mcProvider.getPlayer().getUniqueID().toString())) { - playerInformation = new PlayerInformation(ProviderManager.mcProvider.getPlayer().getName(), ProviderManager.mcProvider.getPlayer().getUniqueID().toString(), ProviderManager.mcProvider.getServerAddress(), "", AccountManager.skin); - FPSMaster.INSTANCE.wsClient.sendInformation(AccountManager.skin, "", ProviderManager.mcProvider.getPlayer().getName(), ProviderManager.mcProvider.getServerAddress()); + playerInformation = new PlayerInformation(ProviderManager.mcProvider.getPlayer().getName(), ProviderManager.mcProvider.getPlayer().getUniqueID().toString(), ProviderManager.mcProvider.getServerAddress(), AccountManager.cosmeticsUsing, AccountManager.skin); + FPSMaster.INSTANCE.wsClient.sendInformation(AccountManager.skin, AccountManager.cosmeticsUsing, ProviderManager.mcProvider.getPlayer().getName(), ProviderManager.mcProvider.getServerAddress()); } }); } } + @Subscribe + public void onCape(EventCapeLoading e){ + if (!AccountManager.cosmeticsUsing.isEmpty()) { + e.setCachedCape("ornaments/" + AccountManager.cosmeticsUsing + "_resource"); + } + } @Subscribe public void onRender(EventRender2D e) { ScaledResolution scaledResolution = new ScaledResolution(Minecraft.getMinecraft()); diff --git a/shared/java/top/fpsmaster/features/manager/ModuleManager.java b/shared/java/top/fpsmaster/features/manager/ModuleManager.java index b6bfd515..e3fd82ab 100644 --- a/shared/java/top/fpsmaster/features/manager/ModuleManager.java +++ b/shared/java/top/fpsmaster/features/manager/ModuleManager.java @@ -13,6 +13,7 @@ import top.fpsmaster.interfaces.ProviderManager; import top.fpsmaster.modules.dev.DevMode; import top.fpsmaster.modules.logger.ClientLogger; +import top.fpsmaster.ui.click.CosmeticScreen; import top.fpsmaster.ui.click.MainPanel; import top.fpsmaster.ui.click.modules.ModuleRenderer; import top.fpsmaster.ui.devspace.DevSpace; @@ -47,7 +48,9 @@ public void onKey(EventKey e) { module.toggle(); } } - +// if (e.key == Keyboard.KEY_INSERT) { +// Minecraft.getMinecraft().displayGuiScreen(new CosmeticScreen()); +// } if (e.key == Keyboard.KEY_INSERT && DevMode.INSTACE.dev) { Minecraft.getMinecraft().displayGuiScreen(new DevSpace()); } diff --git a/shared/java/top/fpsmaster/modules/account/AccountManager.java b/shared/java/top/fpsmaster/modules/account/AccountManager.java index 4a8c30ea..a516803e 100644 --- a/shared/java/top/fpsmaster/modules/account/AccountManager.java +++ b/shared/java/top/fpsmaster/modules/account/AccountManager.java @@ -1,5 +1,6 @@ package top.fpsmaster.modules.account; +import com.google.gson.JsonElement; import com.google.gson.JsonObject; import com.google.gson.JsonParser; import top.fpsmaster.FPSMaster; @@ -12,13 +13,17 @@ import top.fpsmaster.utils.os.HttpRequest; import java.io.IOException; +import java.util.ArrayList; import java.util.HashMap; public class AccountManager { private String token = ""; private String username = ""; - public static JsonParser parser = new JsonParser(); public static String skin = ""; + public static JsonParser parser = new JsonParser(); + public static String cosmeticsHeld = ""; + public static String cosmeticsUsing = ""; + public static HashMap cosmetics = new HashMap<>(); public void autoLogin() { FPSMaster.async.runnable(() -> { @@ -60,7 +65,7 @@ private boolean attemptLogin(String username, String token) throws AccountExcept headers.put("Authorization", "Bearer " + token); HttpRequest.HttpResponseResult s = HttpRequest.get(FPSMaster.SERVICE_API + "/api/auth/validate-jwt", headers); JsonObject json = parser.parse(s.getBody()).getAsJsonObject(); - if (!s.isSuccess()){ + if (!s.isSuccess()) { throw new AccountException("Failed to login via token " + s.getStatusCode()); } this.username = username; @@ -88,7 +93,50 @@ public static JsonObject login(String username, String password) throws AccountE throw new AccountException("登录失败: " + jsonObject.get("message").getAsString()); } return jsonObject; + } + + public void refreshUserData() throws AccountException { + try { + String token = FileUtils.readTempValue("token").trim(); + HashMap headers = new HashMap<>(); + headers.put("Authorization", "Bearer " + token); + HttpRequest.HttpResponseResult s = HttpRequest.post(FPSMaster.SERVICE_API + "/api/users", null, headers); + JsonObject json = parser.parse(s.getBody()).getAsJsonObject(); + if (!s.isSuccess()) { + throw new AccountException("Failed to login via token " + s.getStatusCode()); + } + cosmeticsHeld = json.get("data").getAsJsonObject().get("items").getAsString(); + } catch (Exception e) { + throw new AccountException("Failed to login via token"); + } + } + public void refreshCosmetics() throws AccountException { + try { + String token = FileUtils.readTempValue("token").trim(); + HashMap headers = new HashMap<>(); + headers.put("Authorization", "Bearer " + token); + HttpRequest.HttpResponseResult s = HttpRequest.get(FPSMaster.SERVICE_API + "/api/store/items", headers); + JsonObject json = parser.parse(s.getBody()).getAsJsonObject(); + if (!s.isSuccess()) { + throw new AccountException("Failed to login via token " + s.getStatusCode()); + } + cosmetics.clear(); + for (JsonElement data : json.get("data").getAsJsonArray()) { + JsonObject asJsonObject = data.getAsJsonObject(); + Cosmetic cosmetic = new Cosmetic(); + cosmetic.id = asJsonObject.get("id").getAsInt(); + cosmetic.name = asJsonObject.get("name").getAsString(); + cosmetic.img = asJsonObject.get("img").getAsString(); + cosmetic.category = asJsonObject.get("category").getAsString(); + cosmetic.price = asJsonObject.get("price").getAsDouble(); + cosmetic.available = asJsonObject.get("available").getAsBoolean(); + cosmetic.resource = asJsonObject.get("resource").getAsString(); + cosmetics.put(cosmetic.id, cosmetic); + } + } catch (Exception e) { + throw new AccountException("Failed to login via token"); + } } // Getter and Setter methods diff --git a/shared/java/top/fpsmaster/modules/account/Cosmetic.java b/shared/java/top/fpsmaster/modules/account/Cosmetic.java new file mode 100644 index 00000000..c856ec1c --- /dev/null +++ b/shared/java/top/fpsmaster/modules/account/Cosmetic.java @@ -0,0 +1,41 @@ +package top.fpsmaster.modules.account; + +import com.google.gson.JsonObject; +import net.minecraft.client.renderer.ThreadDownloadImageData; +import net.minecraft.util.ResourceLocation; +import top.fpsmaster.FPSMaster; +import top.fpsmaster.utils.os.HttpRequest; + +import java.awt.image.BufferedImage; +import java.io.IOException; + +import static top.fpsmaster.utils.Utility.mc; + +public class Cosmetic { + public int id; + public String name; + public String img; + public String category; + public double price; + public boolean available; + public String resource; + public boolean loaded; + + public Cosmetic() { + } + + public void load() { + if (mc.theWorld == null) return; + FPSMaster.async.runnable(() -> { + ResourceLocation textureLocation = new ResourceLocation("ornaments/" + id + "_resource"); + ThreadDownloadImageData downloadImageData = new ThreadDownloadImageData(null, resource, textureLocation, null); + try { + downloadImageData.setBufferedImage(HttpRequest.downloadImage(resource)); + mc.getTextureManager().loadTexture(textureLocation, downloadImageData); + } catch (IOException e) { + throw new RuntimeException(e); + } + }); + loaded = true; + } +} diff --git a/shared/java/top/fpsmaster/ui/click/CosmeticScreen.java b/shared/java/top/fpsmaster/ui/click/CosmeticScreen.java new file mode 100644 index 00000000..45f31f58 --- /dev/null +++ b/shared/java/top/fpsmaster/ui/click/CosmeticScreen.java @@ -0,0 +1,75 @@ +package top.fpsmaster.ui.click; + +import top.fpsmaster.FPSMaster; +import top.fpsmaster.exception.AccountException; +import top.fpsmaster.modules.account.AccountManager; +import top.fpsmaster.modules.account.Cosmetic; +import top.fpsmaster.ui.click.component.ScrollContainer; +import top.fpsmaster.utils.render.Render2DUtils; +import top.fpsmaster.utils.render.ScaledGuiScreen; + +import java.awt.*; +import java.io.IOException; + +public class CosmeticScreen extends ScaledGuiScreen { + ScrollContainer container = new ScrollContainer(); + + @Override + public void render(int mouseX, int mouseY, float partialTicks) { + super.render(mouseX, mouseY, partialTicks); + String[] split = AccountManager.cosmeticsHeld.split(","); + Render2DUtils.drawRoundedRectImage(width / 2f - 200, height / 2f - 130, 400, 260, 4, new Color(0, 0, 0, 100)); + container.draw(width / 2f - 200, height / 2f - 130, 400, 260, mouseX, mouseY, () -> { + int y = 0; + for (String id : split) { + if (id.isEmpty()) + continue; + Cosmetic cosmetic = AccountManager.cosmetics.get(Integer.parseInt(id)); + if (!cosmetic.loaded) { + cosmetic.load(); + } + FPSMaster.fontManager.s18.drawString(cosmetic.name, width / 2f - 190, height / 2f - 120 + y, id.equals(AccountManager.cosmeticsUsing) ? Color.GREEN.getRGB() : Color.WHITE.getRGB()); + y += 20; + } + container.setHeight(y); + }); + + } + + @Override + public void initGui() { + super.initGui(); + FPSMaster.async.runnable(() -> { + try { + if (AccountManager.cosmetics.isEmpty()) + FPSMaster.accountManager.refreshCosmetics(); + FPSMaster.accountManager.refreshUserData(); + } catch (AccountException e) { + throw new RuntimeException(e); + } + }); + } + + @Override + protected void mouseClicked(int mouseX, int mouseY, int mouseButton) throws IOException { + super.mouseClicked(mouseX, mouseY, mouseButton); + String[] split = AccountManager.cosmeticsHeld.split(","); + int y = 0; + for (String id : split) { + if (id.isEmpty()) + continue; + Cosmetic cosmetic = AccountManager.cosmetics.get(Integer.parseInt(id)); + if (!cosmetic.loaded) + cosmetic.load(); + if (Render2DUtils.isHovered(width / 2f - 200, height / 2f - 120 + y, 400, 20, mouseX, mouseY)) { + String cosmeticsUsing = String.valueOf(cosmetic.id); + if (AccountManager.cosmeticsUsing.equals(cosmeticsUsing)) { + AccountManager.cosmeticsUsing = ""; + } else { + AccountManager.cosmeticsUsing = cosmeticsUsing; + } + } + y += 20; + } + } +} diff --git a/shared/java/top/fpsmaster/ui/click/MainPanel.java b/shared/java/top/fpsmaster/ui/click/MainPanel.java index 95c084e1..223b966f 100644 --- a/shared/java/top/fpsmaster/ui/click/MainPanel.java +++ b/shared/java/top/fpsmaster/ui/click/MainPanel.java @@ -167,6 +167,23 @@ public void render(int mouseX, int mouseY, float partialTicks) { new Color(0, 0, 0, 200).getRGB() ); + Render2DUtils.drawRoundedRectImage( + x + 5, + y + height - 25, + 20, + 20, + 20, + new Color(0, 0, 0, 200) + ); + + Render2DUtils.drawImage( + new ResourceLocation("client/gui/screen/theme.png"), + x + 11, + y + height - 19, + 8, + 8, + -1); + float my = y + 60; Render2DUtils.drawOptimizedRoundedRect( x + 4 + categoryAnimation / 50f, @@ -279,7 +296,15 @@ public void keyTyped(char typedChar, int keyCode) throws IOException { @Override public void onClick(int mouseX, int mouseY, int mouseButton) { - aiChatPanel.click(mouseX, mouseY, mouseButton); +// aiChatPanel.click(mouseX, mouseY, mouseButton); + if(Render2DUtils.isHovered(x + 5, + y + height - 25, + 20, + 20, mouseX, mouseY)) { + if (mouseButton == 0){ + mc.displayGuiScreen(new CosmeticScreen()); + } + } if (!Render2DUtils.isHoveredWithoutScale(x, y, width, height, mouseX, mouseY)) return; // if (mouseButton == 0 && Render2DUtils.isHoveredWithoutScale( diff --git a/shared/java/top/fpsmaster/utils/os/HttpRequest.java b/shared/java/top/fpsmaster/utils/os/HttpRequest.java index 6a2d2a60..001c9bb9 100644 --- a/shared/java/top/fpsmaster/utils/os/HttpRequest.java +++ b/shared/java/top/fpsmaster/utils/os/HttpRequest.java @@ -19,11 +19,15 @@ import org.apache.http.util.EntityUtils; import top.fpsmaster.modules.logger.ClientLogger; +import javax.imageio.ImageIO; +import java.awt.image.BufferedImage; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; +import java.net.URL; import java.nio.charset.StandardCharsets; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; import java.util.Map; @@ -101,6 +105,10 @@ public static HttpResponseResult postForm(String url, Map params return executeRequest(request, null); } + public static HttpResponseResult post(String url, String body, HashMap headers) throws IOException { + return post(url, body, "application/json", headers); + } + private static HttpResponseResult post(String url, String body, String contentType) throws IOException { return post(url, body, contentType, null); } @@ -144,6 +152,28 @@ public static void downloadAsync(String url, String filepath, Runnable callback) }).start(); } + + public static BufferedImage downloadImage(String imageUrl) throws IOException { + // 验证URL是否为空 + if (imageUrl == null || imageUrl.trim().isEmpty()) { + throw new IllegalArgumentException("图片URL不能为空"); + } + + // 创建URL对象 + URL url = new URL(imageUrl); + + // 使用ImageIO读取URL中的图片并转换为BufferedImage + BufferedImage image = ImageIO.read(url); + + // 检查是否成功读取图片 + if (image == null) { + throw new IOException("Error when reading image from URL: " + imageUrl); + } + + return image; + } + + // ================== Core Execution Method ================== // private static HttpResponseResult executeRequest(HttpRequestBase request, Map headers) throws IOException { // Set request configuration and default headers From ed1fbc6760488162e674f8d6c2abd88ed2facd5f Mon Sep 17 00:00:00 2001 From: SuperSkidder Date: Sat, 19 Jul 2025 21:45:43 +0800 Subject: [PATCH 143/193] fix: support scroll to CosmeticScreen --- shared/java/top/fpsmaster/ui/click/CosmeticScreen.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/shared/java/top/fpsmaster/ui/click/CosmeticScreen.java b/shared/java/top/fpsmaster/ui/click/CosmeticScreen.java index 45f31f58..4224e752 100644 --- a/shared/java/top/fpsmaster/ui/click/CosmeticScreen.java +++ b/shared/java/top/fpsmaster/ui/click/CosmeticScreen.java @@ -1,5 +1,6 @@ package top.fpsmaster.ui.click; +import org.lwjgl.opengl.GL11; import top.fpsmaster.FPSMaster; import top.fpsmaster.exception.AccountException; import top.fpsmaster.modules.account.AccountManager; @@ -19,6 +20,8 @@ public void render(int mouseX, int mouseY, float partialTicks) { super.render(mouseX, mouseY, partialTicks); String[] split = AccountManager.cosmeticsHeld.split(","); Render2DUtils.drawRoundedRectImage(width / 2f - 200, height / 2f - 130, 400, 260, 4, new Color(0, 0, 0, 100)); + GL11.glEnable(GL11.GL_SCISSOR_TEST); + Render2DUtils.doGlScissor(width / 2f - 200, height / 2f - 130, 400, 260, scaleFactor); container.draw(width / 2f - 200, height / 2f - 130, 400, 260, mouseX, mouseY, () -> { int y = 0; for (String id : split) { @@ -28,11 +31,13 @@ public void render(int mouseX, int mouseY, float partialTicks) { if (!cosmetic.loaded) { cosmetic.load(); } - FPSMaster.fontManager.s18.drawString(cosmetic.name, width / 2f - 190, height / 2f - 120 + y, id.equals(AccountManager.cosmeticsUsing) ? Color.GREEN.getRGB() : Color.WHITE.getRGB()); + FPSMaster.fontManager.s18.drawString(cosmetic.name, width / 2f - 190, height / 2f - 120 + y + container.getScroll(), id.equals(AccountManager.cosmeticsUsing) ? Color.GREEN.getRGB() : Color.WHITE.getRGB()); y += 20; } container.setHeight(y); }); + GL11.glDisable(GL11.GL_SCISSOR_TEST); + } From 44efec651aa013dd4f2c2f36281117e9a6048c32 Mon Sep 17 00:00:00 2001 From: SuperSkidder Date: Sat, 19 Jul 2025 23:52:00 +0800 Subject: [PATCH 144/193] fix: music skipping --- .../java/top/fpsmaster/features/GlobalListener.java | 1 - .../java/top/fpsmaster/modules/music/PlayList.java | 2 ++ .../top/fpsmaster/ui/click/music/MusicPanel.java | 2 +- .../top/fpsmaster/utils/render/Render2DUtils.java | 13 ++++++------- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/shared/java/top/fpsmaster/features/GlobalListener.java b/shared/java/top/fpsmaster/features/GlobalListener.java index e563adc8..a0ac14ff 100644 --- a/shared/java/top/fpsmaster/features/GlobalListener.java +++ b/shared/java/top/fpsmaster/features/GlobalListener.java @@ -62,7 +62,6 @@ public void onTick(EventTick e) throws URISyntaxException { if (musicSwitchTimer.delay(500)) { FPSMaster.async.runnable(() -> { if (MusicPlayer.isPlaying && MusicPlayer.getPlayProgress() > 0.999) { - MusicPlayer.curPlayProgress = 0f; MusicPlayer.playList.next(); } if (ProviderManager.mcProvider.getWorld() != null) { diff --git a/shared/java/top/fpsmaster/modules/music/PlayList.java b/shared/java/top/fpsmaster/modules/music/PlayList.java index b22f4db0..817daafd 100644 --- a/shared/java/top/fpsmaster/modules/music/PlayList.java +++ b/shared/java/top/fpsmaster/modules/music/PlayList.java @@ -1,6 +1,7 @@ package top.fpsmaster.modules.music; import top.fpsmaster.FPSMaster; +import top.fpsmaster.modules.music.netease.Music; import top.fpsmaster.ui.notification.NotificationManager; import java.util.LinkedList; @@ -51,6 +52,7 @@ private void shuffleList() { } public void next() { + JLayerHelper.clip = null; MusicPlayer.stop(); if (musics.isEmpty()) return; shuffleList(); diff --git a/shared/java/top/fpsmaster/ui/click/music/MusicPanel.java b/shared/java/top/fpsmaster/ui/click/music/MusicPanel.java index a7829f63..9155736d 100644 --- a/shared/java/top/fpsmaster/ui/click/music/MusicPanel.java +++ b/shared/java/top/fpsmaster/ui/click/music/MusicPanel.java @@ -194,7 +194,7 @@ public static void draw(float x, float y, float width, float height, int mouseX, MusicPanel.width = width; MusicPanel.height = height; if (displayList.musics.isEmpty() && searchThread == null) { - searchThread = new Thread(() -> searchList = MusicWrapper.searchSongs("Minecraft")); + searchThread = new Thread(() -> searchList = MusicWrapper.searchSongs("C418")); searchThread.start(); } diff --git a/shared/java/top/fpsmaster/utils/render/Render2DUtils.java b/shared/java/top/fpsmaster/utils/render/Render2DUtils.java index c3ecd745..844f3e0f 100644 --- a/shared/java/top/fpsmaster/utils/render/Render2DUtils.java +++ b/shared/java/top/fpsmaster/utils/render/Render2DUtils.java @@ -99,13 +99,12 @@ public static void drawImage(ResourceLocation res, float x, float y, float width } public static void drawRoundedRectImage(float x, float y, float width, float height, int radius, Color color) { - ResourceLocation res = AWTUtils.generateRoundImage((int) width, (int) height, radius); - Render2DUtils.drawImage(res, x, y, width, height, color); - } - - public static void drawRoundedRectImage(float x, float y, float width, float height, int radius, Color color, int borderWidth, Color borderColor) { - ResourceLocation res = AWTUtils.generateRoundImage((int) width, (int) height, radius, borderColor, borderWidth); - Render2DUtils.drawImage(res, x, y, width, height, color); + try { + ResourceLocation res = AWTUtils.generateRoundImage((int) width, (int) height, radius); + Render2DUtils.drawImage(res, x, y, width, height, color); + }catch (IllegalArgumentException e){ + Render2DUtils.drawRect(x, y, width, height, color); + } } public static void drawRect(float x, float y, float width, float height, Color color) { From 030a926b9bdb56be32388d9e47efd990dd242e16 Mon Sep 17 00:00:00 2001 From: SuperSkidder Date: Sat, 19 Jul 2025 23:58:06 +0800 Subject: [PATCH 145/193] optimize: multi threads --- .../fpsmaster/features/GlobalListener.java | 87 ++++++++++--------- .../impl/interfaces/MusicOverlay.java | 6 +- .../ui/screens/account/GuiWaiting.java | 6 +- 3 files changed, 54 insertions(+), 45 deletions(-) diff --git a/shared/java/top/fpsmaster/features/GlobalListener.java b/shared/java/top/fpsmaster/features/GlobalListener.java index a0ac14ff..363e8a2c 100644 --- a/shared/java/top/fpsmaster/features/GlobalListener.java +++ b/shared/java/top/fpsmaster/features/GlobalListener.java @@ -56,60 +56,63 @@ public void onChatSend(EventSendChatMessage e) { Map playerInfos = new ConcurrentHashMap<>(); - + Thread tickThread; @Subscribe public void onTick(EventTick e) throws URISyntaxException { if (musicSwitchTimer.delay(500)) { - FPSMaster.async.runnable(() -> { - if (MusicPlayer.isPlaying && MusicPlayer.getPlayProgress() > 0.999) { - MusicPlayer.playList.next(); - } - if (ProviderManager.mcProvider.getWorld() != null) { - Utility.flush(); - } - if (FPSMaster.INSTANCE.loggedIn) { - if (FPSMaster.INSTANCE.wsClient == null) { - try { - FPSMaster.INSTANCE.wsClient = WsClient.start("wss://service.fpsmaster.top/"); - } catch (URISyntaxException ex) { - throw new RuntimeException(ex); + if (tickThread == null || !tickThread.isAlive()) { + tickThread = new Thread(() -> { + if (MusicPlayer.isPlaying && MusicPlayer.getPlayProgress() > 0.999) { + MusicPlayer.playList.next(); + } + if (ProviderManager.mcProvider.getWorld() != null) { + Utility.flush(); + } + if (FPSMaster.INSTANCE.loggedIn) { + if (FPSMaster.INSTANCE.wsClient == null) { + try { + FPSMaster.INSTANCE.wsClient = WsClient.start("wss://service.fpsmaster.top/"); + } catch (URISyntaxException ex) { + throw new RuntimeException(ex); + } + Utility.sendClientDebug("尝试连接"); + } else if (FPSMaster.INSTANCE.wsClient.isClosed() && !FPSMaster.INSTANCE.wsClient.isOpen()) { + FPSMaster.INSTANCE.wsClient.close(); + FPSMaster.INSTANCE.wsClient.connect(); + Utility.sendClientDebug("尝试重连"); + } else { + FPSMaster.INSTANCE.wsClient.sendPing(); } - Utility.sendClientDebug("尝试连接"); - } else if (FPSMaster.INSTANCE.wsClient.isClosed() && !FPSMaster.INSTANCE.wsClient.isOpen()) { - FPSMaster.INSTANCE.wsClient.close(); - FPSMaster.INSTANCE.wsClient.connect(); - Utility.sendClientDebug("尝试重连"); - } else { - FPSMaster.INSTANCE.wsClient.sendPing(); } - } - Set currentPlayers = mc.getNetHandler().getPlayerInfoMap().stream() - .map(info -> info.getGameProfile().getId()) - .collect(Collectors.toSet()); - - playerInfos.keySet().retainAll(currentPlayers); - - for (NetworkPlayerInfo info : mc.getNetHandler().getPlayerInfoMap()) { - UUID uuid = info.getGameProfile().getId(); - if (!playerInfos.containsKey(uuid)) { - playerInfos.put(uuid, info); - FPSMaster.INSTANCE.wsClient.fetchPlayer(uuid.toString(), info.getGameProfile().getName()); + Set currentPlayers = mc.getNetHandler().getPlayerInfoMap().stream() + .map(info -> info.getGameProfile().getId()) + .collect(Collectors.toSet()); + + playerInfos.keySet().retainAll(currentPlayers); + + for (NetworkPlayerInfo info : mc.getNetHandler().getPlayerInfoMap()) { + UUID uuid = info.getGameProfile().getId(); + if (!playerInfos.containsKey(uuid)) { + playerInfos.put(uuid, info); + FPSMaster.INSTANCE.wsClient.fetchPlayer(uuid.toString(), info.getGameProfile().getName()); + } } - } // for (NetworkPlayerInfo networkPlayerInfo : mc.getNetHandler().getPlayerInfoMap()) { // if (!playerInfos.contains(networkPlayerInfo)) { // FPSMaster.INSTANCE.wsClient.fetchPlayer(networkPlayerInfo.getGameProfile().getId().toString(), networkPlayerInfo.getGameProfile().getName()); // playerInfos.add(networkPlayerInfo); // } // } - if (playerInformation == null) { - playerInformation = new PlayerInformation(ProviderManager.mcProvider.getPlayer().getName(), ProviderManager.mcProvider.getPlayer().getUniqueID().toString(), ProviderManager.mcProvider.getServerAddress(), AccountManager.cosmeticsUsing, AccountManager.skin); - FPSMaster.INSTANCE.wsClient.sendInformation(AccountManager.skin, AccountManager.cosmeticsUsing, ProviderManager.mcProvider.getPlayer().getName(), ProviderManager.mcProvider.getServerAddress()); - } else if (!playerInformation.serverAddress.equals(ProviderManager.mcProvider.getServerAddress()) || !playerInformation.name.equals(ProviderManager.mcProvider.getPlayer().getName()) || !playerInformation.skin.equals(AccountManager.skin) || !playerInformation.uuid.equals(ProviderManager.mcProvider.getPlayer().getUniqueID().toString())) { - playerInformation = new PlayerInformation(ProviderManager.mcProvider.getPlayer().getName(), ProviderManager.mcProvider.getPlayer().getUniqueID().toString(), ProviderManager.mcProvider.getServerAddress(), AccountManager.cosmeticsUsing, AccountManager.skin); - FPSMaster.INSTANCE.wsClient.sendInformation(AccountManager.skin, AccountManager.cosmeticsUsing, ProviderManager.mcProvider.getPlayer().getName(), ProviderManager.mcProvider.getServerAddress()); - } - }); + if (playerInformation == null) { + playerInformation = new PlayerInformation(ProviderManager.mcProvider.getPlayer().getName(), ProviderManager.mcProvider.getPlayer().getUniqueID().toString(), ProviderManager.mcProvider.getServerAddress(), AccountManager.cosmeticsUsing, AccountManager.skin); + FPSMaster.INSTANCE.wsClient.sendInformation(AccountManager.skin, AccountManager.cosmeticsUsing, ProviderManager.mcProvider.getPlayer().getName(), ProviderManager.mcProvider.getServerAddress()); + } else if (!playerInformation.serverAddress.equals(ProviderManager.mcProvider.getServerAddress()) || !playerInformation.name.equals(ProviderManager.mcProvider.getPlayer().getName()) || !playerInformation.skin.equals(AccountManager.skin) || !playerInformation.uuid.equals(ProviderManager.mcProvider.getPlayer().getUniqueID().toString())) { + playerInformation = new PlayerInformation(ProviderManager.mcProvider.getPlayer().getName(), ProviderManager.mcProvider.getPlayer().getUniqueID().toString(), ProviderManager.mcProvider.getServerAddress(), AccountManager.cosmeticsUsing, AccountManager.skin); + FPSMaster.INSTANCE.wsClient.sendInformation(AccountManager.skin, AccountManager.cosmeticsUsing, ProviderManager.mcProvider.getPlayer().getName(), ProviderManager.mcProvider.getServerAddress()); + } + }); + tickThread.start(); + } } } diff --git a/shared/java/top/fpsmaster/features/impl/interfaces/MusicOverlay.java b/shared/java/top/fpsmaster/features/impl/interfaces/MusicOverlay.java index 194192c9..d59390fe 100644 --- a/shared/java/top/fpsmaster/features/impl/interfaces/MusicOverlay.java +++ b/shared/java/top/fpsmaster/features/impl/interfaces/MusicOverlay.java @@ -25,10 +25,12 @@ public MusicOverlay() { addSettings(amplitude, progressColor, color, betterFont, fontShadow); } + Thread updateThread = new Thread(JLayerHelper::updateLoudness); + @Subscribe public void onRender(EventRender2D e) { - if (timer.delay(50)) { - FPSMaster.async.runnable(JLayerHelper::updateLoudness); + if (timer.delay(50) && !updateThread.isAlive()) { + updateThread.start(); } IngameOverlay.onRender(); } diff --git a/shared/java/top/fpsmaster/ui/screens/account/GuiWaiting.java b/shared/java/top/fpsmaster/ui/screens/account/GuiWaiting.java index 1e3aaf6a..fee60173 100644 --- a/shared/java/top/fpsmaster/ui/screens/account/GuiWaiting.java +++ b/shared/java/top/fpsmaster/ui/screens/account/GuiWaiting.java @@ -14,10 +14,14 @@ public class GuiWaiting extends GuiScreen { public static boolean loggedIn = false; + Thread loginThread = new Thread(MicrosoftLogin::loginViaBrowser); + @Override public void initGui() { super.initGui(); - FPSMaster.async.runnable(MicrosoftLogin::loginViaBrowser); + if (!loginThread.isAlive()){ + loginThread.start(); + } } @Override From 7236ea59c3ab5e03a716a310e0430b20c38e0e87 Mon Sep 17 00:00:00 2001 From: SuperSkidder Date: Sun, 20 Jul 2025 00:51:13 +0800 Subject: [PATCH 146/193] optimize: memory problem and shutdown nullptr --- shared/java/top/fpsmaster/FPSMaster.java | 4 +++- .../fpsmaster/modules/client/GlobalTextFilter.java | 14 +++++++------- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/shared/java/top/fpsmaster/FPSMaster.java b/shared/java/top/fpsmaster/FPSMaster.java index ef5b6f7e..c935c08f 100644 --- a/shared/java/top/fpsmaster/FPSMaster.java +++ b/shared/java/top/fpsmaster/FPSMaster.java @@ -198,7 +198,9 @@ public void shutdown() { try { ClientLogger.info("Saving configs"); configManager.saveConfig("default"); - wsClient.close(200, "Shutdown"); + if (wsClient != null && wsClient.isOpen()) { + wsClient.close(200, "Shutdown"); + } } catch (FileException e) { throw new RuntimeException(e); } diff --git a/shared/java/top/fpsmaster/modules/client/GlobalTextFilter.java b/shared/java/top/fpsmaster/modules/client/GlobalTextFilter.java index a8d9627c..3e3d5c20 100644 --- a/shared/java/top/fpsmaster/modules/client/GlobalTextFilter.java +++ b/shared/java/top/fpsmaster/modules/client/GlobalTextFilter.java @@ -5,12 +5,12 @@ public class GlobalTextFilter { public static synchronized String filter(String text) { - if (!IRC.using || !IRC.showMates.getValue()) { - return NameProtect.filter(text); - } - - StringBuilder result = new StringBuilder(text); - result = new StringBuilder(NameProtect.filter(result.toString())); - return result.toString(); +// if (!IRC.using || !IRC.showMates.getValue()) { +// return NameProtect.filter(text); +// } + return NameProtect.filter(text); +// StringBuilder result = new StringBuilder(text); +// result = new StringBuilder(NameProtect.filter(result.toString())); +// return text; } } From eb64dff17641d6327a72823f1b524537ff5166d1 Mon Sep 17 00:00:00 2001 From: SuperSkidder Date: Sun, 20 Jul 2025 01:51:45 +0800 Subject: [PATCH 147/193] feat: allow users see capes each other fix: autogg triggers fix: some bugs --- .../fpsmaster/features/GlobalListener.java | 26 +++++++++++++------ .../impl/interfaces/MusicOverlay.java | 1 + .../features/impl/utility/AutoGG.java | 23 +++++++++++++--- .../features/impl/utility/LevelTag.java | 2 +- .../modules/client/ClientUsersManager.java | 6 ++--- .../assets/minecraft/client/lang/en_us.lang | 1 + .../assets/minecraft/client/lang/zh_cn.lang | 1 + 7 files changed, 45 insertions(+), 15 deletions(-) diff --git a/shared/java/top/fpsmaster/features/GlobalListener.java b/shared/java/top/fpsmaster/features/GlobalListener.java index 363e8a2c..27a30e91 100644 --- a/shared/java/top/fpsmaster/features/GlobalListener.java +++ b/shared/java/top/fpsmaster/features/GlobalListener.java @@ -11,6 +11,7 @@ import top.fpsmaster.features.impl.interfaces.ClientSettings; import top.fpsmaster.interfaces.ProviderManager; import top.fpsmaster.modules.account.AccountManager; +import top.fpsmaster.modules.client.ClientUser; import top.fpsmaster.modules.music.MusicPlayer; import top.fpsmaster.ui.notification.NotificationManager; import top.fpsmaster.utils.Utility; @@ -57,6 +58,7 @@ public void onChatSend(EventSendChatMessage e) { Map playerInfos = new ConcurrentHashMap<>(); Thread tickThread; + @Subscribe public void onTick(EventTick e) throws URISyntaxException { if (musicSwitchTimer.delay(500)) { @@ -84,6 +86,11 @@ public void onTick(EventTick e) throws URISyntaxException { FPSMaster.INSTANCE.wsClient.sendPing(); } } + if (mc.getNetHandler() == null) + return; + if (mc.getNetHandler().getPlayerInfoMap() == null) + return; + Set currentPlayers = mc.getNetHandler().getPlayerInfoMap().stream() .map(info -> info.getGameProfile().getId()) .collect(Collectors.toSet()); @@ -97,12 +104,7 @@ public void onTick(EventTick e) throws URISyntaxException { FPSMaster.INSTANCE.wsClient.fetchPlayer(uuid.toString(), info.getGameProfile().getName()); } } -// for (NetworkPlayerInfo networkPlayerInfo : mc.getNetHandler().getPlayerInfoMap()) { -// if (!playerInfos.contains(networkPlayerInfo)) { -// FPSMaster.INSTANCE.wsClient.fetchPlayer(networkPlayerInfo.getGameProfile().getId().toString(), networkPlayerInfo.getGameProfile().getName()); -// playerInfos.add(networkPlayerInfo); -// } -// } + if (playerInformation == null) { playerInformation = new PlayerInformation(ProviderManager.mcProvider.getPlayer().getName(), ProviderManager.mcProvider.getPlayer().getUniqueID().toString(), ProviderManager.mcProvider.getServerAddress(), AccountManager.cosmeticsUsing, AccountManager.skin); FPSMaster.INSTANCE.wsClient.sendInformation(AccountManager.skin, AccountManager.cosmeticsUsing, ProviderManager.mcProvider.getPlayer().getName(), ProviderManager.mcProvider.getServerAddress()); @@ -117,11 +119,19 @@ public void onTick(EventTick e) throws URISyntaxException { } @Subscribe - public void onCape(EventCapeLoading e){ + public void onCape(EventCapeLoading e) { if (!AccountManager.cosmeticsUsing.isEmpty()) { - e.setCachedCape("ornaments/" + AccountManager.cosmeticsUsing + "_resource"); + if (e.player == mc.thePlayer) + e.setCachedCape("ornaments/" + AccountManager.cosmeticsUsing + "_resource"); + else { + ClientUser clientUser = FPSMaster.clientUsersManager.getClientUser(e.player); + if (clientUser != null) { + e.setCachedCape("ornaments/" + clientUser.cosmetics + "_resource"); + } + } } } + @Subscribe public void onRender(EventRender2D e) { ScaledResolution scaledResolution = new ScaledResolution(Minecraft.getMinecraft()); diff --git a/shared/java/top/fpsmaster/features/impl/interfaces/MusicOverlay.java b/shared/java/top/fpsmaster/features/impl/interfaces/MusicOverlay.java index d59390fe..a9f91f1b 100644 --- a/shared/java/top/fpsmaster/features/impl/interfaces/MusicOverlay.java +++ b/shared/java/top/fpsmaster/features/impl/interfaces/MusicOverlay.java @@ -30,6 +30,7 @@ public MusicOverlay() { @Subscribe public void onRender(EventRender2D e) { if (timer.delay(50) && !updateThread.isAlive()) { + updateThread = new Thread(JLayerHelper::updateLoudness); updateThread.start(); } IngameOverlay.onRender(); diff --git a/shared/java/top/fpsmaster/features/impl/utility/AutoGG.java b/shared/java/top/fpsmaster/features/impl/utility/AutoGG.java index deb07f00..e2b301eb 100644 --- a/shared/java/top/fpsmaster/features/impl/utility/AutoGG.java +++ b/shared/java/top/fpsmaster/features/impl/utility/AutoGG.java @@ -1,12 +1,14 @@ package top.fpsmaster.features.impl.utility; import net.minecraft.util.StringUtils; +import top.fpsmaster.FPSMaster; import top.fpsmaster.event.Subscribe; import top.fpsmaster.event.events.EventPacket; import top.fpsmaster.features.manager.Category; import top.fpsmaster.features.manager.Module; import top.fpsmaster.features.settings.impl.BooleanSetting; import top.fpsmaster.features.settings.impl.ModeSetting; +import top.fpsmaster.features.settings.impl.NumberSetting; import top.fpsmaster.features.settings.impl.TextSetting; import top.fpsmaster.interfaces.ProviderManager; import top.fpsmaster.modules.logger.ClientLogger; @@ -16,12 +18,15 @@ public class AutoGG extends Module { public BooleanSetting autoPlay = new BooleanSetting("AutoPlay", false); + public NumberSetting delay = new NumberSetting("DelayToPlay", 5, 0, 10, 1, () -> autoPlay.getValue()); public TextSetting message = new TextSetting("Message", "gg"); public ModeSetting servers = new ModeSetting("Servers", 0, "hypxiel"); + public String hypixelTrigger = "Reward Summary;1st Killer;Damage Dealt;奖励总览;击杀数第一名;造成伤害"; + public AutoGG() { super("AutoGG", Category.Utility); - this.addSettings(autoPlay, message, servers); + this.addSettings(autoPlay, delay, message, servers); } @Subscribe @@ -32,13 +37,25 @@ public void onPacket(EventPacket event) { String componentValue = ProviderManager.packetChat.getChatComponent(event.packet).toString(); boolean hasPlayCommand = componentValue.contains("ClickEvent{action=RUN_COMMAND, value='/play "); String chatMessage = ProviderManager.packetChat.getUnformattedText(event.packet); - boolean hasEndInformation = StringUtils.stripControlCodes(chatMessage).contains(" 胜利者 ") || StringUtils.stripControlCodes(chatMessage).contains(" Winner - "); + boolean hasEndInformation = false; + for (String s : hypixelTrigger.split(";")) { + hasEndInformation = StringUtils.stripControlCodes(chatMessage).contains(s); + if (hasEndInformation) break; + } if (hasEndInformation) { Utility.sendChatMessage("/ac " + message.getValue()); } if (hasPlayCommand) { if (autoPlay.getValue()) { - Utility.sendChatMessage(componentValue.substring(componentValue.indexOf("value='") + 7, componentValue.indexOf("'}"))); + FPSMaster.async.runnable(() -> { + try { + Thread.sleep(delay.getValue().longValue() * 1000); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + Utility.sendClientNotify("Sending you to the next game in " + delay.getValue() + " seconds"); + Utility.sendChatMessage(componentValue.substring(componentValue.indexOf("value='") + 7, componentValue.indexOf("'}"))); + }); } } break; diff --git a/shared/java/top/fpsmaster/features/impl/utility/LevelTag.java b/shared/java/top/fpsmaster/features/impl/utility/LevelTag.java index bf9603ef..984f2adb 100644 --- a/shared/java/top/fpsmaster/features/impl/utility/LevelTag.java +++ b/shared/java/top/fpsmaster/features/impl/utility/LevelTag.java @@ -92,7 +92,7 @@ else if (mc.gameSettings.thirdPersonView == 1) i = -10; } - boolean isMate = ((entityIn == mc.thePlayer) && str.contains(entityIn.getName())) || FPSMaster.clientUsersManager.isClientUser(entityIn); + boolean isMate = ((entityIn == mc.thePlayer) && str.contains(entityIn.getName())) || FPSMaster.clientUsersManager.getClientUser(entityIn) != null; int j = fontRenderer.getStringWidth(str) / 2; diff --git a/shared/java/top/fpsmaster/modules/client/ClientUsersManager.java b/shared/java/top/fpsmaster/modules/client/ClientUsersManager.java index 9e515195..f7f0beeb 100644 --- a/shared/java/top/fpsmaster/modules/client/ClientUsersManager.java +++ b/shared/java/top/fpsmaster/modules/client/ClientUsersManager.java @@ -17,10 +17,10 @@ public void addFromFetch(SFetchPlayerPacket packet) { users.add(clientUser); } - public boolean isClientUser(Entity entityIn) { + public ClientUser getClientUser(Entity entityIn) { for (ClientUser user : users) if (user.uuid.equals(entityIn.getUniqueID().toString())) - return true; - return false; + return user; + return null; } } diff --git a/shared/resources/assets/minecraft/client/lang/en_us.lang b/shared/resources/assets/minecraft/client/lang/en_us.lang index f91b1afd..20d1e8fc 100644 --- a/shared/resources/assets/minecraft/client/lang/en_us.lang +++ b/shared/resources/assets/minecraft/client/lang/en_us.lang @@ -219,6 +219,7 @@ autogg.servers=Servers autogg.servers.hypxiel=Hypxiel autogg.message=Custom Message autogg.autoplay=Auto Play +autogg.delaytoplay=Auto Play Delay musicdisplay=Music HUD musicdisplay.desc=Displays current playing music diff --git a/shared/resources/assets/minecraft/client/lang/zh_cn.lang b/shared/resources/assets/minecraft/client/lang/zh_cn.lang index 99495b04..1f789daa 100644 --- a/shared/resources/assets/minecraft/client/lang/zh_cn.lang +++ b/shared/resources/assets/minecraft/client/lang/zh_cn.lang @@ -221,6 +221,7 @@ autogg.servers=服务器列表 autogg.servers.hypxiel=Hypxiel autogg.message=自定义消息 autogg.autoplay=自动重开 +autogg.delaytoplay=自动重开延迟 musicdisplay=音乐显示 musicdisplay.desc=显示你正在播放的音乐 From 837ca767b1b4e3e2f4e1417ea43c4b21b2b9a3f1 Mon Sep 17 00:00:00 2001 From: SuperSkidder Date: Sun, 20 Jul 2025 01:57:55 +0800 Subject: [PATCH 148/193] fix: a display bug of scoreboard when scaled fix: display bug of cosmetics gui --- shared/java/top/fpsmaster/ui/click/CosmeticScreen.java | 10 +++++----- .../top/fpsmaster/wrapper/mods/WrapperScoreboard.java | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/shared/java/top/fpsmaster/ui/click/CosmeticScreen.java b/shared/java/top/fpsmaster/ui/click/CosmeticScreen.java index 4224e752..01c34ffe 100644 --- a/shared/java/top/fpsmaster/ui/click/CosmeticScreen.java +++ b/shared/java/top/fpsmaster/ui/click/CosmeticScreen.java @@ -19,10 +19,10 @@ public class CosmeticScreen extends ScaledGuiScreen { public void render(int mouseX, int mouseY, float partialTicks) { super.render(mouseX, mouseY, partialTicks); String[] split = AccountManager.cosmeticsHeld.split(","); - Render2DUtils.drawRoundedRectImage(width / 2f - 200, height / 2f - 130, 400, 260, 4, new Color(0, 0, 0, 100)); + Render2DUtils.drawRoundedRectImage(guiWidth / 2f - 200, guiHeight / 2f - 130, 400, 260, 4, new Color(0, 0, 0, 100)); GL11.glEnable(GL11.GL_SCISSOR_TEST); - Render2DUtils.doGlScissor(width / 2f - 200, height / 2f - 130, 400, 260, scaleFactor); - container.draw(width / 2f - 200, height / 2f - 130, 400, 260, mouseX, mouseY, () -> { + Render2DUtils.doGlScissor(guiWidth / 2f - 200, guiHeight / 2f - 130, 400, 260, scaleFactor); + container.draw(guiWidth / 2f - 200, guiHeight / 2f - 130, 400, 260, mouseX, mouseY, () -> { int y = 0; for (String id : split) { if (id.isEmpty()) @@ -31,7 +31,7 @@ public void render(int mouseX, int mouseY, float partialTicks) { if (!cosmetic.loaded) { cosmetic.load(); } - FPSMaster.fontManager.s18.drawString(cosmetic.name, width / 2f - 190, height / 2f - 120 + y + container.getScroll(), id.equals(AccountManager.cosmeticsUsing) ? Color.GREEN.getRGB() : Color.WHITE.getRGB()); + FPSMaster.fontManager.s18.drawString(cosmetic.name, guiWidth / 2f - 190, guiHeight / 2f - 120 + y + container.getScroll(), id.equals(AccountManager.cosmeticsUsing) ? Color.GREEN.getRGB() : Color.WHITE.getRGB()); y += 20; } container.setHeight(y); @@ -66,7 +66,7 @@ protected void mouseClicked(int mouseX, int mouseY, int mouseButton) throws IOEx Cosmetic cosmetic = AccountManager.cosmetics.get(Integer.parseInt(id)); if (!cosmetic.loaded) cosmetic.load(); - if (Render2DUtils.isHovered(width / 2f - 200, height / 2f - 120 + y, 400, 20, mouseX, mouseY)) { + if (Render2DUtils.isHovered(guiWidth / 2f - 200, guiHeight / 2f - 120 + y, 400, 20, mouseX, mouseY)) { String cosmeticsUsing = String.valueOf(cosmetic.id); if (AccountManager.cosmeticsUsing.equals(cosmeticsUsing)) { AccountManager.cosmeticsUsing = ""; diff --git a/v1.8.9/src/main/java/top/fpsmaster/wrapper/mods/WrapperScoreboard.java b/v1.8.9/src/main/java/top/fpsmaster/wrapper/mods/WrapperScoreboard.java index 1f18d992..b62d21d5 100644 --- a/v1.8.9/src/main/java/top/fpsmaster/wrapper/mods/WrapperScoreboard.java +++ b/v1.8.9/src/main/java/top/fpsmaster/wrapper/mods/WrapperScoreboard.java @@ -69,7 +69,7 @@ public static float[] render(ScoreboardComponent scoreboardComponent, InterfaceM if (j == collection.size()) { String s3 = objective.getDisplayName(); scoreboardComponent.drawRect(x, y, i, height1 + 1, mod.backgroundColor.getColor()); - scoreboardComponent.drawString(16, s3, (int) (x + 2 + (float) i / 2 - scoreboardComponent.getStringWidth(16, s3) / 2f), y, -1); + scoreboardComponent.drawString(16, s3, (int) (x + 2 + ((float) i / 2 - scoreboardComponent.getStringWidth(16, s3) / 2f) * scoreboardComponent.scale), y, -1); } scoreboardComponent.drawString(16, s1, ((int) x) + 2, (int) (y + (h - k) * scoreboardComponent.scale), -1); // 红字 From 100892c338e9a1e2e65afe176d8962d02a2d39c7 Mon Sep 17 00:00:00 2001 From: SuperSkidder Date: Sun, 20 Jul 2025 12:32:21 +0800 Subject: [PATCH 149/193] feat: support animated cloaks fix: click problem of cosmetics --- .../fpsmaster/features/GlobalListener.java | 29 ++++++++++++-- .../fpsmaster/modules/account/Cosmetic.java | 38 +++++++++++++++---- .../fpsmaster/ui/click/CosmeticScreen.java | 3 +- .../java/top/fpsmaster/utils/awt/GifUtil.java | 5 ++- .../top/fpsmaster/utils/os/HttpRequest.java | 10 +++++ 5 files changed, 71 insertions(+), 14 deletions(-) diff --git a/shared/java/top/fpsmaster/features/GlobalListener.java b/shared/java/top/fpsmaster/features/GlobalListener.java index 27a30e91..aff3d994 100644 --- a/shared/java/top/fpsmaster/features/GlobalListener.java +++ b/shared/java/top/fpsmaster/features/GlobalListener.java @@ -11,6 +11,7 @@ import top.fpsmaster.features.impl.interfaces.ClientSettings; import top.fpsmaster.interfaces.ProviderManager; import top.fpsmaster.modules.account.AccountManager; +import top.fpsmaster.modules.account.Cosmetic; import top.fpsmaster.modules.client.ClientUser; import top.fpsmaster.modules.music.MusicPlayer; import top.fpsmaster.ui.notification.NotificationManager; @@ -121,12 +122,34 @@ public void onTick(EventTick e) throws URISyntaxException { @Subscribe public void onCape(EventCapeLoading e) { if (!AccountManager.cosmeticsUsing.isEmpty()) { + String[] cosmetics; + if (e.player == mc.thePlayer) - e.setCachedCape("ornaments/" + AccountManager.cosmeticsUsing + "_resource"); + cosmetics = AccountManager.cosmeticsUsing.split(","); else { ClientUser clientUser = FPSMaster.clientUsersManager.getClientUser(e.player); - if (clientUser != null) { - e.setCachedCape("ornaments/" + clientUser.cosmetics + "_resource"); + if (clientUser == null) + return; + cosmetics = clientUser.cosmetics.split(","); + } + + for (String cosmetic : cosmetics) { + if (cosmetic.isEmpty()) + continue; + Cosmetic cosmetic1 = AccountManager.cosmetics.get(Integer.valueOf(cosmetic)); + if (cosmetic1.resource.endsWith(".gif")) { + if (cosmetic1.frame < cosmetic1.frames.size() - 1){ + if (System.currentTimeMillis() - cosmetic1.frameTime > cosmetic1.frames.get(cosmetic1.frame).delay) { + cosmetic1.frame++; + cosmetic1.frameTime = System.currentTimeMillis(); + } + }else{ + cosmetic1.frame = 0; + cosmetic1.frameTime = System.currentTimeMillis(); + } + e.setCachedCape("ornaments/" + cosmetic + "_resource_" + cosmetic1.frame); + } else { + e.setCachedCape("ornaments/" + cosmetic + "_resource"); } } } diff --git a/shared/java/top/fpsmaster/modules/account/Cosmetic.java b/shared/java/top/fpsmaster/modules/account/Cosmetic.java index c856ec1c..b895fbaf 100644 --- a/shared/java/top/fpsmaster/modules/account/Cosmetic.java +++ b/shared/java/top/fpsmaster/modules/account/Cosmetic.java @@ -3,11 +3,16 @@ import com.google.gson.JsonObject; import net.minecraft.client.renderer.ThreadDownloadImageData; import net.minecraft.util.ResourceLocation; +import scala.Int; import top.fpsmaster.FPSMaster; +import top.fpsmaster.utils.awt.GifUtil; import top.fpsmaster.utils.os.HttpRequest; import java.awt.image.BufferedImage; import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.List; import static top.fpsmaster.utils.Utility.mc; @@ -20,6 +25,9 @@ public class Cosmetic { public boolean available; public String resource; public boolean loaded; + public Integer frame = 0; + public long frameTime = 0; + public List frames = new ArrayList<>(); public Cosmetic() { } @@ -27,13 +35,29 @@ public Cosmetic() { public void load() { if (mc.theWorld == null) return; FPSMaster.async.runnable(() -> { - ResourceLocation textureLocation = new ResourceLocation("ornaments/" + id + "_resource"); - ThreadDownloadImageData downloadImageData = new ThreadDownloadImageData(null, resource, textureLocation, null); - try { - downloadImageData.setBufferedImage(HttpRequest.downloadImage(resource)); - mc.getTextureManager().loadTexture(textureLocation, downloadImageData); - } catch (IOException e) { - throw new RuntimeException(e); + if (resource.endsWith(".png")) { + ResourceLocation textureLocation = new ResourceLocation("ornaments/" + id + "_resource"); + ThreadDownloadImageData downloadImageData = new ThreadDownloadImageData(null, "", textureLocation, null); + try { + downloadImageData.setBufferedImage(HttpRequest.downloadImage(resource)); + mc.getTextureManager().loadTexture(textureLocation, downloadImageData); + } catch (IOException e) { + throw new RuntimeException(e); + } + } else if (resource.endsWith(".gif")) { + try { + InputStream inputStream = HttpRequest.downloadFile(resource); + frames.clear(); + frames = GifUtil.convertGifToPng(inputStream); + for (GifUtil.FrameData frame : frames) { + ResourceLocation textureLocation = new ResourceLocation("ornaments/" + id + "_resource_" + frames.indexOf(frame)); + ThreadDownloadImageData downloadImageData = new ThreadDownloadImageData(null, "", textureLocation, null); + downloadImageData.setBufferedImage(frame.image); + mc.getTextureManager().loadTexture(textureLocation, downloadImageData); + } + } catch (IOException e) { + throw new RuntimeException(e); + } } }); loaded = true; diff --git a/shared/java/top/fpsmaster/ui/click/CosmeticScreen.java b/shared/java/top/fpsmaster/ui/click/CosmeticScreen.java index 01c34ffe..6963bcc3 100644 --- a/shared/java/top/fpsmaster/ui/click/CosmeticScreen.java +++ b/shared/java/top/fpsmaster/ui/click/CosmeticScreen.java @@ -56,8 +56,7 @@ public void initGui() { } @Override - protected void mouseClicked(int mouseX, int mouseY, int mouseButton) throws IOException { - super.mouseClicked(mouseX, mouseY, mouseButton); + public void onClick(int mouseX, int mouseY, int mouseButton) { String[] split = AccountManager.cosmeticsHeld.split(","); int y = 0; for (String id : split) { diff --git a/shared/java/top/fpsmaster/utils/awt/GifUtil.java b/shared/java/top/fpsmaster/utils/awt/GifUtil.java index 6aa86344..a4eb6b83 100644 --- a/shared/java/top/fpsmaster/utils/awt/GifUtil.java +++ b/shared/java/top/fpsmaster/utils/awt/GifUtil.java @@ -13,6 +13,7 @@ import java.awt.image.BufferedImage; import java.io.File; import java.io.IOException; +import java.io.InputStream; import java.util.ArrayList; import java.util.List; @@ -27,10 +28,10 @@ public FrameData(BufferedImage image, int delay) { } } - public static List convertGifToPng(String gifPath) throws IOException { + public static List convertGifToPng(InputStream stream) throws IOException { // 读取GIF ImageReader reader = ImageIO.getImageReadersByFormatName("gif").next(); - ImageInputStream in = ImageIO.createImageInputStream(new File(gifPath)); + ImageInputStream in = ImageIO.createImageInputStream(stream); reader.setInput(in); // 获取GIF的帧数 diff --git a/shared/java/top/fpsmaster/utils/os/HttpRequest.java b/shared/java/top/fpsmaster/utils/os/HttpRequest.java index 001c9bb9..c7552024 100644 --- a/shared/java/top/fpsmaster/utils/os/HttpRequest.java +++ b/shared/java/top/fpsmaster/utils/os/HttpRequest.java @@ -143,6 +143,16 @@ public static boolean downloadFile(String url, String filepath) { } } + // download file to buffer + public static InputStream downloadFile(String url) { + try { + return HTTP_CLIENT.execute(new HttpGet(url)).getEntity().getContent(); + } catch (Exception e) { + ClientLogger.error("Download failed: " + e.getMessage()); + return null; + } + } + public static void downloadAsync(String url, String filepath, Runnable callback) { new Thread(() -> { boolean success = downloadFile(url, filepath); From f675164638218dba464eef6f618213c73f98403b Mon Sep 17 00:00:00 2001 From: SuperSkidder Date: Sun, 20 Jul 2025 13:20:59 +0800 Subject: [PATCH 150/193] fix: possible sync bug --- shared/java/top/fpsmaster/features/GlobalListener.java | 2 +- .../top/fpsmaster/modules/client/ClientUsersManager.java | 7 +++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/shared/java/top/fpsmaster/features/GlobalListener.java b/shared/java/top/fpsmaster/features/GlobalListener.java index aff3d994..ab0c86eb 100644 --- a/shared/java/top/fpsmaster/features/GlobalListener.java +++ b/shared/java/top/fpsmaster/features/GlobalListener.java @@ -109,7 +109,7 @@ public void onTick(EventTick e) throws URISyntaxException { if (playerInformation == null) { playerInformation = new PlayerInformation(ProviderManager.mcProvider.getPlayer().getName(), ProviderManager.mcProvider.getPlayer().getUniqueID().toString(), ProviderManager.mcProvider.getServerAddress(), AccountManager.cosmeticsUsing, AccountManager.skin); FPSMaster.INSTANCE.wsClient.sendInformation(AccountManager.skin, AccountManager.cosmeticsUsing, ProviderManager.mcProvider.getPlayer().getName(), ProviderManager.mcProvider.getServerAddress()); - } else if (!playerInformation.serverAddress.equals(ProviderManager.mcProvider.getServerAddress()) || !playerInformation.name.equals(ProviderManager.mcProvider.getPlayer().getName()) || !playerInformation.skin.equals(AccountManager.skin) || !playerInformation.uuid.equals(ProviderManager.mcProvider.getPlayer().getUniqueID().toString())) { + } else if (!playerInformation.serverAddress.equals(ProviderManager.mcProvider.getServerAddress()) || !playerInformation.name.equals(ProviderManager.mcProvider.getPlayer().getName()) || !playerInformation.skin.equals(AccountManager.skin) || !playerInformation.uuid.equals(ProviderManager.mcProvider.getPlayer().getUniqueID().toString()) || !playerInformation.cosmetics.equals(AccountManager.cosmeticsUsing)) { playerInformation = new PlayerInformation(ProviderManager.mcProvider.getPlayer().getName(), ProviderManager.mcProvider.getPlayer().getUniqueID().toString(), ProviderManager.mcProvider.getServerAddress(), AccountManager.cosmeticsUsing, AccountManager.skin); FPSMaster.INSTANCE.wsClient.sendInformation(AccountManager.skin, AccountManager.cosmeticsUsing, ProviderManager.mcProvider.getPlayer().getName(), ProviderManager.mcProvider.getServerAddress()); } diff --git a/shared/java/top/fpsmaster/modules/client/ClientUsersManager.java b/shared/java/top/fpsmaster/modules/client/ClientUsersManager.java index f7f0beeb..f0258f23 100644 --- a/shared/java/top/fpsmaster/modules/client/ClientUsersManager.java +++ b/shared/java/top/fpsmaster/modules/client/ClientUsersManager.java @@ -10,16 +10,19 @@ public class ClientUsersManager { public void addFromFetch(SFetchPlayerPacket packet) { ClientUser clientUser = new ClientUser(packet.uid, packet.name, packet.uuid, packet.gameId, packet.cosmetics, packet.skin, packet.rank, packet.customRank); + ClientUser rm = null; for (ClientUser user : users) { if (user.uid.equals(clientUser.uid)) - return; + rm = user; } + if (rm != null) + users.remove(rm); users.add(clientUser); } public ClientUser getClientUser(Entity entityIn) { for (ClientUser user : users) - if (user.uuid.equals(entityIn.getUniqueID().toString())) + if (user.gameId.equals(entityIn.getName()) && user.uuid.equals(entityIn.getUniqueID().toString())) return user; return null; } From 3c8e5656bbfc0feaa0968b284f47b33c10a3d640 Mon Sep 17 00:00:00 2001 From: SuperSkidder Date: Sun, 20 Jul 2025 15:18:59 +0800 Subject: [PATCH 151/193] bug fixes fix: scroll bugs fix: cosmetics bugs fix: irc bugs --- .../fpsmaster/features/GlobalListener.java | 129 +++++++++++------- .../features/command/impl/IRCChat.java | 2 +- .../modules/account/AccountManager.java | 1 + .../fpsmaster/modules/account/Cosmetic.java | 4 +- .../modules/client/ClientUsersManager.java | 3 + .../fpsmaster/ui/click/CosmeticScreen.java | 2 - .../ui/click/component/ScrollContainer.java | 2 +- 7 files changed, 86 insertions(+), 57 deletions(-) diff --git a/shared/java/top/fpsmaster/features/GlobalListener.java b/shared/java/top/fpsmaster/features/GlobalListener.java index ab0c86eb..53fe8d80 100644 --- a/shared/java/top/fpsmaster/features/GlobalListener.java +++ b/shared/java/top/fpsmaster/features/GlobalListener.java @@ -3,6 +3,7 @@ import net.minecraft.client.Minecraft; import net.minecraft.client.gui.ScaledResolution; import net.minecraft.client.network.NetworkPlayerInfo; +import org.java_websocket.enums.ReadyState; import org.lwjgl.input.Mouse; import top.fpsmaster.FPSMaster; import top.fpsmaster.event.EventDispatcher; @@ -59,33 +60,51 @@ public void onChatSend(EventSendChatMessage e) { Map playerInfos = new ConcurrentHashMap<>(); Thread tickThread; + Thread accThread; @Subscribe public void onTick(EventTick e) throws URISyntaxException { - if (musicSwitchTimer.delay(500)) { - if (tickThread == null || !tickThread.isAlive()) { - tickThread = new Thread(() -> { - if (MusicPlayer.isPlaying && MusicPlayer.getPlayProgress() > 0.999) { - MusicPlayer.playList.next(); - } - if (ProviderManager.mcProvider.getWorld() != null) { - Utility.flush(); - } - if (FPSMaster.INSTANCE.loggedIn) { - if (FPSMaster.INSTANCE.wsClient == null) { - try { - FPSMaster.INSTANCE.wsClient = WsClient.start("wss://service.fpsmaster.top/"); - } catch (URISyntaxException ex) { - throw new RuntimeException(ex); - } - Utility.sendClientDebug("尝试连接"); - } else if (FPSMaster.INSTANCE.wsClient.isClosed() && !FPSMaster.INSTANCE.wsClient.isOpen()) { - FPSMaster.INSTANCE.wsClient.close(); - FPSMaster.INSTANCE.wsClient.connect(); - Utility.sendClientDebug("尝试重连"); - } else { - FPSMaster.INSTANCE.wsClient.sendPing(); + if (tickThread == null || !tickThread.isAlive()) { + tickThread = new Thread(() -> { + try { + Thread.sleep(1000); + } catch (InterruptedException ex) { + throw new RuntimeException(ex); + } + if (MusicPlayer.isPlaying && MusicPlayer.getPlayProgress() > 0.999) { + MusicPlayer.playList.next(); + } + if (ProviderManager.mcProvider.getWorld() != null) { + Utility.flush(); + } + }); + tickThread.start(); + } + + + if (accThread == null || !accThread.isAlive()) { + accThread = new Thread(() -> { + try { + Thread.sleep(5000); + } catch (InterruptedException ex) { + throw new RuntimeException(ex); + } + if (FPSMaster.INSTANCE.loggedIn) { + if (FPSMaster.INSTANCE.wsClient == null) { + try { + FPSMaster.INSTANCE.wsClient = WsClient.start("wss://service.fpsmaster.top/"); + } catch (URISyntaxException ex) { + throw new RuntimeException(ex); } + Utility.sendClientDebug("尝试连接"); + } else if (FPSMaster.INSTANCE.wsClient.isClosed() || FPSMaster.INSTANCE.wsClient.getReadyState() != ReadyState.OPEN) { + FPSMaster.INSTANCE.wsClient.close(); + FPSMaster.INSTANCE.wsClient.connect(); + playerInformation = null; + playerInfos.clear(); + Utility.sendClientDebug("尝试重连"); + } else { + FPSMaster.INSTANCE.wsClient.sendPing(); } if (mc.getNetHandler() == null) return; @@ -98,6 +117,10 @@ public void onTick(EventTick e) throws URISyntaxException { playerInfos.keySet().retainAll(currentPlayers); + + if (FPSMaster.INSTANCE.wsClient.getReadyState() != ReadyState.OPEN) + return; + for (NetworkPlayerInfo info : mc.getNetHandler().getPlayerInfoMap()) { UUID uuid = info.getGameProfile().getId(); if (!playerInfos.containsKey(uuid)) { @@ -106,6 +129,10 @@ public void onTick(EventTick e) throws URISyntaxException { } } + for (ClientUser user : FPSMaster.clientUsersManager.users) { + FPSMaster.INSTANCE.wsClient.fetchPlayer(user.uuid, user.name); + } + if (playerInformation == null) { playerInformation = new PlayerInformation(ProviderManager.mcProvider.getPlayer().getName(), ProviderManager.mcProvider.getPlayer().getUniqueID().toString(), ProviderManager.mcProvider.getServerAddress(), AccountManager.cosmeticsUsing, AccountManager.skin); FPSMaster.INSTANCE.wsClient.sendInformation(AccountManager.skin, AccountManager.cosmeticsUsing, ProviderManager.mcProvider.getPlayer().getName(), ProviderManager.mcProvider.getServerAddress()); @@ -113,44 +140,44 @@ public void onTick(EventTick e) throws URISyntaxException { playerInformation = new PlayerInformation(ProviderManager.mcProvider.getPlayer().getName(), ProviderManager.mcProvider.getPlayer().getUniqueID().toString(), ProviderManager.mcProvider.getServerAddress(), AccountManager.cosmeticsUsing, AccountManager.skin); FPSMaster.INSTANCE.wsClient.sendInformation(AccountManager.skin, AccountManager.cosmeticsUsing, ProviderManager.mcProvider.getPlayer().getName(), ProviderManager.mcProvider.getServerAddress()); } - }); - tickThread.start(); - } + } + }); + accThread.start(); } } @Subscribe public void onCape(EventCapeLoading e) { - if (!AccountManager.cosmeticsUsing.isEmpty()) { - String[] cosmetics; - - if (e.player == mc.thePlayer) - cosmetics = AccountManager.cosmeticsUsing.split(","); - else { - ClientUser clientUser = FPSMaster.clientUsersManager.getClientUser(e.player); - if (clientUser == null) - return; - cosmetics = clientUser.cosmetics.split(","); - } + String[] cosmetics; + + if (e.player == mc.thePlayer) { + if (AccountManager.cosmeticsUsing.isEmpty()) + return; + cosmetics = AccountManager.cosmeticsUsing.split(","); + } else { + ClientUser clientUser = FPSMaster.clientUsersManager.getClientUser(e.player); + if (clientUser == null) + return; + cosmetics = clientUser.cosmetics.split(","); + } - for (String cosmetic : cosmetics) { - if (cosmetic.isEmpty()) - continue; - Cosmetic cosmetic1 = AccountManager.cosmetics.get(Integer.valueOf(cosmetic)); - if (cosmetic1.resource.endsWith(".gif")) { - if (cosmetic1.frame < cosmetic1.frames.size() - 1){ - if (System.currentTimeMillis() - cosmetic1.frameTime > cosmetic1.frames.get(cosmetic1.frame).delay) { - cosmetic1.frame++; - cosmetic1.frameTime = System.currentTimeMillis(); - } - }else{ - cosmetic1.frame = 0; + for (String cosmetic : cosmetics) { + if (cosmetic.isEmpty()) + continue; + Cosmetic cosmetic1 = AccountManager.cosmetics.get(Integer.valueOf(cosmetic)); + if (cosmetic1.resource.endsWith(".gif")) { + if (cosmetic1.frame < cosmetic1.frames.size() - 1) { + if (System.currentTimeMillis() - cosmetic1.frameTime > cosmetic1.frames.get(cosmetic1.frame).delay) { + cosmetic1.frame++; cosmetic1.frameTime = System.currentTimeMillis(); } - e.setCachedCape("ornaments/" + cosmetic + "_resource_" + cosmetic1.frame); } else { - e.setCachedCape("ornaments/" + cosmetic + "_resource"); + cosmetic1.frame = 0; + cosmetic1.frameTime = System.currentTimeMillis(); } + e.setCachedCape("ornaments/" + cosmetic + "_resource_" + cosmetic1.frame); + } else { + e.setCachedCape("ornaments/" + cosmetic + "_resource"); } } } diff --git a/shared/java/top/fpsmaster/features/command/impl/IRCChat.java b/shared/java/top/fpsmaster/features/command/impl/IRCChat.java index 8b6ed037..2f4f5d00 100644 --- a/shared/java/top/fpsmaster/features/command/impl/IRCChat.java +++ b/shared/java/top/fpsmaster/features/command/impl/IRCChat.java @@ -46,7 +46,7 @@ public void execute(String[] args) { String message = sb.toString(); FPSMaster.INSTANCE.wsClient.sendDM(args[1], message); } else if ("update".equals(args[0])) { - FPSMaster.INSTANCE.wsClient.sendInformation(AccountManager.skin, "", ProviderManager.mcProvider.getPlayer().getName(), ProviderManager.mcProvider.getServerAddress()); + FPSMaster.INSTANCE.wsClient.sendInformation(AccountManager.skin, AccountManager.cosmeticsUsing, ProviderManager.mcProvider.getPlayer().getName(), ProviderManager.mcProvider.getServerAddress()); } else if ("fetch".equals(args[0])) { for (NetworkPlayerInfo networkPlayerInfo : mc.getNetHandler().getPlayerInfoMap()) { FPSMaster.INSTANCE.wsClient.fetchPlayer(networkPlayerInfo.getGameProfile().getId().toString(), networkPlayerInfo.getGameProfile().getName()); diff --git a/shared/java/top/fpsmaster/modules/account/AccountManager.java b/shared/java/top/fpsmaster/modules/account/AccountManager.java index a516803e..e84787d1 100644 --- a/shared/java/top/fpsmaster/modules/account/AccountManager.java +++ b/shared/java/top/fpsmaster/modules/account/AccountManager.java @@ -133,6 +133,7 @@ public void refreshCosmetics() throws AccountException { cosmetic.available = asJsonObject.get("available").getAsBoolean(); cosmetic.resource = asJsonObject.get("resource").getAsString(); cosmetics.put(cosmetic.id, cosmetic); + cosmetic.load(); } } catch (Exception e) { throw new AccountException("Failed to login via token"); diff --git a/shared/java/top/fpsmaster/modules/account/Cosmetic.java b/shared/java/top/fpsmaster/modules/account/Cosmetic.java index b895fbaf..d48df695 100644 --- a/shared/java/top/fpsmaster/modules/account/Cosmetic.java +++ b/shared/java/top/fpsmaster/modules/account/Cosmetic.java @@ -37,7 +37,7 @@ public void load() { FPSMaster.async.runnable(() -> { if (resource.endsWith(".png")) { ResourceLocation textureLocation = new ResourceLocation("ornaments/" + id + "_resource"); - ThreadDownloadImageData downloadImageData = new ThreadDownloadImageData(null, "", textureLocation, null); + ThreadDownloadImageData downloadImageData = new ThreadDownloadImageData(null, null, textureLocation, null); try { downloadImageData.setBufferedImage(HttpRequest.downloadImage(resource)); mc.getTextureManager().loadTexture(textureLocation, downloadImageData); @@ -51,7 +51,7 @@ public void load() { frames = GifUtil.convertGifToPng(inputStream); for (GifUtil.FrameData frame : frames) { ResourceLocation textureLocation = new ResourceLocation("ornaments/" + id + "_resource_" + frames.indexOf(frame)); - ThreadDownloadImageData downloadImageData = new ThreadDownloadImageData(null, "", textureLocation, null); + ThreadDownloadImageData downloadImageData = new ThreadDownloadImageData(null, null, textureLocation, null); downloadImageData.setBufferedImage(frame.image); mc.getTextureManager().loadTexture(textureLocation, downloadImageData); } diff --git a/shared/java/top/fpsmaster/modules/client/ClientUsersManager.java b/shared/java/top/fpsmaster/modules/client/ClientUsersManager.java index f0258f23..1d8c4141 100644 --- a/shared/java/top/fpsmaster/modules/client/ClientUsersManager.java +++ b/shared/java/top/fpsmaster/modules/client/ClientUsersManager.java @@ -1,6 +1,8 @@ package top.fpsmaster.modules.client; import net.minecraft.entity.Entity; +import top.fpsmaster.modules.logger.ClientLogger; +import top.fpsmaster.utils.Utility; import top.fpsmaster.websocket.data.message.server.SFetchPlayerPacket; import java.util.ArrayList; @@ -18,6 +20,7 @@ public void addFromFetch(SFetchPlayerPacket packet) { if (rm != null) users.remove(rm); users.add(clientUser); + Utility.sendClientDebug("Add user: " + clientUser.name + " " + clientUser.uid + " " + clientUser.uuid + " " + clientUser.gameId + " " + clientUser.rank + " " + clientUser.customRank + " " + clientUser.cosmetics + " " + clientUser.skin); } public ClientUser getClientUser(Entity entityIn) { diff --git a/shared/java/top/fpsmaster/ui/click/CosmeticScreen.java b/shared/java/top/fpsmaster/ui/click/CosmeticScreen.java index 6963bcc3..6fb5419d 100644 --- a/shared/java/top/fpsmaster/ui/click/CosmeticScreen.java +++ b/shared/java/top/fpsmaster/ui/click/CosmeticScreen.java @@ -63,8 +63,6 @@ public void onClick(int mouseX, int mouseY, int mouseButton) { if (id.isEmpty()) continue; Cosmetic cosmetic = AccountManager.cosmetics.get(Integer.parseInt(id)); - if (!cosmetic.loaded) - cosmetic.load(); if (Render2DUtils.isHovered(guiWidth / 2f - 200, guiHeight / 2f - 120 + y, 400, 20, mouseX, mouseY)) { String cosmeticsUsing = String.valueOf(cosmetic.id); if (AccountManager.cosmeticsUsing.equals(cosmeticsUsing)) { diff --git a/shared/java/top/fpsmaster/ui/click/component/ScrollContainer.java b/shared/java/top/fpsmaster/ui/click/component/ScrollContainer.java index 093798d3..9fefac9f 100644 --- a/shared/java/top/fpsmaster/ui/click/component/ScrollContainer.java +++ b/shared/java/top/fpsmaster/ui/click/component/ScrollContainer.java @@ -59,7 +59,7 @@ public void draw(float x, float y, float width, float height, int mouseX, int mo wheel_anim = -((mouseY - scrollStart - y) / height) * this.height; } else { isScrolling = false; - MainPanel.bindLock = "null"; + MainPanel.dragLock = "null"; } } } else { From a19a6e67a9efd9c9bfc6b70993532c573a4de477 Mon Sep 17 00:00:00 2001 From: SuperSkidder Date: Sun, 20 Jul 2025 15:59:27 +0800 Subject: [PATCH 152/193] feat: draw client icon in tab gui fix: client icon only show when leveltag is enabled --- .../features/impl/utility/LevelTag.java | 4 + .../features/manager/ModuleManager.java | 2 + .../modules/client/ClientUsersManager.java | 7 + .../forge/mixin/MixinGuiPlayerOverlay.java | 173 +++++++++++++++++- .../fpsmaster/forge/mixin/MixinRender.java | 12 +- 5 files changed, 190 insertions(+), 8 deletions(-) diff --git a/shared/java/top/fpsmaster/features/impl/utility/LevelTag.java b/shared/java/top/fpsmaster/features/impl/utility/LevelTag.java index 984f2adb..a04b6bab 100644 --- a/shared/java/top/fpsmaster/features/impl/utility/LevelTag.java +++ b/shared/java/top/fpsmaster/features/impl/utility/LevelTag.java @@ -31,6 +31,8 @@ public LevelTag() { } public static void renderHealth(Entity entityIn, String str, double x, double y, double z, int maxDistance) { + if (!using) + return; if(!str.contains(entityIn.getName()) || !(entityIn instanceof EntityPlayer)) return; if (str.contains("[NPC]")) @@ -65,6 +67,8 @@ else if (mc.gameSettings.thirdPersonView == 1) } public static void renderName(Entity entityIn, String str, double x, double y, double z, int maxDistance) { + if ((!using || !showSelf.getValue()) && entityIn == mc.thePlayer) + return; double d = entityIn.getDistanceSqToEntity(mc.getRenderManager().livingPlayer); if (!(d > (double)(maxDistance * maxDistance))) { FontRenderer fontRenderer = mc.fontRendererObj; diff --git a/shared/java/top/fpsmaster/features/manager/ModuleManager.java b/shared/java/top/fpsmaster/features/manager/ModuleManager.java index e3fd82ab..a2d27dc0 100644 --- a/shared/java/top/fpsmaster/features/manager/ModuleManager.java +++ b/shared/java/top/fpsmaster/features/manager/ModuleManager.java @@ -121,6 +121,8 @@ public void init() { modules.add(new MiniMap()); modules.add(new DirectionDisplay()); modules.add(new DamageIndicator()); + modules.add(new TabOverlay()); + if (ProviderManager.constants.getVersion().equals("1.12.2")) { modules.add(new HideIndicator()); diff --git a/shared/java/top/fpsmaster/modules/client/ClientUsersManager.java b/shared/java/top/fpsmaster/modules/client/ClientUsersManager.java index 1d8c4141..da19a86d 100644 --- a/shared/java/top/fpsmaster/modules/client/ClientUsersManager.java +++ b/shared/java/top/fpsmaster/modules/client/ClientUsersManager.java @@ -29,4 +29,11 @@ public ClientUser getClientUser(Entity entityIn) { return user; return null; } + + public ClientUser getClientUser(String name, String uuid) { + for (ClientUser user : users) + if (user.gameId.equals(name) && user.uuid.equals(uuid)) + return user; + return null; + } } diff --git a/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinGuiPlayerOverlay.java b/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinGuiPlayerOverlay.java index d7191502..be4dd584 100644 --- a/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinGuiPlayerOverlay.java +++ b/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinGuiPlayerOverlay.java @@ -10,25 +10,36 @@ import net.minecraft.client.renderer.GlStateManager; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EnumPlayerModelParts; +import net.minecraft.scoreboard.IScoreObjectiveCriteria; import net.minecraft.scoreboard.ScoreObjective; import net.minecraft.scoreboard.Scoreboard; +import net.minecraft.util.EnumChatFormatting; import net.minecraft.util.IChatComponent; import net.minecraft.util.ResourceLocation; +import net.minecraft.world.WorldSettings; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Overwrite; import org.spongepowered.asm.mixin.Shadow; import top.fpsmaster.FPSMaster; +import top.fpsmaster.features.impl.interfaces.TabOverlay; +import top.fpsmaster.modules.account.AccountManager; +import top.fpsmaster.modules.client.ClientUser; +import top.fpsmaster.utils.render.Render2DUtils; import javax.annotation.Nullable; +import java.awt.*; import java.util.Iterator; import java.util.List; +import static top.fpsmaster.utils.Utility.mc; + @Mixin(GuiPlayerTabOverlay.class) public abstract class MixinGuiPlayerOverlay { - Minecraft mc = Minecraft.getMinecraft(); - + @Final + @Shadow + private static Ordering field_175252_a; @Shadow public abstract String getPlayerName(NetworkPlayerInfo networkPlayerInfoIn); @@ -44,4 +55,162 @@ public abstract class MixinGuiPlayerOverlay { @Shadow protected abstract void drawPing(int i, int j, int k, NetworkPlayerInfo networkPlayerInfoIn); + + + /** + * @author SuperSkidder + * @reason BetterTabUI + */ + @Overwrite + public void renderPlayerlist(int width, Scoreboard scoreboardIn, ScoreObjective scoreObjectiveIn) { + width += 10; + NetHandlerPlayClient netHandlerPlayClient = mc.thePlayer.sendQueue; + List list = field_175252_a.sortedCopy(netHandlerPlayClient.getPlayerInfoMap()); + int i = 0; + int j = 0; + for (NetworkPlayerInfo networkPlayerInfo : list) { + int k = mc.fontRendererObj.getStringWidth(this.getPlayerName(networkPlayerInfo)); + i = Math.max(i, k); + if (scoreObjectiveIn != null && scoreObjectiveIn.getRenderType() != IScoreObjectiveCriteria.EnumRenderType.HEARTS) { + k = mc.fontRendererObj.getStringWidth(" " + scoreboardIn.getValueFromObjective(networkPlayerInfo.getGameProfile().getName(), scoreObjectiveIn).getScorePoints()); + j = Math.max(j, k); + } + } + + list = list.subList(0, Math.min(list.size(), 80)); + int l = list.size(); + int m = l; + + int k; + for (k = 1; m > 20; m = (l + k - 1) / k) { + ++k; + } + + boolean bl = mc.isIntegratedServerRunning() || mc.getNetHandler().getNetworkManager().getIsencrypted(); + int n; + if (scoreObjectiveIn != null) { + if (scoreObjectiveIn.getRenderType() == IScoreObjectiveCriteria.EnumRenderType.HEARTS) { + n = 90; + } else { + n = j; + } + } else { + n = 0; + } + + int o = Math.min(k * ((bl ? 9 : 0) + i + n + 13), width - 50) / k; + int p = width / 2 - (o * k + (k - 1) * 5) / 2; + int q = 10; + int r = o * k + (k - 1) * 5; + List list2 = null; + List list3 = null; + if (this.header != null) { + list2 = mc.fontRendererObj.listFormattedStringToWidth(this.header.getFormattedText(), width - 50); + + for (String string : list2) { + r = Math.max(r, mc.fontRendererObj.getStringWidth(string)); + } + } + + if (this.footer != null) { + list3 = mc.fontRendererObj.listFormattedStringToWidth(this.footer.getFormattedText(), width - 50); + + for (String string : list3) { + r = Math.max(r, mc.fontRendererObj.getStringWidth(string)); + } + } + + if (list2 != null) { + Gui.drawRect(width / 2 - r / 2 - 1, q - 1, width / 2 + r / 2 + 1, q + list2.size() * mc.fontRendererObj.FONT_HEIGHT, Integer.MIN_VALUE); + + for (String string : list2) { + int s = mc.fontRendererObj.getStringWidth(string); + mc.fontRendererObj.drawStringWithShadow(string, (float) (width / 2 - s / 2), (float) q, -1); + q += mc.fontRendererObj.FONT_HEIGHT; + } + + ++q; + } + + Gui.drawRect(width / 2 - r / 2 - 1, q - 1, width / 2 + r / 2 + 1, q + m * 9, Integer.MIN_VALUE); + + for (int t = 0; t < l; ++t) { + int u = t / m; + int s = t % m; + int v = p + u * o + u * 5; + int w = q + s * 9; + Gui.drawRect(v, w, v + o, w + 8, 553648127); + GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F); + GlStateManager.enableAlpha(); + GlStateManager.enableBlend(); + GlStateManager.tryBlendFuncSeparate(770, 771, 1, 0); + if (t < list.size()) { + NetworkPlayerInfo networkPlayerInfo2 = (NetworkPlayerInfo) list.get(t); + String string2 = this.getPlayerName(networkPlayerInfo2); + GameProfile gameProfile = networkPlayerInfo2.getGameProfile(); + if (bl) { + EntityPlayer entityPlayer = mc.theWorld.getPlayerEntityByUUID(gameProfile.getId()); + boolean bl2 = entityPlayer != null && entityPlayer.isWearing(EnumPlayerModelParts.CAPE) && (gameProfile.getName().equals("Dinnerbone") || gameProfile.getName().equals("Grumm")); + mc.getTextureManager().bindTexture(networkPlayerInfo2.getLocationSkin()); + int x = 8 + (bl2 ? 8 : 0); + int y = 8 * (bl2 ? -1 : 1); + Gui.drawScaledCustomSizeModalRect(v, w, 8.0F, (float) x, 8, y, 8, 8, 64.0F, 64.0F); + if (entityPlayer != null && entityPlayer.isWearing(EnumPlayerModelParts.HAT)) { + int z = 8 + (bl2 ? 8 : 0); + int aa = 8 * (bl2 ? -1 : 1); + Gui.drawScaledCustomSizeModalRect(v, w, 40.0F, (float) z, 8, aa, 8, 8, 64.0F, 64.0F); + } + + v += 9; + } + + ClientUser clientUser = FPSMaster.clientUsersManager.getClientUser(networkPlayerInfo2.getGameProfile().getName(), networkPlayerInfo2.getGameProfile().getId().toString()); + boolean isSelf = networkPlayerInfo2.getGameProfile().getName().equals(mc.thePlayer.getName()) && networkPlayerInfo2.getGameProfile().getId().equals(mc.thePlayer.getUniqueID()); + + int clientOffset = 0; + if (clientUser != null || isSelf) { + Render2DUtils.drawImage(new ResourceLocation("client/textures/mate.png"), v, w, 8, 8, -1, true); + clientOffset = 10; + } + + if (networkPlayerInfo2.getGameType() == WorldSettings.GameType.SPECTATOR) { + string2 = EnumChatFormatting.ITALIC + string2; + mc.fontRendererObj.drawStringWithShadow(string2, (float) v + clientOffset, (float) w, -1862270977); + } else { + mc.fontRendererObj.drawStringWithShadow(string2, (float) v + clientOffset, (float) w, -1); + } + + if (scoreObjectiveIn != null && networkPlayerInfo2.getGameType() != WorldSettings.GameType.SPECTATOR) { + int ab = v + i + 1; + int ac = ab + n; + if (ac - ab > 5) { + this.drawScoreboardValues(scoreObjectiveIn, w, gameProfile.getName(), ab, ac, networkPlayerInfo2); + } + } + + if (TabOverlay.using && TabOverlay.showPing.getValue()) { + int responseTime = networkPlayerInfo2.getResponseTime(); + String text = responseTime + "ms"; + Color color = responseTime < 150 ? Color.GREEN : responseTime < 300 ? Color.YELLOW : Color.RED; + mc.fontRendererObj.drawStringWithShadow(text, o + v - (bl ? 9 : 0) - mc.fontRendererObj.getStringWidth(text), w, color.getRGB()); + } else { + this.drawPing(o, v - (bl ? 9 : 0), w, networkPlayerInfo2); + } + } + } + + if (list3 != null) { + q += m * 9 + 1; + Gui.drawRect(width / 2 - r / 2 - 1, q - 1, width / 2 + r / 2 + 1, q + list3.size() * mc.fontRendererObj.FONT_HEIGHT, Integer.MIN_VALUE); + + for (String string : list3) { + int s = mc.fontRendererObj.getStringWidth(string); + mc.fontRendererObj.drawStringWithShadow(string, (float) (width / 2 - s / 2), (float) q, -1); + q += mc.fontRendererObj.FONT_HEIGHT; + } + } + + } + + } diff --git a/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinRender.java b/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinRender.java index dcc2affa..4625dcef 100644 --- a/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinRender.java +++ b/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinRender.java @@ -15,6 +15,8 @@ import top.fpsmaster.features.impl.utility.LevelTag; import top.fpsmaster.interfaces.ProviderManager; +import static top.fpsmaster.utils.Utility.mc; + @Mixin(Render.class) public abstract class MixinRender { protected MixinRender() { @@ -37,12 +39,10 @@ public void doRender(Entity entity, double x, double y, double z, float entityYa @Inject(method = "renderLivingLabel", at = @At("HEAD"), cancellable = true) protected void renderLivingLabel(Entity entityIn, String str, double x, double y, double z, int maxDistance, CallbackInfo ci) { - if (LevelTag.using) { - if (LevelTag.health.getValue()) - LevelTag.renderHealth(entityIn, str, x, y, z, maxDistance); - LevelTag.renderName(entityIn, str, x, y, z, maxDistance); - ci.cancel(); - } + if (LevelTag.health.getValue()) + LevelTag.renderHealth(entityIn, str, x, y, z, maxDistance); + LevelTag.renderName(entityIn, str, x, y, z, maxDistance); + ci.cancel(); } @Inject(method = "renderName", at = @At("HEAD"), cancellable = true) From 8c2304e4fc024190d6724d0129452d9c12f177cf Mon Sep 17 00:00:00 2001 From: SuperSkidder Date: Sun, 20 Jul 2025 17:07:23 +0800 Subject: [PATCH 153/193] feat: chat switch button --- .../assets/minecraft/client/lang/en_us.lang | 2 + .../assets/minecraft/client/lang/zh_cn.lang | 2 + .../fpsmaster/forge/mixin/MixinGuiChat.java | 55 +++++++++++++++++++ .../src/main/resources/mixins.fpsmaster.json | 1 + 4 files changed, 60 insertions(+) create mode 100644 v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinGuiChat.java diff --git a/shared/resources/assets/minecraft/client/lang/en_us.lang b/shared/resources/assets/minecraft/client/lang/en_us.lang index 20d1e8fc..3e0360c1 100644 --- a/shared/resources/assets/minecraft/client/lang/en_us.lang +++ b/shared/resources/assets/minecraft/client/lang/en_us.lang @@ -521,3 +521,5 @@ command.notfound=Command not found. If the client command affects your chat, dis blur.fast_render=UI blur is not compatible with Fast Render. Please disable Fast Render first. blur.performance=Blur may reduce performance. Disable on low-end PCs! motionblur.fast_render=Motion Blur is not compatible with Fast Render. Fast Render has been disabled. +chat.irc=Client +chat.mc=Vanilla \ No newline at end of file diff --git a/shared/resources/assets/minecraft/client/lang/zh_cn.lang b/shared/resources/assets/minecraft/client/lang/zh_cn.lang index 1f789daa..04c57afc 100644 --- a/shared/resources/assets/minecraft/client/lang/zh_cn.lang +++ b/shared/resources/assets/minecraft/client/lang/zh_cn.lang @@ -526,3 +526,5 @@ command.notfound=未找到命令,如果客户端命令影响了您的消息, blur.fast_render=组件模糊与快速渲染不兼容,如要使用模糊效果,请先在设置中关闭快速渲染。 blur.performance=组件模糊会极大影响性能,若您的配置较低则不建议开启! motionblur.fast_render=快速渲染与运动模糊不兼容,已为您自动关闭快速渲染。 +chat.irc=客户端 +chat.mc=原版 \ No newline at end of file diff --git a/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinGuiChat.java b/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinGuiChat.java new file mode 100644 index 00000000..1a3e26b2 --- /dev/null +++ b/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinGuiChat.java @@ -0,0 +1,55 @@ +package top.fpsmaster.forge.mixin; + +import net.minecraft.client.gui.Gui; +import net.minecraft.client.gui.GuiChat; +import net.minecraft.client.gui.GuiScreen; +import org.lwjgl.input.Mouse; +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; +import top.fpsmaster.FPSMaster; +import top.fpsmaster.utils.render.Render2DUtils; + +import java.awt.*; + +@Mixin(GuiChat.class) +public class MixinGuiChat extends GuiScreen { + + @Unique + private static boolean irc = false; + + + @Inject(method = "drawScreen", at = @At("HEAD")) + public void drawScreen(int mouseX, int mouseY, float partialTicks, CallbackInfo ci) { + int width1 = mc.fontRendererObj.getStringWidth(FPSMaster.i18n.get("chat.mc")); + int width2 = mc.fontRendererObj.getStringWidth(FPSMaster.i18n.get("chat.irc")); + + + Gui.drawRect(2, this.height - 28, 2 + width1 + 4, this.height - 14, irc ? new Color(0, 0, 0, 180).getRGB() : new Color(80, 80, 80, 180).getRGB()); + mc.fontRendererObj.drawStringWithShadow(FPSMaster.i18n.get("chat.mc"), 4, this.height - 28, irc ? new Color(200, 200, 200).getRGB() : -1); + + Gui.drawRect(2 + width1 + 8, this.height - 28, 2 + width1 + 6 + width2 + 6, this.height - 14, irc ? new Color(80, 80, 80, 180).getRGB() : new Color(0, 0, 0, 180).getRGB()); + mc.fontRendererObj.drawStringWithShadow(FPSMaster.i18n.get("chat.irc"), 4 + width1 + 8, this.height - 28, irc ? -1 : new Color(200, 200, 200).getRGB()); + + if (Mouse.isButtonDown(0)) { + if (Render2DUtils.isHovered(2, this.height - 28, width1 + 4, 12, mouseX, mouseY)) { + irc = false; + } else if (Render2DUtils.isHovered(2 + width1 + 8, this.height - 28, width1 + 6 + width2 + 4, 12, mouseX, mouseY)) { + irc = true; + } + } + } + + + @Redirect(method = "keyTyped", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/GuiChat;sendChatMessage(Ljava/lang/String;)V")) + public void sendChatMessage(GuiChat instance, String message) { + if (irc) { + FPSMaster.INSTANCE.wsClient.sendMessage(message); + } else { + instance.sendChatMessage(message); + } + } +} diff --git a/v1.8.9/src/main/resources/mixins.fpsmaster.json b/v1.8.9/src/main/resources/mixins.fpsmaster.json index 1c9f6c75..52021163 100644 --- a/v1.8.9/src/main/resources/mixins.fpsmaster.json +++ b/v1.8.9/src/main/resources/mixins.fpsmaster.json @@ -22,6 +22,7 @@ "MixinEntityPlayerSP", "MixinEntityRenderer", "MixinFontRender", + "MixinGuiChat", "MixinGuiContainer", "MixinGuiIngame", "MixinGuiIngameForge", From e1baa0d776e072702ef445c01781ab1806e58c0d Mon Sep 17 00:00:00 2001 From: SuperSkidder Date: Sun, 20 Jul 2025 17:10:06 +0800 Subject: [PATCH 154/193] change: chat switch button --- .../main/java/top/fpsmaster/forge/mixin/MixinGuiChat.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinGuiChat.java b/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinGuiChat.java index 1a3e26b2..a1c91523 100644 --- a/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinGuiChat.java +++ b/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinGuiChat.java @@ -29,15 +29,15 @@ public void drawScreen(int mouseX, int mouseY, float partialTicks, CallbackInfo Gui.drawRect(2, this.height - 28, 2 + width1 + 4, this.height - 14, irc ? new Color(0, 0, 0, 180).getRGB() : new Color(80, 80, 80, 180).getRGB()); - mc.fontRendererObj.drawStringWithShadow(FPSMaster.i18n.get("chat.mc"), 4, this.height - 28, irc ? new Color(200, 200, 200).getRGB() : -1); + mc.fontRendererObj.drawStringWithShadow(FPSMaster.i18n.get("chat.mc"), 4, this.height - 26, irc ? new Color(200, 200, 200).getRGB() : -1); - Gui.drawRect(2 + width1 + 8, this.height - 28, 2 + width1 + 6 + width2 + 6, this.height - 14, irc ? new Color(80, 80, 80, 180).getRGB() : new Color(0, 0, 0, 180).getRGB()); - mc.fontRendererObj.drawStringWithShadow(FPSMaster.i18n.get("chat.irc"), 4 + width1 + 8, this.height - 28, irc ? -1 : new Color(200, 200, 200).getRGB()); + Gui.drawRect(2 + width1 + 4, this.height - 28, 2 + width1 + 6 + width2 + 2, this.height - 14, irc ? new Color(80, 80, 80, 180).getRGB() : new Color(0, 0, 0, 180).getRGB()); + mc.fontRendererObj.drawStringWithShadow(FPSMaster.i18n.get("chat.irc"), 4 + width1 + 4, this.height - 26, irc ? -1 : new Color(200, 200, 200).getRGB()); if (Mouse.isButtonDown(0)) { if (Render2DUtils.isHovered(2, this.height - 28, width1 + 4, 12, mouseX, mouseY)) { irc = false; - } else if (Render2DUtils.isHovered(2 + width1 + 8, this.height - 28, width1 + 6 + width2 + 4, 12, mouseX, mouseY)) { + } else if (Render2DUtils.isHovered(2 + width1 + 4, this.height - 28, width2 + 2, 12, mouseX, mouseY)) { irc = true; } } From 88adc4baa0673a1163e09de2e467856da0379b06 Mon Sep 17 00:00:00 2001 From: SuperSkidder Date: Sun, 20 Jul 2025 17:16:53 +0800 Subject: [PATCH 155/193] feat: recommended songs loading wouldn't stuck game now --- shared/java/top/fpsmaster/ui/click/music/MusicPanel.java | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/shared/java/top/fpsmaster/ui/click/music/MusicPanel.java b/shared/java/top/fpsmaster/ui/click/music/MusicPanel.java index 9155736d..fbe28250 100644 --- a/shared/java/top/fpsmaster/ui/click/music/MusicPanel.java +++ b/shared/java/top/fpsmaster/ui/click/music/MusicPanel.java @@ -83,10 +83,13 @@ public static void mouseClicked(int mouseX, int mouseY, int btn) { if (Mouse.isButtonDown(0)) { curSearch = i; if (curSearch == 2) { - recommendList = MusicWrapper.getSongsFromDaily(); - displayList = recommendList; MusicPlayer.playList.pause(); - setMusicList(); + searchThread = new Thread(() -> { + recommendList = MusicWrapper.getSongsFromDaily(); + displayList = recommendList; + setMusicList(); + }); + searchThread.start(); } } } From 09e9ea685ee98e0a4224fc8f0a1f3a0ec9ecf1f6 Mon Sep 17 00:00:00 2001 From: SuperSkidder Date: Sun, 20 Jul 2025 17:25:04 +0800 Subject: [PATCH 156/193] misc: add missing lang fix a render bug --- shared/java/top/fpsmaster/utils/render/Render2DUtils.java | 1 + shared/resources/assets/minecraft/client/lang/en_us.lang | 2 ++ shared/resources/assets/minecraft/client/lang/zh_cn.lang | 1 + 3 files changed, 4 insertions(+) diff --git a/shared/java/top/fpsmaster/utils/render/Render2DUtils.java b/shared/java/top/fpsmaster/utils/render/Render2DUtils.java index 844f3e0f..4bd4c3ba 100644 --- a/shared/java/top/fpsmaster/utils/render/Render2DUtils.java +++ b/shared/java/top/fpsmaster/utils/render/Render2DUtils.java @@ -126,6 +126,7 @@ public static int limit(double i) { public static void drawRect(float x, float y, float width, float height, int color) { GlStateManager.enableBlend(); GlStateManager.disableTexture2D(); + GlStateManager.enableAlpha(); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glEnable(GL_LINE_SMOOTH); glColor(color); diff --git a/shared/resources/assets/minecraft/client/lang/en_us.lang b/shared/resources/assets/minecraft/client/lang/en_us.lang index 3e0360c1..a23f5441 100644 --- a/shared/resources/assets/minecraft/client/lang/en_us.lang +++ b/shared/resources/assets/minecraft/client/lang/en_us.lang @@ -231,6 +231,8 @@ musicdisplay.roundradius=Corner Radius musicdisplay.round=Rounded Corners musicdisplay.betterfont=Clean Font musicdisplay.background=Show Background +musicdisplay.fontshadow=Font Shadow + oldanimations=Old Animations oldanimations.desc=Revert to old 1.7 animations diff --git a/shared/resources/assets/minecraft/client/lang/zh_cn.lang b/shared/resources/assets/minecraft/client/lang/zh_cn.lang index 04c57afc..f60f3c8c 100644 --- a/shared/resources/assets/minecraft/client/lang/zh_cn.lang +++ b/shared/resources/assets/minecraft/client/lang/zh_cn.lang @@ -233,6 +233,7 @@ musicdisplay.roundradius=圆角半径 musicdisplay.round=圆角 musicdisplay.betterfont=更好的字体 musicdisplay.background=背景 +musicdisplay.fontshadow=字体阴影 oldanimations=旧动画 oldanimations.desc=旧动画 From 14de044f130b00d68787fb63c246d28f19d96a83 Mon Sep 17 00:00:00 2001 From: SuperSkidder Date: Sun, 20 Jul 2025 17:45:16 +0800 Subject: [PATCH 157/193] fix: add via support --- .../top/fpsmaster/utils/render/ScaledGuiScreen.java | 4 +--- .../top/fpsmaster/forge/mixin/MixinGuiMultiplayer.java | 10 +++++++++- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/shared/java/top/fpsmaster/utils/render/ScaledGuiScreen.java b/shared/java/top/fpsmaster/utils/render/ScaledGuiScreen.java index 1dccd16b..0830a054 100644 --- a/shared/java/top/fpsmaster/utils/render/ScaledGuiScreen.java +++ b/shared/java/top/fpsmaster/utils/render/ScaledGuiScreen.java @@ -41,10 +41,8 @@ public void initGui() { } @Override - protected void mouseClicked(int mouseX, int mouseY, int mouseButton) throws IOException { + public void mouseClicked(int mouseX, int mouseY, int mouseButton) throws IOException { super.mouseClicked(mouseX, mouseY, mouseButton); - ScaledResolution sr = new ScaledResolution(mc); - int realMouseX = mouseX * scaleFactor / 2; int realMouseY = mouseY * scaleFactor / 2; onClick(realMouseX, realMouseY, mouseButton); diff --git a/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinGuiMultiplayer.java b/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinGuiMultiplayer.java index ce4f0c9f..26f70770 100644 --- a/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinGuiMultiplayer.java +++ b/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinGuiMultiplayer.java @@ -6,11 +6,19 @@ import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import top.fpsmaster.ui.screens.mainmenu.MainMenu; @Mixin(GuiMultiplayer.class) public class MixinGuiMultiplayer { @Inject(method = "initGui", at = @At("HEAD")) public void initGui(CallbackInfo ci) { - Minecraft.getMinecraft().displayGuiScreen(new top.fpsmaster.ui.mc.GuiMultiplayer()); + // check ViaVersion + try { + Class.forName("com.viaversion.viaversion.api.Via"); + Minecraft.getMinecraft().displayGuiScreen(new GuiMultiplayer(new MainMenu())); + } catch (ClassNotFoundException e) { + Minecraft.getMinecraft().displayGuiScreen(new top.fpsmaster.ui.mc.GuiMultiplayer()); + ci.cancel(); + } } } From 79ace073e15b475127270381287e7cf56f9d701f Mon Sep 17 00:00:00 2001 From: SuperSkidder Date: Sun, 20 Jul 2025 17:45:39 +0800 Subject: [PATCH 158/193] fix: a stupid issue --- .../java/top/fpsmaster/forge/mixin/MixinGuiMultiplayer.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinGuiMultiplayer.java b/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinGuiMultiplayer.java index 26f70770..2034ea5e 100644 --- a/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinGuiMultiplayer.java +++ b/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinGuiMultiplayer.java @@ -10,7 +10,7 @@ @Mixin(GuiMultiplayer.class) public class MixinGuiMultiplayer { - @Inject(method = "initGui", at = @At("HEAD")) + @Inject(method = "initGui", at = @At("HEAD"), cancellable = true) public void initGui(CallbackInfo ci) { // check ViaVersion try { From 76759036f734755c625e50597b176b1ddc1ff0b5 Mon Sep 17 00:00:00 2001 From: vlouboos Date: Sun, 20 Jul 2025 19:59:42 +0800 Subject: [PATCH 159/193] Wavy Cape --- .../features/impl/optimizes/WavyCape.java | 10 + .../features/manager/ModuleManager.java | 1 + .../top/fpsmaster/utils/render/PoseStack.java | 166 ++++++++++ .../assets/minecraft/client/lang/en_us.lang | 3 + .../assets/minecraft/client/lang/zh_cn.lang | 3 + .../client/textures/modules/wavycape.png | Bin 0 -> 307 bytes .../fpsmaster/forge/mixin/MixinLayerCape.java | 310 ++++++++++++++++++ .../forge/mixin/MixinSplashScreen.java | 3 +- .../src/main/resources/mixins.fpsmaster.json | 1 + 9 files changed, 495 insertions(+), 2 deletions(-) create mode 100644 shared/java/top/fpsmaster/features/impl/optimizes/WavyCape.java create mode 100644 shared/java/top/fpsmaster/utils/render/PoseStack.java create mode 100644 shared/resources/assets/minecraft/client/textures/modules/wavycape.png create mode 100644 v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinLayerCape.java diff --git a/shared/java/top/fpsmaster/features/impl/optimizes/WavyCape.java b/shared/java/top/fpsmaster/features/impl/optimizes/WavyCape.java new file mode 100644 index 00000000..662a86e6 --- /dev/null +++ b/shared/java/top/fpsmaster/features/impl/optimizes/WavyCape.java @@ -0,0 +1,10 @@ +package top.fpsmaster.features.impl.optimizes; + +import top.fpsmaster.features.manager.Category; +import top.fpsmaster.features.manager.Module; + +public class WavyCape extends Module { + public WavyCape() { + super("WavyCape", Category.OPTIMIZE); + } +} diff --git a/shared/java/top/fpsmaster/features/manager/ModuleManager.java b/shared/java/top/fpsmaster/features/manager/ModuleManager.java index a2d27dc0..f774e916 100644 --- a/shared/java/top/fpsmaster/features/manager/ModuleManager.java +++ b/shared/java/top/fpsmaster/features/manager/ModuleManager.java @@ -76,6 +76,7 @@ public void init() { modules.add(new Performance()); modules.add(new MotionBlur()); modules.add(new SmoothZoom()); + modules.add(new WavyCape()); modules.add(new FullBright()); modules.add(new ItemPhysics()); modules.add(new MinimizedBobbing()); diff --git a/shared/java/top/fpsmaster/utils/render/PoseStack.java b/shared/java/top/fpsmaster/utils/render/PoseStack.java new file mode 100644 index 00000000..a084e300 --- /dev/null +++ b/shared/java/top/fpsmaster/utils/render/PoseStack.java @@ -0,0 +1,166 @@ +package top.fpsmaster.utils.render; + +import java.util.Deque; + +import com.google.common.collect.Queues; +import org.lwjgl.util.vector.Quaternion; + +import javax.vecmath.Matrix3f; +import javax.vecmath.Matrix4f; + +public class PoseStack { + private final Deque poseStack; + + public PoseStack() { + this.poseStack = Queues.newArrayDeque(); + Matrix4f poseMatrix = new Matrix4f(); + poseMatrix.setIdentity(); + Matrix3f normalMatrix = new Matrix3f(); + normalMatrix.setIdentity(); + poseStack.addLast(new Pose(poseMatrix, normalMatrix)); + } + + public void translate(double x, double y, double z) { + Pose pose = poseStack.getLast(); + multiplyWithTranslation(pose.pose, (float) x, (float) y, (float) z); + } + + public void multiplyWithTranslation(Matrix4f matrix, float x, float y, float z) { + matrix.m03 += matrix.m00 * x + matrix.m01 * y + matrix.m02 * z; + matrix.m13 += matrix.m10 * x + matrix.m11 * y + matrix.m12 * z; + matrix.m23 += matrix.m20 * x + matrix.m21 * y + matrix.m22 * z; + matrix.m33 = matrix.m30 * x + matrix.m31 * y + matrix.m32 * z + matrix.m33; + } + + public void scale(float x, float y, float z) { + Pose pose = poseStack.getLast(); + pose.pose.mul(createScaleMatrix4f(x, y, z)); + + if (x == y && y == z) { + if (x > 0.0F) return; + pose.normal.mul(-1.0F); // Uniform negative scale + } + + float invX = 1.0F / x; + float invY = 1.0F / y; + float invZ = 1.0F / z; + float invDet = fastInvCubeRoot(invX * invY * invZ); + pose.normal.mul(createScaleMatrix3f(invDet * invX, invDet * invY, invDet * invZ)); + } + + private Matrix3f createScaleMatrix3f(float x, float y, float z) { + Matrix3f mat = new Matrix3f(); + mat.setIdentity(); + mat.m00 = x; + mat.m11 = y; + mat.m22 = z; + return mat; + } + + private Matrix4f createScaleMatrix4f(float x, float y, float z) { + Matrix4f mat = new Matrix4f(); + mat.setIdentity(); + mat.m00 = x; + mat.m11 = y; + mat.m22 = z; + mat.m33 = 1.0F; + return mat; + } + + public static float fastInvCubeRoot(float value) { + int i = Float.floatToIntBits(value); + i = 1419967116 - i / 3; + float approx = Float.intBitsToFloat(i); + approx = 0.6666667F * approx + (1.0F / 3.0F) * approx * approx * value; + approx = 0.6666667F * approx + (1.0F / 3.0F) * approx * approx * value; + return approx; + } + + public void mulPose(Quaternion quaternion) { + Pose pose = poseStack.getLast(); + pose.pose.mul(fromQuaternion4f(quaternion)); + pose.normal.mul(fromQuaternion3f(quaternion)); + } + + public void pushPose() { + Pose current = poseStack.getLast(); + poseStack.addLast(new Pose(new Matrix4f(current.pose), new Matrix3f(current.normal))); + } + + public void popPose() { + if (poseStack.size() <= 1) + throw new IllegalStateException("Cannot pop the root pose"); + poseStack.removeLast(); + } + + public Pose last() { + return poseStack.getLast(); + } + + public boolean clear() { + return poseStack.size() == 1; + } + + public Matrix4f fromQuaternion4f(Quaternion q) { + float[][] m = rotationMatrixFromQuaternion(q); + Matrix4f mat = new Matrix4f(); + mat.setIdentity(); + mat.m00 = m[0][0]; mat.m01 = m[0][1]; mat.m02 = m[0][2]; + mat.m10 = m[1][0]; mat.m11 = m[1][1]; mat.m12 = m[1][2]; + mat.m20 = m[2][0]; mat.m21 = m[2][1]; mat.m22 = m[2][2]; + return mat; + } + + public Matrix3f fromQuaternion3f(Quaternion q) { + float[][] m = rotationMatrixFromQuaternion(q); + Matrix3f mat = new Matrix3f(); + mat.setIdentity(); + mat.m00 = m[0][0]; mat.m01 = m[0][1]; mat.m02 = m[0][2]; + mat.m10 = m[1][0]; mat.m11 = m[1][1]; mat.m12 = m[1][2]; + mat.m20 = m[2][0]; mat.m21 = m[2][1]; mat.m22 = m[2][2]; + return mat; + } + + + private float[][] rotationMatrixFromQuaternion(Quaternion q) { + float x = q.x, y = q.y, z = q.z, w = q.w; + + float xx = 2.0F * x * x; + float yy = 2.0F * y * y; + float zz = 2.0F * z * z; + + float xy = x * y; + float yz = y * z; + float zx = z * x; + float xw = x * w; + float yw = y * w; + float zw = z * w; + + float[][] m = new float[3][3]; + m[0][0] = 1.0F - yy - zz; + m[1][1] = 1.0F - zz - xx; + m[2][2] = 1.0F - xx - yy; + + m[1][0] = 2.0F * (xy + zw); + m[0][1] = 2.0F * (xy - zw); + + m[2][0] = 2.0F * (zx - yw); + m[0][2] = 2.0F * (zx + yw); + + m[2][1] = 2.0F * (yz + xw); + m[1][2] = 2.0F * (yz - xw); + + return m; + } + + + public static final class Pose { + public final Matrix4f pose; + public final Matrix3f normal; + + Pose(Matrix4f pose, Matrix3f normal) { + this.pose = pose; + this.normal = normal; + } + } +} diff --git a/shared/resources/assets/minecraft/client/lang/en_us.lang b/shared/resources/assets/minecraft/client/lang/en_us.lang index a23f5441..30e4432d 100644 --- a/shared/resources/assets/minecraft/client/lang/en_us.lang +++ b/shared/resources/assets/minecraft/client/lang/en_us.lang @@ -497,6 +497,9 @@ customtitles.x=xOffset customtitles.y=yOffset customtitles.scale=Scale +wavycape=Wavy Cape +wavycape.desc=Make your cape natural if exists + # Categories category.optimize=Performance category.render=Visual diff --git a/shared/resources/assets/minecraft/client/lang/zh_cn.lang b/shared/resources/assets/minecraft/client/lang/zh_cn.lang index f60f3c8c..7dfa2119 100644 --- a/shared/resources/assets/minecraft/client/lang/zh_cn.lang +++ b/shared/resources/assets/minecraft/client/lang/zh_cn.lang @@ -501,6 +501,9 @@ customtitles.x=横坐标偏移 customtitles.y=纵坐标偏移 customtitles.scale=缩放 +wavycape=披风飘动 +wavycape.desc=使你的披风随着移动飘动 + # 类别 category.optimize=优化 category.render=视觉 diff --git a/shared/resources/assets/minecraft/client/textures/modules/wavycape.png b/shared/resources/assets/minecraft/client/textures/modules/wavycape.png new file mode 100644 index 0000000000000000000000000000000000000000..fe91986aec274ed6a7a8871eb10c8cd870887d61 GIT binary patch literal 307 zcmeAS@N?(olHy`uVBq!ia0vp^G9b*s1|*Ak?@s|zjKx9jP7LeL$-D$|Sc;uILpXq- zh9ji|$iM69;uzx5x%aB0;9&)kmc$@dkB%0vP8O9Tj!P643TZ7AnlQoYM>WUXhZBS% zG^)?nd`^%zTxQU~%=Ex(|4Kds^?+IXGFtv{UJ++~C#ZGy7S}ViUsKnzmN4Du`L$5P zJ@HURiReMKkhwxrz7@%=og{9sIyjFhLsh3~+ONe|!&MfY$~(7q#d?6ZwDnwa+hpX~!1z-N13Z)bAH< zt_I&1Y`4vnEV16H|6N?i(fRxDT@2GJ;(x8r2(i1$c&6aj1^0_Uk1}|=`njxgN@xNA DFtK>; literal 0 HcmV?d00001 diff --git a/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinLayerCape.java b/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinLayerCape.java new file mode 100644 index 00000000..0bd3bc85 --- /dev/null +++ b/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinLayerCape.java @@ -0,0 +1,310 @@ +package top.fpsmaster.forge.mixin; + +import net.minecraft.client.entity.AbstractClientPlayer; +import net.minecraft.client.renderer.Tessellator; +import net.minecraft.client.renderer.WorldRenderer; +import net.minecraft.client.renderer.entity.RenderPlayer; +import net.minecraft.client.renderer.entity.layers.LayerCape; +import net.minecraft.client.renderer.entity.layers.LayerRenderer; +import net.minecraft.client.renderer.vertex.DefaultVertexFormats; +import net.minecraft.entity.player.EnumPlayerModelParts; +import net.minecraft.util.MathHelper; +import org.lwjgl.util.vector.Quaternion; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +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.callback.CallbackInfo; +import top.fpsmaster.FPSMaster; +import top.fpsmaster.features.impl.optimizes.WavyCape; +import top.fpsmaster.utils.render.PoseStack; + +import javax.vecmath.Matrix4f; +import javax.vecmath.Vector4f; + +@Mixin(LayerCape.class) +public abstract class MixinLayerCape implements LayerRenderer { + @Shadow + @Final + private RenderPlayer playerRenderer; + + + @Inject(method = "doRenderLayer(Lnet/minecraft/client/entity/AbstractClientPlayer;FFFFFFF)V", at = @At("HEAD"), cancellable = true) + public void renderLayer(AbstractClientPlayer player, float f, float g, float partialTicks, float h, float i, float j, float scale, CallbackInfo ci) { + if (FPSMaster.moduleManager.getModule(WavyCape.class).isEnabled()) { + if (player.isInvisible()) return; + + if (!player.hasPlayerInfo() || player.isInvisible() || !player.isWearing(EnumPlayerModelParts.CAPE) || player.getLocationCape() == null) { + return; + } + this.playerRenderer.bindTexture(player.getLocationCape()); + v1_8_9$renderSmoothCape(player, partialTicks); + ci.cancel(); + } + } + + @Unique + public void v1_8_9$renderSmoothCape(AbstractClientPlayer abstractClientPlayer, float delta) { + WorldRenderer worldrenderer = Tessellator.getInstance().getWorldRenderer(); + worldrenderer.begin(7, DefaultVertexFormats.POSITION_TEX_NORMAL); + PoseStack poseStack = new PoseStack(); + poseStack.pushPose(); + + Matrix4f oldPositionMatrix = null; + for (int part = 0; part < 16; part++) { + v1_8_9$modifyPoseStack(poseStack, abstractClientPlayer, delta, part); + + if (oldPositionMatrix == null) { + oldPositionMatrix = poseStack.last().pose; + } + + if (part == 0) { + v1_8_9$addTopVertex(worldrenderer, poseStack.last().pose, oldPositionMatrix, part); + } else if (part == 15) { + v1_8_9$addBottomVertex(worldrenderer, poseStack.last().pose, poseStack.last().pose, (part + 1) * (0.96F / 16), (part + 1) * (0.96F / 16), part); + } + + v1_8_9$addLeftVertex(worldrenderer, poseStack.last().pose, oldPositionMatrix, (part + 1) * (0.96F / 16), part * (0.96F / 16), part); + v1_8_9$addRightVertex(worldrenderer, poseStack.last().pose, oldPositionMatrix, (part + 1) * (0.96F / 16), part * (0.96F / 16), part); + v1_8_9$addBackVertex(worldrenderer, poseStack.last().pose, oldPositionMatrix, (part + 1) * (0.96F / 16), part * (0.96F / 16), part); + v1_8_9$addFrontVertex(worldrenderer, oldPositionMatrix, poseStack.last().pose, (part + 1) * (0.96F / 16), part * (0.96F / 16), part); + oldPositionMatrix = poseStack.last().pose; + poseStack.popPose(); + } + Tessellator.getInstance().draw(); + } + + @Unique + private void v1_8_9$modifyPoseStack(PoseStack poseStack, AbstractClientPlayer abstractClientPlayer, float h, int part) { + poseStack.pushPose(); + poseStack.translate(0.0D, 0.0D, 0.125D); + double d = v1_8_9$lerp(h, abstractClientPlayer.prevChasingPosX, abstractClientPlayer.chasingPosX) + - v1_8_9$lerp(h, abstractClientPlayer.prevPosX, abstractClientPlayer.posX); + double e = v1_8_9$lerp(h, abstractClientPlayer.prevChasingPosY, abstractClientPlayer.chasingPosY) + - v1_8_9$lerp(h, abstractClientPlayer.prevPosY, abstractClientPlayer.posY); + double m = v1_8_9$lerp(h, abstractClientPlayer.prevChasingPosZ, abstractClientPlayer.chasingPosZ) + - v1_8_9$lerp(h, abstractClientPlayer.prevPosZ, abstractClientPlayer.posZ); + float n = abstractClientPlayer.prevRenderYawOffset + abstractClientPlayer.renderYawOffset - abstractClientPlayer.prevRenderYawOffset; + double o = Math.sin(n * 0.017453292F); + double p = -Math.cos(n * 0.017453292F); + float height = (float) e * 10.0F; + height = MathHelper.clamp_float(height, -6.0F, 32.0F); + float swing = (float) (d * o + m * p) * v1_8_9$easeOutSine(1.0F / 16 * part) * 100; + swing = MathHelper.clamp_float(swing, 0.0F, 150.0F * v1_8_9$easeOutSine(1F / 16 * part)); + float sidewaysRotationOffset = (float) (d * p - m * o) * 100.0F; + sidewaysRotationOffset = MathHelper.clamp_float(sidewaysRotationOffset, -20.0F, 20.0F); + float t = v1_8_9$lerp(h, abstractClientPlayer.prevCameraYaw, abstractClientPlayer.cameraYaw); + height += (float) (Math.sin(v1_8_9$lerp(h, abstractClientPlayer.prevDistanceWalkedModified, abstractClientPlayer.distanceWalkedModified) * 6.0F) * 32.0F * t); + if (abstractClientPlayer.isSneaking()) { + height += 25.0F; + poseStack.translate(0, 0.15F, 0); + } + + poseStack.mulPose(v1_8_9$fromDegree(1.0F, 0.0F, 0.0F, 6.0F + swing / 2.0F + height)); + poseStack.mulPose(v1_8_9$fromDegree(0.0F, 0.0F, 1.0F, sidewaysRotationOffset / 2.0F)); + poseStack.mulPose(v1_8_9$fromDegree(0.0F, 1.0F, 0.0F, 180.0F - sidewaysRotationOffset / 2.0F)); + } + + @Unique + private float v1_8_9$easeOutSine(float x) { + return (float) Math.sin((x * Math.PI) / 2); + } + + @Unique + private Quaternion v1_8_9$fromDegree(float x, float y, float z, float degree) { + Quaternion quaternion = new Quaternion(); + degree *= 0.017453292F; + float g = (float) Math.sin(degree / 2.0F); + quaternion.x = x * g; + quaternion.y = y * g; + quaternion.z = z * g; + quaternion.w = (float) Math.cos(degree / 2.0F); + return quaternion; + } + + @Unique + private float v1_8_9$lerp(float f, float g, float h) { + return g + f * (h - g); + } + + @Unique + private double v1_8_9$lerp(double d, double e, double f) { + return e + d * (f - e); + } + + @Unique + private void v1_8_9$addBackVertex(WorldRenderer worldrenderer, Matrix4f matrix, Matrix4f oldMatrix, float y1, float y2, int part) { + float i; + Matrix4f k; + if (y1 < y2) { + i = y1; + y1 = y2; + y2 = i; + + k = matrix; + matrix = oldMatrix; + oldMatrix = k; + } + + float minU = .015625F; + float maxU = .171875F; + + float minV = .03125F; + float maxV = .53125F; + + float deltaV = maxV - minV; + float vPerPart = deltaV / 16; + maxV = minV + (vPerPart * (part + 1)); + minV = minV + (vPerPart * part); + + v1_8_9$vertex(worldrenderer, oldMatrix, (float) 0.3, y2, (float) -0.06).tex(maxU, minV).normal(1, 0, 0).endVertex(); + v1_8_9$vertex(worldrenderer, oldMatrix, (float) -0.3, y2, (float) -0.06).tex(minU, minV).normal(1, 0, 0).endVertex(); + v1_8_9$vertex(worldrenderer, matrix, (float) -0.3, y1, (float) -0.06).tex(minU, maxV).normal(1, 0, 0).endVertex(); + v1_8_9$vertex(worldrenderer, matrix, (float) 0.3, y1, (float) -0.06).tex(maxU, maxV).normal(1, 0, 0).endVertex(); + + } + + @Unique + private void v1_8_9$addFrontVertex(WorldRenderer worldrenderer, Matrix4f matrix, Matrix4f oldMatrix, float y1, float y2, int part) { + float i; + Matrix4f k; + + if (y1 < y2) { + i = y1; + y1 = y2; + y2 = i; + + k = matrix; + matrix = oldMatrix; + oldMatrix = k; + } + + float minU = .1875F; + float maxU = .34375F; + + float minV = .03125F; + float maxV = .53125F; + + float deltaV = maxV - minV; + float vPerPart = deltaV / 16; + maxV = minV + (vPerPart * (part + 1)); + minV = minV + (vPerPart * part); + + v1_8_9$vertex(worldrenderer, oldMatrix, (float) 0.3, y1, (float) 0.0).tex(maxU, maxV).normal(1, 0, 0).endVertex(); + v1_8_9$vertex(worldrenderer, oldMatrix, (float) -0.3, y1, (float) 0.0).tex(minU, maxV).normal(1, 0, 0).endVertex(); + v1_8_9$vertex(worldrenderer, matrix, (float) -0.3, y2, (float) 0.0).tex(minU, minV).normal(1, 0, 0).endVertex(); + v1_8_9$vertex(worldrenderer, matrix, (float) 0.3, y2, (float) 0.0).tex(maxU, minV).normal(1, 0, 0).endVertex(); + + } + + @Unique + private void v1_8_9$addLeftVertex(WorldRenderer worldrenderer, Matrix4f matrix, Matrix4f oldMatrix, float y1, float y2, int part) { + float i; + if (y1 < y2) { + i = y1; + y1 = y2; + y2 = i; + } + + float minU = 0; + float maxU = .015625F; + + float minV = .03125F; + float maxV = .53125F; + + float deltaV = maxV - minV; + float vPerPart = deltaV / 16; + maxV = minV + (vPerPart * (part + 1)); + minV = minV + (vPerPart * part); + + v1_8_9$vertex(worldrenderer, oldMatrix, (float) -0.3, y2, (float) -0.06).tex(minU, minV).normal(1, 0, 0).endVertex(); + v1_8_9$vertex(worldrenderer, oldMatrix, (float) -0.3, y2, (float) 0.0).tex(maxU, minV).normal(1, 0, 0).endVertex(); + v1_8_9$vertex(worldrenderer, matrix, (float) -0.3, y1, (float) 0.0).tex(maxU, maxV).normal(1, 0, 0).endVertex(); + v1_8_9$vertex(worldrenderer, matrix, (float) -0.3, y1, (float) -0.06).tex(minU, maxV).normal(1, 0, 0).endVertex(); + + } + + @Unique + private void v1_8_9$addRightVertex(WorldRenderer worldrenderer, Matrix4f matrix, Matrix4f oldMatrix, float y1, float y2, int part) { + float i; + + if (y1 < y2) { + i = y1; + y1 = y2; + y2 = i; + } + + float minU = .171875F; + float maxU = .1875F; + + float minV = .03125F; + float maxV = .53125F; + + float deltaV = maxV - minV; + float vPerPart = deltaV / 16; + maxV = minV + (vPerPart * (part + 1)); + minV = minV + (vPerPart * part); + + v1_8_9$vertex(worldrenderer, oldMatrix, (float) 0.3, y2, (float) 0.0).tex(maxU, minV).normal(1, 0, 0).endVertex(); + v1_8_9$vertex(worldrenderer, oldMatrix, (float) 0.3, y2, (float) -0.06).tex(minU, minV).normal(1, 0, 0).endVertex(); + v1_8_9$vertex(worldrenderer, matrix, (float) 0.3, y1, (float) -0.06).tex(minU, maxV).normal(1, 0, 0).endVertex(); + v1_8_9$vertex(worldrenderer, matrix, (float) 0.3, y1, (float) 0.0).tex(maxU, maxV).normal(1, 0, 0).endVertex(); + + } + + @Unique + private void v1_8_9$addBottomVertex(WorldRenderer worldrenderer, Matrix4f matrix, Matrix4f oldMatrix, float y1, float y2, int part) { + float i; + if (y1 < y2) { + i = y1; + y1 = y2; + y2 = i; + } + + float minU = .171875F; + float maxU = .328125F; + + float minV = 0; + float maxV = .03125F; + + float deltaV = maxV - minV; + float vPerPart = deltaV / 16; + maxV = minV + (vPerPart * (part + 1)); + minV = minV + (vPerPart * part); + + v1_8_9$vertex(worldrenderer, oldMatrix, (float) 0.3, y2, (float) -0.06).tex(maxU, minV).normal(1, 0, 0).endVertex(); + v1_8_9$vertex(worldrenderer, oldMatrix, (float) -0.3, y2, (float) -0.06).tex(minU, minV).normal(1, 0, 0).endVertex(); + v1_8_9$vertex(worldrenderer, matrix, (float) -0.3, y1, (float) 0.0).tex(minU, maxV).normal(1, 0, 0).endVertex(); + v1_8_9$vertex(worldrenderer, matrix, (float) 0.3, y1, (float) 0.0).tex(maxU, maxV).normal(1, 0, 0).endVertex(); + + } + + @Unique + private WorldRenderer v1_8_9$vertex(WorldRenderer worldrenderer, Matrix4f matrix4f, float f, float g, float h) { + Vector4f vector4f = new Vector4f(f, g, h, 1.0F); + matrix4f.transform(vector4f); + worldrenderer.pos(vector4f.x, vector4f.y, vector4f.z); + return worldrenderer; + } + + @Unique + private void v1_8_9$addTopVertex(WorldRenderer worldrenderer, Matrix4f matrix, Matrix4f oldMatrix, int part) { + float minU = .015625F; + float maxU = .171875F; + + float minV = 0; + float maxV = .03125F; + + float deltaV = maxV - minV; + float vPerPart = deltaV / 16; + maxV = minV + (vPerPart * (part + 1)); + minV = minV + (vPerPart * part); + + v1_8_9$vertex(worldrenderer, oldMatrix, (float) 0.3, (float) 0, (float) 0.0).tex(maxU, maxV).normal(0, 1, 0).endVertex(); + v1_8_9$vertex(worldrenderer, oldMatrix, (float) -0.3, (float) 0, (float) 0.0).tex(minU, maxV).normal(0, 1, 0).endVertex(); + v1_8_9$vertex(worldrenderer, matrix, (float) -0.3, (float) 0, (float) -0.06).tex(minU, minV).normal(0, 1, 0).endVertex(); + v1_8_9$vertex(worldrenderer, matrix, (float) 0.3, (float) 0, (float) -0.06).tex(maxU, minV).normal(0, 1, 0).endVertex(); + } +} diff --git a/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinSplashScreen.java b/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinSplashScreen.java index 2fa158a9..ac58401b 100644 --- a/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinSplashScreen.java +++ b/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinSplashScreen.java @@ -4,7 +4,6 @@ import net.minecraft.client.gui.ScaledResolution; import net.minecraft.client.renderer.GlStateManager; import net.minecraft.client.shader.Framebuffer; -import net.minecraft.util.ResourceLocation; import net.minecraftforge.fml.client.SplashProgress; import org.lwjgl.opengl.Display; import org.spongepowered.asm.mixin.Mixin; @@ -14,7 +13,7 @@ import java.awt.*; -@Mixin(value = SplashProgress.class) +@Mixin(SplashProgress.class) @SuppressWarnings("all") public class MixinSplashScreen { diff --git a/v1.8.9/src/main/resources/mixins.fpsmaster.json b/v1.8.9/src/main/resources/mixins.fpsmaster.json index 52021163..29860d84 100644 --- a/v1.8.9/src/main/resources/mixins.fpsmaster.json +++ b/v1.8.9/src/main/resources/mixins.fpsmaster.json @@ -34,6 +34,7 @@ "MixinItemRenderer", "MixinKeybinding", "MixinLayerArmorBase", + "MixinLayerCape", "MixinLayerHeldItem", "MixinMainMenu", "MixinMinecraft", From ab91712ee81f509bb13fbe56dcc08a54586d7330 Mon Sep 17 00:00:00 2001 From: SuperSkidder Date: Sun, 20 Jul 2025 21:45:30 +0800 Subject: [PATCH 160/193] feat: add wind effect --- .../features/impl/optimizes/WavyCape.java | 3 +- .../fpsmaster/forge/mixin/MixinLayerCape.java | 420 +++++++++--------- 2 files changed, 202 insertions(+), 221 deletions(-) diff --git a/shared/java/top/fpsmaster/features/impl/optimizes/WavyCape.java b/shared/java/top/fpsmaster/features/impl/optimizes/WavyCape.java index 662a86e6..578ee6a6 100644 --- a/shared/java/top/fpsmaster/features/impl/optimizes/WavyCape.java +++ b/shared/java/top/fpsmaster/features/impl/optimizes/WavyCape.java @@ -2,9 +2,10 @@ import top.fpsmaster.features.manager.Category; import top.fpsmaster.features.manager.Module; +import top.fpsmaster.features.settings.impl.ModeSetting; public class WavyCape extends Module { public WavyCape() { - super("WavyCape", Category.OPTIMIZE); + super("WavyCape", Category.RENDER); } } diff --git a/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinLayerCape.java b/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinLayerCape.java index 0bd3bc85..fd1bc8e2 100644 --- a/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinLayerCape.java +++ b/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinLayerCape.java @@ -1,6 +1,7 @@ package top.fpsmaster.forge.mixin; import net.minecraft.client.entity.AbstractClientPlayer; +import net.minecraft.client.renderer.GlStateManager; import net.minecraft.client.renderer.Tessellator; import net.minecraft.client.renderer.WorldRenderer; import net.minecraft.client.renderer.entity.RenderPlayer; @@ -26,285 +27,264 @@ @Mixin(LayerCape.class) public abstract class MixinLayerCape implements LayerRenderer { + @Shadow @Final private RenderPlayer playerRenderer; + private static final int SEGMENTS = 16; + private static final float CAPE_WIDTH = 0.6F; + private static final float CAPE_LENGTH = 0.96F; + private static final float CAPE_DEPTH = 0.06F; - @Inject(method = "doRenderLayer(Lnet/minecraft/client/entity/AbstractClientPlayer;FFFFFFF)V", at = @At("HEAD"), cancellable = true) - public void renderLayer(AbstractClientPlayer player, float f, float g, float partialTicks, float h, float i, float j, float scale, CallbackInfo ci) { - if (FPSMaster.moduleManager.getModule(WavyCape.class).isEnabled()) { - if (player.isInvisible()) return; + @Inject(method = "doRenderLayer", at = @At("HEAD"), cancellable = true) + public void onRenderCape(AbstractClientPlayer player, float limbSwing, float limbSwingAmount, float partialTicks, + float ageInTicks, float netHeadYaw, float headPitch, float scale, CallbackInfo ci) { + if (!FPSMaster.moduleManager.getModule(WavyCape.class).isEnabled()) return; + if (shouldSkipRender(player)) return; - if (!player.hasPlayerInfo() || player.isInvisible() || !player.isWearing(EnumPlayerModelParts.CAPE) || player.getLocationCape() == null) { - return; - } - this.playerRenderer.bindTexture(player.getLocationCape()); - v1_8_9$renderSmoothCape(player, partialTicks); - ci.cancel(); - } + playerRenderer.bindTexture(player.getLocationCape()); + renderWavyCape(player, partialTicks); + ci.cancel(); + } + + @Unique + private boolean shouldSkipRender(AbstractClientPlayer player) { + return player.isInvisible() || + !player.hasPlayerInfo() || + !player.isWearing(EnumPlayerModelParts.CAPE) || + player.getLocationCape() == null; } @Unique - public void v1_8_9$renderSmoothCape(AbstractClientPlayer abstractClientPlayer, float delta) { - WorldRenderer worldrenderer = Tessellator.getInstance().getWorldRenderer(); - worldrenderer.begin(7, DefaultVertexFormats.POSITION_TEX_NORMAL); + private void renderWavyCape(AbstractClientPlayer player, float partialTicks) { + Tessellator tessellator = Tessellator.getInstance(); + WorldRenderer buffer = tessellator.getWorldRenderer(); PoseStack poseStack = new PoseStack(); + + buffer.begin(7, DefaultVertexFormats.POSITION_TEX_NORMAL); poseStack.pushPose(); - Matrix4f oldPositionMatrix = null; - for (int part = 0; part < 16; part++) { - v1_8_9$modifyPoseStack(poseStack, abstractClientPlayer, delta, part); + Matrix4f prevMatrix = null; + final float segmentLength = CAPE_LENGTH / SEGMENTS; + + for (int segment = 0; segment < SEGMENTS; segment++) { + poseStack.pushPose(); + applySegmentTransform(poseStack, player, partialTicks, segment); + + Matrix4f currentMatrix = poseStack.last().pose; + float yOffsetTop = segment * segmentLength; + float yOffsetBottom = (segment + 1) * segmentLength; - if (oldPositionMatrix == null) { - oldPositionMatrix = poseStack.last().pose; + if (prevMatrix != null) { + renderCapeSegment(buffer, prevMatrix, currentMatrix, yOffsetTop, yOffsetBottom, segment); } - if (part == 0) { - v1_8_9$addTopVertex(worldrenderer, poseStack.last().pose, oldPositionMatrix, part); - } else if (part == 15) { - v1_8_9$addBottomVertex(worldrenderer, poseStack.last().pose, poseStack.last().pose, (part + 1) * (0.96F / 16), (part + 1) * (0.96F / 16), part); + if (segment == 0) { + renderTopSegment(buffer, currentMatrix); } - v1_8_9$addLeftVertex(worldrenderer, poseStack.last().pose, oldPositionMatrix, (part + 1) * (0.96F / 16), part * (0.96F / 16), part); - v1_8_9$addRightVertex(worldrenderer, poseStack.last().pose, oldPositionMatrix, (part + 1) * (0.96F / 16), part * (0.96F / 16), part); - v1_8_9$addBackVertex(worldrenderer, poseStack.last().pose, oldPositionMatrix, (part + 1) * (0.96F / 16), part * (0.96F / 16), part); - v1_8_9$addFrontVertex(worldrenderer, oldPositionMatrix, poseStack.last().pose, (part + 1) * (0.96F / 16), part * (0.96F / 16), part); - oldPositionMatrix = poseStack.last().pose; + prevMatrix = currentMatrix; poseStack.popPose(); } - Tessellator.getInstance().draw(); + + poseStack.popPose(); + tessellator.draw(); } @Unique - private void v1_8_9$modifyPoseStack(PoseStack poseStack, AbstractClientPlayer abstractClientPlayer, float h, int part) { - poseStack.pushPose(); - poseStack.translate(0.0D, 0.0D, 0.125D); - double d = v1_8_9$lerp(h, abstractClientPlayer.prevChasingPosX, abstractClientPlayer.chasingPosX) - - v1_8_9$lerp(h, abstractClientPlayer.prevPosX, abstractClientPlayer.posX); - double e = v1_8_9$lerp(h, abstractClientPlayer.prevChasingPosY, abstractClientPlayer.chasingPosY) - - v1_8_9$lerp(h, abstractClientPlayer.prevPosY, abstractClientPlayer.posY); - double m = v1_8_9$lerp(h, abstractClientPlayer.prevChasingPosZ, abstractClientPlayer.chasingPosZ) - - v1_8_9$lerp(h, abstractClientPlayer.prevPosZ, abstractClientPlayer.posZ); - float n = abstractClientPlayer.prevRenderYawOffset + abstractClientPlayer.renderYawOffset - abstractClientPlayer.prevRenderYawOffset; - double o = Math.sin(n * 0.017453292F); - double p = -Math.cos(n * 0.017453292F); - float height = (float) e * 10.0F; - height = MathHelper.clamp_float(height, -6.0F, 32.0F); - float swing = (float) (d * o + m * p) * v1_8_9$easeOutSine(1.0F / 16 * part) * 100; - swing = MathHelper.clamp_float(swing, 0.0F, 150.0F * v1_8_9$easeOutSine(1F / 16 * part)); - float sidewaysRotationOffset = (float) (d * p - m * o) * 100.0F; - sidewaysRotationOffset = MathHelper.clamp_float(sidewaysRotationOffset, -20.0F, 20.0F); - float t = v1_8_9$lerp(h, abstractClientPlayer.prevCameraYaw, abstractClientPlayer.cameraYaw); - height += (float) (Math.sin(v1_8_9$lerp(h, abstractClientPlayer.prevDistanceWalkedModified, abstractClientPlayer.distanceWalkedModified) * 6.0F) * 32.0F * t); - if (abstractClientPlayer.isSneaking()) { - height += 25.0F; + private void applySegmentTransform(PoseStack poseStack, AbstractClientPlayer player, float partialTicks, int segment) { + poseStack.translate(0.0, 0.0, 0.125); + + // 计算玩家运动差值 + double motionX = interpolate(partialTicks, player.prevChasingPosX, player.chasingPosX) - + interpolate(partialTicks, player.prevPosX, player.posX); + double motionY = interpolate(partialTicks, player.prevChasingPosY, player.chasingPosY) - + interpolate(partialTicks, player.prevPosY, player.posY); + double motionZ = interpolate(partialTicks, player.prevChasingPosZ, player.chasingPosZ) - + interpolate(partialTicks, player.prevPosZ, player.posZ); + + // 计算旋转角度 + float yawOffset = interpolate(partialTicks, player.prevRenderYawOffset, player.renderYawOffset); + double sinYaw = Math.sin(yawOffset * Math.PI / 180.0); + double cosYaw = -Math.cos(yawOffset * Math.PI / 180.0); + + // 计算高度偏移 + float heightOffset = (float) motionY * 10.0F; + heightOffset = MathHelper.clamp_float(heightOffset, -6.0F, 32.0F); + + // 计算摆动幅度 + float swingFactor = (float) (motionX * sinYaw + motionZ * cosYaw) * + easeOutSine((float) segment / SEGMENTS) * 100; + swingFactor = MathHelper.clamp_float(swingFactor, 0.0F, 150.0F * easeOutSine((float) segment / SEGMENTS)); + + // 计算侧向旋转 + float sidewaysRotation = (float) (motionX * cosYaw - motionZ * sinYaw) * 100.0F; + sidewaysRotation = MathHelper.clamp_float(sidewaysRotation, -20.0F, 20.0F); + + // 添加行走动画效果 + float walkAnimation = interpolate(partialTicks, player.prevDistanceWalkedModified, player.distanceWalkedModified); + heightOffset += MathHelper.sin(walkAnimation * 6.0F) * 32.0F * + interpolate(partialTicks, player.prevCameraYaw, player.cameraYaw); + + // 蹲下调整 + if (player.isSneaking()) { + heightOffset += 25.0F; poseStack.translate(0, 0.15F, 0); } - poseStack.mulPose(v1_8_9$fromDegree(1.0F, 0.0F, 0.0F, 6.0F + swing / 2.0F + height)); - poseStack.mulPose(v1_8_9$fromDegree(0.0F, 0.0F, 1.0F, sidewaysRotationOffset / 2.0F)); - poseStack.mulPose(v1_8_9$fromDegree(0.0F, 1.0F, 0.0F, 180.0F - sidewaysRotationOffset / 2.0F)); + // 应用风摆效果 + float windSwing = calculateWindSwing(segment); + + // 应用旋转 + poseStack.mulPose(createQuaternion(1.0F, 0.0F, 0.0F, 6.0F + swingFactor / 2.0F + heightOffset + windSwing)); + poseStack.mulPose(createQuaternion(0.0F, 0.0F, 1.0F, sidewaysRotation / 2.0F)); + poseStack.mulPose(createQuaternion(0.0F, 1.0F, 0.0F, 180.0F - sidewaysRotation / 2.0F)); } @Unique - private float v1_8_9$easeOutSine(float x) { - return (float) Math.sin((x * Math.PI) / 2); + private float calculateWindSwing(int segment) { + long time = System.currentTimeMillis() / 3; + float phase = (float) (segment + 1) / SEGMENTS; + return (float) Math.sin(Math.toRadians(phase * 360 - (time % 360))) * 3; } @Unique - private Quaternion v1_8_9$fromDegree(float x, float y, float z, float degree) { - Quaternion quaternion = new Quaternion(); - degree *= 0.017453292F; - float g = (float) Math.sin(degree / 2.0F); - quaternion.x = x * g; - quaternion.y = y * g; - quaternion.z = z * g; - quaternion.w = (float) Math.cos(degree / 2.0F); - return quaternion; + private void renderCapeSegment(WorldRenderer buffer, Matrix4f prevMatrix, Matrix4f currentMatrix, + float yTop, float yBottom, int segment) { + renderBackFace(buffer, prevMatrix, currentMatrix, yTop, yBottom, segment); + renderFrontFace(buffer, prevMatrix, currentMatrix, yTop, yBottom, segment); + renderLeftSide(buffer, prevMatrix, currentMatrix, yTop, yBottom, segment); + renderRightSide(buffer, prevMatrix, currentMatrix, yTop, yBottom, segment); + + if (segment == SEGMENTS - 1) { + renderBottomEdge(buffer, prevMatrix, currentMatrix, yTop, yBottom); + } } @Unique - private float v1_8_9$lerp(float f, float g, float h) { - return g + f * (h - g); + private void renderBackFace(WorldRenderer buffer, Matrix4f prevMatrix, Matrix4f currentMatrix, + float yTop, float yBottom, int segment) { + float minU = 0.015625F; + float maxU = 0.171875F; + float[] texCoords = getVerticalTexCoords(segment, 0.03125F, 0.53125F); + + addVertex(buffer, prevMatrix, -CAPE_WIDTH/2, yTop, -CAPE_DEPTH, minU, texCoords[0]); + addVertex(buffer, prevMatrix, CAPE_WIDTH/2, yTop, -CAPE_DEPTH, maxU, texCoords[0]); + addVertex(buffer, currentMatrix, CAPE_WIDTH/2, yBottom, -CAPE_DEPTH, maxU, texCoords[1]); + addVertex(buffer, currentMatrix, -CAPE_WIDTH/2, yBottom, -CAPE_DEPTH, minU, texCoords[1]); } @Unique - private double v1_8_9$lerp(double d, double e, double f) { - return e + d * (f - e); + private void renderFrontFace(WorldRenderer buffer, Matrix4f prevMatrix, Matrix4f currentMatrix, + float yTop, float yBottom, int segment) { + float minU = 0.1875F; + float maxU = 0.34375F; + float[] texCoords = getVerticalTexCoords(segment, 0.03125F, 0.53125F); + + addVertex(buffer, prevMatrix, -CAPE_WIDTH/2, yBottom, 0, minU, texCoords[1]); + addVertex(buffer, prevMatrix, CAPE_WIDTH/2, yBottom, 0, maxU, texCoords[1]); + addVertex(buffer, currentMatrix, CAPE_WIDTH/2, yTop, 0, maxU, texCoords[0]); + addVertex(buffer, currentMatrix, -CAPE_WIDTH/2, yTop, 0, minU, texCoords[0]); } @Unique - private void v1_8_9$addBackVertex(WorldRenderer worldrenderer, Matrix4f matrix, Matrix4f oldMatrix, float y1, float y2, int part) { - float i; - Matrix4f k; - if (y1 < y2) { - i = y1; - y1 = y2; - y2 = i; - - k = matrix; - matrix = oldMatrix; - oldMatrix = k; - } - - float minU = .015625F; - float maxU = .171875F; - - float minV = .03125F; - float maxV = .53125F; - - float deltaV = maxV - minV; - float vPerPart = deltaV / 16; - maxV = minV + (vPerPart * (part + 1)); - minV = minV + (vPerPart * part); - - v1_8_9$vertex(worldrenderer, oldMatrix, (float) 0.3, y2, (float) -0.06).tex(maxU, minV).normal(1, 0, 0).endVertex(); - v1_8_9$vertex(worldrenderer, oldMatrix, (float) -0.3, y2, (float) -0.06).tex(minU, minV).normal(1, 0, 0).endVertex(); - v1_8_9$vertex(worldrenderer, matrix, (float) -0.3, y1, (float) -0.06).tex(minU, maxV).normal(1, 0, 0).endVertex(); - v1_8_9$vertex(worldrenderer, matrix, (float) 0.3, y1, (float) -0.06).tex(maxU, maxV).normal(1, 0, 0).endVertex(); - + private void renderLeftSide(WorldRenderer buffer, Matrix4f prevMatrix, Matrix4f currentMatrix, + float yTop, float yBottom, int segment) { + float minU = 0.0F; + float maxU = 0.015625F; + float[] texCoords = getVerticalTexCoords(segment, 0.03125F, 0.53125F); + + addVertex(buffer, prevMatrix, -CAPE_WIDTH/2, yTop, 0, maxU, texCoords[0]); + addVertex(buffer, prevMatrix, -CAPE_WIDTH/2, yTop, -CAPE_DEPTH, minU, texCoords[0]); + addVertex(buffer, currentMatrix, -CAPE_WIDTH/2, yBottom, -CAPE_DEPTH, minU, texCoords[1]); + addVertex(buffer, currentMatrix, -CAPE_WIDTH/2, yBottom, 0, maxU, texCoords[1]); } @Unique - private void v1_8_9$addFrontVertex(WorldRenderer worldrenderer, Matrix4f matrix, Matrix4f oldMatrix, float y1, float y2, int part) { - float i; - Matrix4f k; - - if (y1 < y2) { - i = y1; - y1 = y2; - y2 = i; - - k = matrix; - matrix = oldMatrix; - oldMatrix = k; - } - - float minU = .1875F; - float maxU = .34375F; - - float minV = .03125F; - float maxV = .53125F; - - float deltaV = maxV - minV; - float vPerPart = deltaV / 16; - maxV = minV + (vPerPart * (part + 1)); - minV = minV + (vPerPart * part); - - v1_8_9$vertex(worldrenderer, oldMatrix, (float) 0.3, y1, (float) 0.0).tex(maxU, maxV).normal(1, 0, 0).endVertex(); - v1_8_9$vertex(worldrenderer, oldMatrix, (float) -0.3, y1, (float) 0.0).tex(minU, maxV).normal(1, 0, 0).endVertex(); - v1_8_9$vertex(worldrenderer, matrix, (float) -0.3, y2, (float) 0.0).tex(minU, minV).normal(1, 0, 0).endVertex(); - v1_8_9$vertex(worldrenderer, matrix, (float) 0.3, y2, (float) 0.0).tex(maxU, minV).normal(1, 0, 0).endVertex(); - + private void renderRightSide(WorldRenderer buffer, Matrix4f prevMatrix, Matrix4f currentMatrix, + float yTop, float yBottom, int segment) { + float minU = 0.171875F; + float maxU = 0.1875F; + float[] texCoords = getVerticalTexCoords(segment, 0.03125F, 0.53125F); + + addVertex(buffer, prevMatrix, CAPE_WIDTH/2, yTop, -CAPE_DEPTH, minU, texCoords[0]); + addVertex(buffer, prevMatrix, CAPE_WIDTH/2, yTop, 0, maxU, texCoords[0]); + addVertex(buffer, currentMatrix, CAPE_WIDTH/2, yBottom, 0, maxU, texCoords[1]); + addVertex(buffer, currentMatrix, CAPE_WIDTH/2, yBottom, -CAPE_DEPTH, minU, texCoords[1]); } @Unique - private void v1_8_9$addLeftVertex(WorldRenderer worldrenderer, Matrix4f matrix, Matrix4f oldMatrix, float y1, float y2, int part) { - float i; - if (y1 < y2) { - i = y1; - y1 = y2; - y2 = i; - } - - float minU = 0; - float maxU = .015625F; - - float minV = .03125F; - float maxV = .53125F; - - float deltaV = maxV - minV; - float vPerPart = deltaV / 16; - maxV = minV + (vPerPart * (part + 1)); - minV = minV + (vPerPart * part); - - v1_8_9$vertex(worldrenderer, oldMatrix, (float) -0.3, y2, (float) -0.06).tex(minU, minV).normal(1, 0, 0).endVertex(); - v1_8_9$vertex(worldrenderer, oldMatrix, (float) -0.3, y2, (float) 0.0).tex(maxU, minV).normal(1, 0, 0).endVertex(); - v1_8_9$vertex(worldrenderer, matrix, (float) -0.3, y1, (float) 0.0).tex(maxU, maxV).normal(1, 0, 0).endVertex(); - v1_8_9$vertex(worldrenderer, matrix, (float) -0.3, y1, (float) -0.06).tex(minU, maxV).normal(1, 0, 0).endVertex(); - + private void renderTopSegment(WorldRenderer buffer, Matrix4f matrix) { + float minU = 0.015625F; + float maxU = 0.171875F; + float minV = 0.0F; + float maxV = 0.03125F; + + addVertex(buffer, matrix, -CAPE_WIDTH/2, 0, 0, minU, maxV); + addVertex(buffer, matrix, CAPE_WIDTH/2, 0, 0, maxU, maxV); + addVertex(buffer, matrix, CAPE_WIDTH/2, 0, -CAPE_DEPTH, maxU, minV); + addVertex(buffer, matrix, -CAPE_WIDTH/2, 0, -CAPE_DEPTH, minU, minV); } @Unique - private void v1_8_9$addRightVertex(WorldRenderer worldrenderer, Matrix4f matrix, Matrix4f oldMatrix, float y1, float y2, int part) { - float i; - - if (y1 < y2) { - i = y1; - y1 = y2; - y2 = i; - } - - float minU = .171875F; - float maxU = .1875F; - - float minV = .03125F; - float maxV = .53125F; - - float deltaV = maxV - minV; - float vPerPart = deltaV / 16; - maxV = minV + (vPerPart * (part + 1)); - minV = minV + (vPerPart * part); - - v1_8_9$vertex(worldrenderer, oldMatrix, (float) 0.3, y2, (float) 0.0).tex(maxU, minV).normal(1, 0, 0).endVertex(); - v1_8_9$vertex(worldrenderer, oldMatrix, (float) 0.3, y2, (float) -0.06).tex(minU, minV).normal(1, 0, 0).endVertex(); - v1_8_9$vertex(worldrenderer, matrix, (float) 0.3, y1, (float) -0.06).tex(minU, maxV).normal(1, 0, 0).endVertex(); - v1_8_9$vertex(worldrenderer, matrix, (float) 0.3, y1, (float) 0.0).tex(maxU, maxV).normal(1, 0, 0).endVertex(); - + private void renderBottomEdge(WorldRenderer buffer, Matrix4f prevMatrix, Matrix4f currentMatrix, + float yTop, float yBottom) { + float minU = 0.171875F; + float maxU = 0.328125F; + float minV = 0.0F; + float maxV = 0.03125F; + + addVertex(buffer, prevMatrix, -CAPE_WIDTH/2, yBottom, -CAPE_DEPTH, minU, minV); + addVertex(buffer, prevMatrix, CAPE_WIDTH/2, yBottom, -CAPE_DEPTH, maxU, minV); + addVertex(buffer, currentMatrix, CAPE_WIDTH/2, yTop, 0, maxU, maxV); + addVertex(buffer, currentMatrix, -CAPE_WIDTH/2, yTop, 0, minU, maxV); } @Unique - private void v1_8_9$addBottomVertex(WorldRenderer worldrenderer, Matrix4f matrix, Matrix4f oldMatrix, float y1, float y2, int part) { - float i; - if (y1 < y2) { - i = y1; - y1 = y2; - y2 = i; - } - - float minU = .171875F; - float maxU = .328125F; - - float minV = 0; - float maxV = .03125F; + private float[] getVerticalTexCoords(int segment, float minV, float maxV) { + float vRange = maxV - minV; + float vStep = vRange / SEGMENTS; + return new float[] { + minV + segment * vStep, + minV + (segment + 1) * vStep + }; + } - float deltaV = maxV - minV; - float vPerPart = deltaV / 16; - maxV = minV + (vPerPart * (part + 1)); - minV = minV + (vPerPart * part); + @Unique + private void addVertex(WorldRenderer buffer, Matrix4f matrix, float x, float y, float z, float u, float v) { + Vector4f pos = new Vector4f(x, y, z, 1.0F); + matrix.transform(pos); + buffer.pos(pos.x, pos.y, pos.z) + .tex(u, v) + .normal(0, 1, 0) // 实际法线应根据面调整,此处简化为(0,1,0) + .endVertex(); + } - v1_8_9$vertex(worldrenderer, oldMatrix, (float) 0.3, y2, (float) -0.06).tex(maxU, minV).normal(1, 0, 0).endVertex(); - v1_8_9$vertex(worldrenderer, oldMatrix, (float) -0.3, y2, (float) -0.06).tex(minU, minV).normal(1, 0, 0).endVertex(); - v1_8_9$vertex(worldrenderer, matrix, (float) -0.3, y1, (float) 0.0).tex(minU, maxV).normal(1, 0, 0).endVertex(); - v1_8_9$vertex(worldrenderer, matrix, (float) 0.3, y1, (float) 0.0).tex(maxU, maxV).normal(1, 0, 0).endVertex(); + @Unique + private float interpolate(float delta, float prev, float current) { + return prev + delta * (current - prev); + } + @Unique + private double interpolate(double delta, double prev, double current) { + return prev + delta * (current - prev); } @Unique - private WorldRenderer v1_8_9$vertex(WorldRenderer worldrenderer, Matrix4f matrix4f, float f, float g, float h) { - Vector4f vector4f = new Vector4f(f, g, h, 1.0F); - matrix4f.transform(vector4f); - worldrenderer.pos(vector4f.x, vector4f.y, vector4f.z); - return worldrenderer; + private float easeOutSine(float progress) { + return (float) Math.sin((progress * Math.PI) / 2); } @Unique - private void v1_8_9$addTopVertex(WorldRenderer worldrenderer, Matrix4f matrix, Matrix4f oldMatrix, int part) { - float minU = .015625F; - float maxU = .171875F; - - float minV = 0; - float maxV = .03125F; - - float deltaV = maxV - minV; - float vPerPart = deltaV / 16; - maxV = minV + (vPerPart * (part + 1)); - minV = minV + (vPerPart * part); - - v1_8_9$vertex(worldrenderer, oldMatrix, (float) 0.3, (float) 0, (float) 0.0).tex(maxU, maxV).normal(0, 1, 0).endVertex(); - v1_8_9$vertex(worldrenderer, oldMatrix, (float) -0.3, (float) 0, (float) 0.0).tex(minU, maxV).normal(0, 1, 0).endVertex(); - v1_8_9$vertex(worldrenderer, matrix, (float) -0.3, (float) 0, (float) -0.06).tex(minU, minV).normal(0, 1, 0).endVertex(); - v1_8_9$vertex(worldrenderer, matrix, (float) 0.3, (float) 0, (float) -0.06).tex(maxU, minV).normal(0, 1, 0).endVertex(); + private Quaternion createQuaternion(float axisX, float axisY, float axisZ, float degrees) { + Quaternion q = new Quaternion(); + float radians = degrees * (float) Math.PI / 180; + float sinHalf = (float) Math.sin(radians / 2); + q.x = axisX * sinHalf; + q.y = axisY * sinHalf; + q.z = axisZ * sinHalf; + q.w = (float) Math.cos(radians / 2); + return q; } -} +} \ No newline at end of file From 98782b321078e309ad5f49cd918538ef073ccd75 Mon Sep 17 00:00:00 2001 From: SuperSkidder Date: Sun, 20 Jul 2025 23:12:41 +0800 Subject: [PATCH 161/193] optimize: code quality --- .../java/top/fpsmaster/event/ASMHandler.java | 11 +- .../event/events/EventValueChange.java | 4 +- .../fpsmaster/features/GlobalListener.java | 2 +- .../features/impl/interfaces/MiniMap.java | 9 + .../impl/interfaces/TargetDisplay.java | 2 +- .../impl/optimizes/OldAnimations.java | 2 +- .../features/impl/render/BlockOverlay.java | 6 +- .../features/impl/render/Crosshair.java | 8 +- .../features/impl/render/DamageIndicator.java | 22 +- .../features/impl/utility/SkinChanger.java | 12 +- .../fpsmaster/font/EnhancedFontRenderer.java | 2 +- .../top/fpsmaster/font/FontRendererHook.java | 6 +- .../top/fpsmaster/font/impl/GlyphCache.java | 5 +- .../top/fpsmaster/font/impl/StringCache.java | 2 +- .../modules/account/AccountManager.java | 2 +- .../modules/logger/ClientLogger.java | 4 +- .../top/fpsmaster/modules/lua/LuaManager.java | 20 +- .../fpsmaster/modules/music/MusicPlayer.java | 4 +- .../netease/deserialize/MusicWrapper.java | 12 +- .../ui/click/modules/ModuleRenderer.java | 31 +- .../modules/impl/NumberSettingRender.java | 2 - .../fpsmaster/ui/click/music/MusicPanel.java | 13 +- .../top/fpsmaster/ui/common/TextField.java | 13 +- .../custom/impl/PotionDisplayComponent.java | 2 +- .../top/fpsmaster/ui/devspace/DevSpace.java | 6 +- .../FunctionCallExpressionComponent.java | 2 +- .../top/fpsmaster/ui/mc/GuiMultiplayer.java | 14 +- .../top/fpsmaster/ui/mc/ServerListEntry.java | 4 +- .../ui/screens/mainmenu/MainMenu.java | 12 +- .../ui/screens/oobe/impls/Login.java | 4 +- shared/java/top/fpsmaster/utils/Utility.java | 7 +- .../top/fpsmaster/utils/awt/AWTUtils.java | 72 ---- .../fpsmaster/utils/render/Render2DUtils.java | 14 +- .../fpsmaster/utils/render/StencilUtil.java | 11 +- .../utils/thirdparty/openai/OpenAI.java | 34 +- .../thirdparty/rawinput/RawInputMod.java | 2 +- .../websocket/data/message/Packet.java | 2 +- .../forge/mixin/MixinGuiNewChat.java | 15 +- .../forge/mixin/MixinGuiPlayerOverlay.java | 2 +- .../mixin/MixinInventoryEffectRenderer.java | 4 +- .../forge/mixin/MixinItemRenderer.java | 4 +- .../java/top/fpsmaster/minimap/Minimap.java | 315 ++++++++---------- .../wrapper/ChatFormattingProvider.java | 7 +- .../top/fpsmaster/wrapper/SkinProvider.java | 2 +- .../wrapper/util/WrapperAxisAlignedBB.java | 4 +- 45 files changed, 290 insertions(+), 443 deletions(-) diff --git a/shared/java/top/fpsmaster/event/ASMHandler.java b/shared/java/top/fpsmaster/event/ASMHandler.java index 6df043ef..f213b45f 100644 --- a/shared/java/top/fpsmaster/event/ASMHandler.java +++ b/shared/java/top/fpsmaster/event/ASMHandler.java @@ -82,15 +82,8 @@ public static Handler loadHandlerClass(Object listener, Method method) { try { return (Handler) EventClassLoader.defineClass(declaringClass.getClassLoader(), className, cv.toByteArray()).getConstructor(Object.class, Method.class).newInstance(listener, method); - } catch (InstantiationException e) { - throw new RuntimeException(e); - } catch (IllegalAccessException e) { - throw new RuntimeException(e); - } catch (InvocationTargetException e) { - throw new RuntimeException(e); - } catch (NoSuchMethodException e) { - throw new RuntimeException(e); - } catch (ClassNotFoundException e) { + } catch (InstantiationException | IllegalAccessException | InvocationTargetException | NoSuchMethodException | + ClassNotFoundException e) { throw new RuntimeException(e); } } diff --git a/shared/java/top/fpsmaster/event/events/EventValueChange.java b/shared/java/top/fpsmaster/event/events/EventValueChange.java index 0f9a94fa..03c5fad9 100644 --- a/shared/java/top/fpsmaster/event/events/EventValueChange.java +++ b/shared/java/top/fpsmaster/event/events/EventValueChange.java @@ -4,10 +4,10 @@ import top.fpsmaster.features.settings.Setting; public class EventValueChange extends CancelableEvent { - public Setting setting; + public Setting setting; public Object oldValue; public Object newValue; - public EventValueChange(Setting setting, Object oldValue, Object newValue) { + public EventValueChange(Setting setting, Object oldValue, Object newValue) { this.setting = setting; this.oldValue = oldValue; this.newValue = newValue; diff --git a/shared/java/top/fpsmaster/features/GlobalListener.java b/shared/java/top/fpsmaster/features/GlobalListener.java index 53fe8d80..55c40fa8 100644 --- a/shared/java/top/fpsmaster/features/GlobalListener.java +++ b/shared/java/top/fpsmaster/features/GlobalListener.java @@ -200,7 +200,7 @@ public void onRender(EventRender2D e) { NotificationManager.drawNotifications(); } - class PlayerInformation { + static class PlayerInformation { String name; String uuid; String serverAddress; diff --git a/shared/java/top/fpsmaster/features/impl/interfaces/MiniMap.java b/shared/java/top/fpsmaster/features/impl/interfaces/MiniMap.java index 315bbe79..2f481297 100644 --- a/shared/java/top/fpsmaster/features/impl/interfaces/MiniMap.java +++ b/shared/java/top/fpsmaster/features/impl/interfaces/MiniMap.java @@ -11,9 +11,12 @@ public MiniMap() { super("MiniMap", Category.Interface); } + public static boolean using = false; + @Override public void onEnable() { super.onEnable(); + using = true; if (OptifineUtil.isFastRender()) { OptifineUtil.setFastRender(false); NotificationManager.addNotification( @@ -23,4 +26,10 @@ public void onEnable() { ); } } + + @Override + public void onDisable() { + super.onDisable(); + using = false; + } } diff --git a/shared/java/top/fpsmaster/features/impl/interfaces/TargetDisplay.java b/shared/java/top/fpsmaster/features/impl/interfaces/TargetDisplay.java index 3a87c3f5..758fe049 100644 --- a/shared/java/top/fpsmaster/features/impl/interfaces/TargetDisplay.java +++ b/shared/java/top/fpsmaster/features/impl/interfaces/TargetDisplay.java @@ -70,7 +70,7 @@ private void drawCircle(Entity entity, double rad, boolean shade) { GL11.glColor4f(c.getRed() / 255f, c.getGreen() / 255f, c.getBlue() / 255f, 0.75f); } GL11.glVertex3d(vecX, y, vecZ); - i += (Math.PI * 2 / 64f); + i += (float) (Math.PI * 2 / 64f); } GL11.glEnd(); if (shade) GL11.glShadeModel(GL11.GL_FLAT); diff --git a/shared/java/top/fpsmaster/features/impl/optimizes/OldAnimations.java b/shared/java/top/fpsmaster/features/impl/optimizes/OldAnimations.java index 006a01ba..32a7ba18 100644 --- a/shared/java/top/fpsmaster/features/impl/optimizes/OldAnimations.java +++ b/shared/java/top/fpsmaster/features/impl/optimizes/OldAnimations.java @@ -29,7 +29,7 @@ public class OldAnimations extends Module { public static BooleanSetting blockSwing = new BooleanSetting("BlockSwing", true); public static BooleanSetting oldDamage = new BooleanSetting("OldDamage", true); public static BooleanSetting oldThirdPerson = new BooleanSetting("OldThirdPerson", true); - ; + public static NumberSetting x = new NumberSetting("X", 0, -1, 1, 0.01); public static NumberSetting y = new NumberSetting("Y", 0, -1, 1, 0.01); public static NumberSetting z = new NumberSetting("Z", 0, -1, 1, 0.01); diff --git a/shared/java/top/fpsmaster/features/impl/render/BlockOverlay.java b/shared/java/top/fpsmaster/features/impl/render/BlockOverlay.java index b7415077..b9782ee4 100644 --- a/shared/java/top/fpsmaster/features/impl/render/BlockOverlay.java +++ b/shared/java/top/fpsmaster/features/impl/render/BlockOverlay.java @@ -24,9 +24,9 @@ public class BlockOverlay extends Module { private final BooleanSetting fill = new BooleanSetting("Fill", true); private final BooleanSetting outline = new BooleanSetting("Outline", true); private final BooleanSetting throughBlock = new BooleanSetting("ThroughBlock", false); - private final NumberSetting width = new NumberSetting("Width", 1, 0.1, 10, 0.1, ()->outline.getValue()); - private final ColorSetting color1 = new ColorSetting("FillColor", new Color(255, 255, 255, 50), ()->fill.getValue()); - private final ColorSetting color2 = new ColorSetting("OutlineColor", new Color(255, 255, 255, 255), ()->outline.getValue()); + private final NumberSetting width = new NumberSetting("Width", 1, 0.1, 10, 0.1, outline::getValue); + private final ColorSetting color1 = new ColorSetting("FillColor", new Color(255, 255, 255, 50), fill::getValue); + private final ColorSetting color2 = new ColorSetting("OutlineColor", new Color(255, 255, 255, 255), outline::getValue); public static boolean using = false; public BlockOverlay(){ diff --git a/shared/java/top/fpsmaster/features/impl/render/Crosshair.java b/shared/java/top/fpsmaster/features/impl/render/Crosshair.java index b3a1974b..6282d3ac 100644 --- a/shared/java/top/fpsmaster/features/impl/render/Crosshair.java +++ b/shared/java/top/fpsmaster/features/impl/render/Crosshair.java @@ -22,13 +22,13 @@ public class Crosshair extends Module { private final NumberSetting dynamic = new NumberSetting("Dynamic", 4, 0, 10, 0.1); private final BooleanSetting outline = new BooleanSetting("Outline", true); - private final NumberSetting outlineWidth = new NumberSetting("OutlineWidth", 1, 0, 10, 0.1, () -> outline.getValue()); + private final NumberSetting outlineWidth = new NumberSetting("OutlineWidth", 1, 0, 10, 0.1, outline::getValue); private final BooleanSetting dot = new BooleanSetting("Dot", true); private final NumberSetting gap = new NumberSetting("Gap", 6, 0, 10, 0.1); private final NumberSetting width = new NumberSetting("Width", 0.6, 0, 10, 0.1); private final NumberSetting length = new NumberSetting("Length", 3.5, 0, 10, 0.1); private final ColorSetting color = new ColorSetting("Color", new Color(255, 255, 255)); - private final ColorSetting outlineColor = new ColorSetting("OutlineColor", new Color(161, 161, 161), () -> outline.getValue()); + private final ColorSetting outlineColor = new ColorSetting("OutlineColor", new Color(161, 161, 161), outline::getValue); private final ColorSetting enemyColor = new ColorSetting("Enemy", new Color(255, 55, 50)); private final ColorSetting friendColor = new ColorSetting("Friend", new Color(20, 255, 55)); @@ -104,9 +104,11 @@ private void drawOutlineRect(float x, float y, float width, float height, float } private boolean isFriend(Object entity) { + if (entity instanceof EntityAnimal) + return true; if (entity instanceof EntityPlayer) { EntityPlayer player = (EntityPlayer) entity; - return isTeammate(player) || entity instanceof EntityAnimal; + return isTeammate(player); } return false; } diff --git a/shared/java/top/fpsmaster/features/impl/render/DamageIndicator.java b/shared/java/top/fpsmaster/features/impl/render/DamageIndicator.java index c64aca30..94ea4f73 100644 --- a/shared/java/top/fpsmaster/features/impl/render/DamageIndicator.java +++ b/shared/java/top/fpsmaster/features/impl/render/DamageIndicator.java @@ -116,18 +116,18 @@ public void doRender(Damage indicator) { GL11.glNormal3f(1.0f, 1.0f, 1.0f); GL11.glPopMatrix(); } -} -class Damage { - float damage; - float x, y, z; - float animation; + private static class Damage { + float damage; + float x, y, z; + float animation; - public Damage(float damage, float x, float y, float z, float animation) { - this.damage = damage; - this.x = x; - this.y = y; - this.z = z; - this.animation = animation; + public Damage(float damage, float x, float y, float z, float animation) { + this.damage = damage; + this.x = x; + this.y = y; + this.z = z; + this.animation = animation; + } } } \ No newline at end of file diff --git a/shared/java/top/fpsmaster/features/impl/utility/SkinChanger.java b/shared/java/top/fpsmaster/features/impl/utility/SkinChanger.java index 9cceace2..356fa3fc 100644 --- a/shared/java/top/fpsmaster/features/impl/utility/SkinChanger.java +++ b/shared/java/top/fpsmaster/features/impl/utility/SkinChanger.java @@ -73,13 +73,11 @@ public void update() { @Override public void onDisable() { super.onDisable(); - FPSMaster.async.runnable(() -> { - ProviderManager.skinProvider.updateSkin( - ProviderManager.mcProvider.getPlayer().getName(), - ProviderManager.mcProvider.getPlayer().getUniqueID().toString(), - ProviderManager.mcProvider.getPlayer().getName() - ); - }); + FPSMaster.async.runnable(() -> ProviderManager.skinProvider.updateSkin( + ProviderManager.mcProvider.getPlayer().getName(), + ProviderManager.mcProvider.getPlayer().getUniqueID().toString(), + ProviderManager.mcProvider.getPlayer().getName() + )); using = false; } } \ No newline at end of file diff --git a/shared/java/top/fpsmaster/font/EnhancedFontRenderer.java b/shared/java/top/fpsmaster/font/EnhancedFontRenderer.java index c0b1e138..4a3c7d38 100644 --- a/shared/java/top/fpsmaster/font/EnhancedFontRenderer.java +++ b/shared/java/top/fpsmaster/font/EnhancedFontRenderer.java @@ -14,7 +14,6 @@ public final class EnhancedFontRenderer { private final Map stringWidthCache = new HashMap<>(); private final Queue glRemoval = new ConcurrentLinkedQueue<>(); private final Map stringCache = new HashMap<>(); - private final int maxCacheSize = 5000; public EnhancedFontRenderer() { instances.add(this); @@ -46,6 +45,7 @@ public CachedString get(StringHash key) { } public void cache(StringHash key, CachedString value) { + int maxCacheSize = 5000; if (stringCache.size() >= maxCacheSize) { // 如果缓存达到最大限制,进行清理 stringCache.clear(); diff --git a/shared/java/top/fpsmaster/font/FontRendererHook.java b/shared/java/top/fpsmaster/font/FontRendererHook.java index 96c0d3d3..9398c815 100644 --- a/shared/java/top/fpsmaster/font/FontRendererHook.java +++ b/shared/java/top/fpsmaster/font/FontRendererHook.java @@ -184,7 +184,7 @@ public boolean renderStringAtPos(String text, boolean shadow) { return true; } - int list = 0; + int list; textureState.textureName = glTextureId; GlStateManager.resetColor(); list = enhancedFontRenderer.getGlList(); @@ -324,7 +324,7 @@ public boolean renderStringAtPos(String text, boolean shadow) { } endDrawing(); - final boolean hasStyle = underline.size() > 0 || strikethrough.size() > 0; + final boolean hasStyle = !underline.isEmpty() || !strikethrough.isEmpty(); if (hasStyle) { GlStateManager.disableTexture2D(); @@ -556,7 +556,7 @@ public RenderPair(float posX, float width, float red, float green, float blue, f } } - class Pair { + static class Pair { private final A first; private final B second; diff --git a/shared/java/top/fpsmaster/font/impl/GlyphCache.java b/shared/java/top/fpsmaster/font/impl/GlyphCache.java index 1f9efcc6..ae969fa3 100644 --- a/shared/java/top/fpsmaster/font/impl/GlyphCache.java +++ b/shared/java/top/fpsmaster/font/impl/GlyphCache.java @@ -383,7 +383,10 @@ void cacheGlyphs(Font font, char[] text, int start, int limit, int layoutFlags) vectorBounds = vector.getPixelBounds(fontRenderContext, 0, 0); /* Enlage the stringImage if it is too small to store the entire rendered string */ - if (stringImage == null || vectorBounds.width > stringImage.getWidth() || vectorBounds.height > stringImage.getHeight()) { + if (stringImage == null) + return; + + if (vectorBounds.width > stringImage.getWidth() || vectorBounds.height > stringImage.getHeight()) { int width = Math.max(vectorBounds.width, stringImage.getWidth()); int height = Math.max(vectorBounds.height, stringImage.getHeight()); allocateStringImage(width, height); diff --git a/shared/java/top/fpsmaster/font/impl/StringCache.java b/shared/java/top/fpsmaster/font/impl/StringCache.java index e4f77d8b..c13c70f9 100644 --- a/shared/java/top/fpsmaster/font/impl/StringCache.java +++ b/shared/java/top/fpsmaster/font/impl/StringCache.java @@ -553,7 +553,7 @@ public int renderString(String str, float startX, float startY, int initialColor * color code takes effect. */ while (colorIndex < entry.colors.length && entry.glyphs[glyphIndex].stringIndex >= entry.colors[colorIndex].stringIndex) { - color = applyColorCode(entry.colors[colorIndex].colorCode, initialColor, shadowFlag); + applyColorCode(entry.colors[colorIndex].colorCode, initialColor, shadowFlag); renderStyle = entry.colors[colorIndex].renderStyle; colorIndex++; } diff --git a/shared/java/top/fpsmaster/modules/account/AccountManager.java b/shared/java/top/fpsmaster/modules/account/AccountManager.java index e84787d1..0b298c01 100644 --- a/shared/java/top/fpsmaster/modules/account/AccountManager.java +++ b/shared/java/top/fpsmaster/modules/account/AccountManager.java @@ -81,7 +81,7 @@ public static JsonObject login(String username, String password) throws AccountE JsonObject body = new JsonObject(); body.addProperty("username", username); body.addProperty("password", password); - HttpRequest.HttpResponseResult s = null; + HttpRequest.HttpResponseResult s; try { s = HttpRequest.post(FPSMaster.SERVICE_API + "/api/auth/login", body.toString()); } catch (IOException e) { diff --git a/shared/java/top/fpsmaster/modules/logger/ClientLogger.java b/shared/java/top/fpsmaster/modules/logger/ClientLogger.java index 522517f1..c1de8483 100644 --- a/shared/java/top/fpsmaster/modules/logger/ClientLogger.java +++ b/shared/java/top/fpsmaster/modules/logger/ClientLogger.java @@ -31,10 +31,10 @@ public static void trace(String s) { } public static void info(String from, String s) { - logger.info(from + " -> " + s); + logger.info("{} -> {}", from, s); } public static void error(String from, String s) { - logger.error(from + " -> " + s); + logger.error("{} -> {}", from, s); } } diff --git a/shared/java/top/fpsmaster/modules/lua/LuaManager.java b/shared/java/top/fpsmaster/modules/lua/LuaManager.java index 087e731c..932634d8 100644 --- a/shared/java/top/fpsmaster/modules/lua/LuaManager.java +++ b/shared/java/top/fpsmaster/modules/lua/LuaManager.java @@ -219,20 +219,24 @@ public static void reload() throws FileException { unloadLua(script); } - for (File luaFile : luas) { - RawLua rawLua = new RawLua(luaFile.getName(), FileUtils.readAbsoluteFile(luaFile.getAbsolutePath())); - loadLua(rawLua); + if (luas != null) { + for (File luaFile : luas) { + RawLua rawLua = new RawLua(luaFile.getName(), FileUtils.readAbsoluteFile(luaFile.getAbsolutePath())); + loadLua(rawLua); + } } } public static void hotswap() throws FileException { ArrayList newRawLuaList = new ArrayList<>(); File[] luas = FileUtils.plugins.listFiles(); - for (File luaFile : luas) { - String luaName = luaFile.getName(); - if (luaName.endsWith(".lua")) { - String luaContent = FileUtils.readAbsoluteFile(luaFile.getAbsolutePath()); - newRawLuaList.add(new RawLua(luaName, luaContent)); + if (luas != null) { + for (File luaFile : luas) { + String luaName = luaFile.getName(); + if (luaName.endsWith(".lua")) { + String luaContent = FileUtils.readAbsoluteFile(luaFile.getAbsolutePath()); + newRawLuaList.add(new RawLua(luaName, luaContent)); + } } } diff --git a/shared/java/top/fpsmaster/modules/music/MusicPlayer.java b/shared/java/top/fpsmaster/modules/music/MusicPlayer.java index 0b34253a..edbdc63e 100644 --- a/shared/java/top/fpsmaster/modules/music/MusicPlayer.java +++ b/shared/java/top/fpsmaster/modules/music/MusicPlayer.java @@ -59,9 +59,7 @@ public static void playFile(String path) { playThread = new Thread(() -> { try { JLayerHelper.playWAV(path.replace(".mp3", ".wav")); - } catch (IOException e) { - throw new RuntimeException(e); - } catch (LineUnavailableException e) { + } catch (IOException | LineUnavailableException e) { throw new RuntimeException(e); } setVolume(v); diff --git a/shared/java/top/fpsmaster/modules/music/netease/deserialize/MusicWrapper.java b/shared/java/top/fpsmaster/modules/music/netease/deserialize/MusicWrapper.java index 31a953d6..5a8d2b21 100644 --- a/shared/java/top/fpsmaster/modules/music/netease/deserialize/MusicWrapper.java +++ b/shared/java/top/fpsmaster/modules/music/netease/deserialize/MusicWrapper.java @@ -50,9 +50,8 @@ private static PlayList getSongsFromList(String id) { long id1 = songObject.get("id").getAsLong(); String name = songObject.get("name").getAsString(); StringBuilder artists = new StringBuilder(); - Iterator artistIterator = songObject.getAsJsonArray("ar").iterator(); - while (artistIterator.hasNext()) { - artists.append(artistIterator.next().getAsJsonObject().get("name").getAsString()); + for (JsonElement jsonElement : songObject.getAsJsonArray("ar")) { + artists.append(jsonElement.getAsJsonObject().get("name").getAsString()); } String picUrl = songObject.getAsJsonObject("al").get("picUrl").getAsString(); playList.add(new Music(id1, name, artists.toString(), picUrl)); @@ -73,9 +72,8 @@ public static PlayList getSongsFromDaily() { long id1 = songObject.get("id").getAsLong(); String name = songObject.get("name").getAsString(); StringBuilder artists = new StringBuilder(); - Iterator artistIterator = songObject.getAsJsonArray("ar").iterator(); - while (artistIterator.hasNext()) { - artists.append(artistIterator.next().getAsJsonObject().get("name").getAsString()); + for (JsonElement jsonElement : songObject.getAsJsonArray("ar")) { + artists.append(jsonElement.getAsJsonObject().get("name").getAsString()); } String picUrl = songObject.getAsJsonObject("al").get("picUrl").getAsString(); playList.add(new Music(id1, name, artists.toString(), picUrl)); @@ -143,7 +141,7 @@ private static Lyrics parseLyrics2(String str) { private static Lyrics parseLyrics(String str) { Lyrics lyrics = new Lyrics(); - str = str.replace("\n", System.lineSeparator()).replace("\"", "\""); + str = str.replace("\n", System.lineSeparator()); for (String s : str.split(System.lineSeparator())) { if (s.startsWith("[")) { Line line = new Line(); diff --git a/shared/java/top/fpsmaster/ui/click/modules/ModuleRenderer.java b/shared/java/top/fpsmaster/ui/click/modules/ModuleRenderer.java index ce890806..311d90fb 100644 --- a/shared/java/top/fpsmaster/ui/click/modules/ModuleRenderer.java +++ b/shared/java/top/fpsmaster/ui/click/modules/ModuleRenderer.java @@ -5,7 +5,6 @@ import top.fpsmaster.FPSMaster; import top.fpsmaster.features.manager.Category; import top.fpsmaster.features.manager.Module; -import top.fpsmaster.features.settings.Setting; import top.fpsmaster.features.settings.impl.*; import top.fpsmaster.modules.lua.LuaModule; import top.fpsmaster.ui.click.MainPanel; @@ -18,7 +17,6 @@ import java.awt.*; import java.util.ArrayList; import java.util.Locale; -import java.util.function.Consumer; public class ModuleRenderer extends ValueRender { ArrayList> settingsRenderers = new ArrayList<>(); @@ -33,22 +31,19 @@ public class ModuleRenderer extends ValueRender { public ModuleRenderer(Module mod) { this.mod = mod; content = new ColorAnimation(mod.isEnabled() ? new Color(66, 66, 66) : new Color(40, 40, 40)); - mod.settings.forEach(new Consumer>() { - @Override - public void accept(Setting setting) { - if (setting instanceof BooleanSetting) { - settingsRenderers.add(new BooleanSettingRender(mod, (BooleanSetting) setting)); - } else if (setting instanceof ModeSetting) { - settingsRenderers.add(new ModeSettingRender(mod, (ModeSetting) setting)); - } else if (setting instanceof TextSetting) { - settingsRenderers.add(new TextSettingRender(mod, (TextSetting) setting)); - } else if (setting instanceof NumberSetting) { - settingsRenderers.add(new NumberSettingRender(mod, (NumberSetting) setting)); - } else if (setting instanceof ColorSetting) { - settingsRenderers.add(new ColorSettingRender(mod, (ColorSetting) setting)); - } else if (setting instanceof BindSetting) { - settingsRenderers.add(new BindSettingRender(mod, (BindSetting) setting)); - } + mod.settings.forEach(setting -> { + if (setting instanceof BooleanSetting) { + settingsRenderers.add(new BooleanSettingRender(mod, (BooleanSetting) setting)); + } else if (setting instanceof ModeSetting) { + settingsRenderers.add(new ModeSettingRender(mod, (ModeSetting) setting)); + } else if (setting instanceof TextSetting) { + settingsRenderers.add(new TextSettingRender(mod, (TextSetting) setting)); + } else if (setting instanceof NumberSetting) { + settingsRenderers.add(new NumberSettingRender(mod, (NumberSetting) setting)); + } else if (setting instanceof ColorSetting) { + settingsRenderers.add(new ColorSettingRender(mod, (ColorSetting) setting)); + } else if (setting instanceof BindSetting) { + settingsRenderers.add(new BindSettingRender(mod, (BindSetting) setting)); } }); } diff --git a/shared/java/top/fpsmaster/ui/click/modules/impl/NumberSettingRender.java b/shared/java/top/fpsmaster/ui/click/modules/impl/NumberSettingRender.java index c0169daa..b4c485e6 100644 --- a/shared/java/top/fpsmaster/ui/click/modules/impl/NumberSettingRender.java +++ b/shared/java/top/fpsmaster/ui/click/modules/impl/NumberSettingRender.java @@ -15,7 +15,6 @@ public class NumberSettingRender extends SettingRender { // animation private float aWidth = 0f; - private boolean dragging = false; public NumberSettingRender(Module mod, NumberSetting setting) { super(setting); @@ -59,7 +58,6 @@ public void mouseClick(float x, float y, float width, float height, float mouseX if (Render2DUtils.isHovered(x + 16 + fw, y, 160f, height, (int) mouseX, (int) mouseY) && Mouse.isButtonDown(0)) { if (btn == 0 && MainPanel.dragLock.equals("null")) { MainPanel.dragLock = mod.name + setting.name + 4; - dragging = true; } } } diff --git a/shared/java/top/fpsmaster/ui/click/music/MusicPanel.java b/shared/java/top/fpsmaster/ui/click/music/MusicPanel.java index fbe28250..0de604c3 100644 --- a/shared/java/top/fpsmaster/ui/click/music/MusicPanel.java +++ b/shared/java/top/fpsmaster/ui/click/music/MusicPanel.java @@ -226,15 +226,10 @@ public static void draw(float x, float y, float width, float height, int mouseX, Render2DUtils.drawOptimizedRoundedRect(x + 30, dY.get() + 10, 20f, 20f, new Color(200, 200, 200, 255)); } } - if (MusicPlayer.playList.current == i) { - FPSMaster.fontManager.s16.drawString(music.name + " " + music.author, x + 60, dY.get() + 10, new Color(234, 234, 234).getRGB()); - FPSMaster.fontManager.s16.drawString(music.author, x + 60, dY.get() + 20, new Color(162, 162, 162).getRGB()); - } else { - FPSMaster.fontManager.s16.drawString(music.name + " " + music.author, x + 60, dY.get() + 10, new Color(234, 234, 234).getRGB()); - FPSMaster.fontManager.s16.drawString(music.author, x + 60, dY.get() + 20, new Color(162, 162, 162).getRGB()); - } - dY.updateAndGet(v -> new Float(v + 40f)); - musicHeight.updateAndGet(v -> new Float(v + 40f)); + FPSMaster.fontManager.s16.drawString(music.name + " " + music.author, x + 60, dY.get() + 10, new Color(234, 234, 234).getRGB()); + FPSMaster.fontManager.s16.drawString(music.author, x + 60, dY.get() + 20, new Color(162, 162, 162).getRGB()); + dY.updateAndGet(v -> v + 40f); + musicHeight.updateAndGet(v -> v + 40f); } container.setHeight(musicHeight.get()); }); diff --git a/shared/java/top/fpsmaster/ui/common/TextField.java b/shared/java/top/fpsmaster/ui/common/TextField.java index 768764d6..4727e28c 100644 --- a/shared/java/top/fpsmaster/ui/common/TextField.java +++ b/shared/java/top/fpsmaster/ui/common/TextField.java @@ -12,6 +12,7 @@ import top.fpsmaster.wrapper.renderEngine.bufferbuilder.WrapperBufferBuilder; import java.awt.*; +import java.util.Arrays; import java.util.function.Predicate; public class TextField extends Gui { @@ -29,7 +30,7 @@ public class TextField extends Gui { * Has the current text being edited on the textbox. */ public String text = ""; - private int maxStringLength = 32; + private int maxStringLength; private int cursorCounter; /** @@ -144,7 +145,7 @@ public void writeText(String p_146191_1_) { int i = Math.min(this.cursorPosition, this.selectionEnd); int j = Math.max(this.cursorPosition, this.selectionEnd); int k = this.maxStringLength - this.text.length() - (i - j); - int l = 0; + int l; if (!this.text.isEmpty()) { s = s + this.text.substring(0, i); @@ -441,8 +442,12 @@ public void drawTextBox(float x, float y, float width, float height) { int j = this.cursorPosition - this.lineScrollOffset; int k = this.selectionEnd - this.lineScrollOffset; String s = this.fontRendererInstance.trimStringToWidth(this.text.substring(this.lineScrollOffset), this.getWidth()); - if (hideContent) - s = s.replaceAll(".", "*"); + if (hideContent) { + char[] stars = new char[s.length()]; + Arrays.fill(stars, '*'); + s = new String(stars); + } + boolean flag = j >= 0 && j <= s.length(); boolean isFocus = this.isFocused && this.cursorCounter / 6 % 2 == 0 && flag; float l = this.xPosition + 4; diff --git a/shared/java/top/fpsmaster/ui/custom/impl/PotionDisplayComponent.java b/shared/java/top/fpsmaster/ui/custom/impl/PotionDisplayComponent.java index d72ff46a..e9261f90 100644 --- a/shared/java/top/fpsmaster/ui/custom/impl/PotionDisplayComponent.java +++ b/shared/java/top/fpsmaster/ui/custom/impl/PotionDisplayComponent.java @@ -50,7 +50,7 @@ public void draw(float x, float y) { 0, 0, (potion % 8 * 18) + 1, - (198 + potion / 8 * 18) + 1, + (198 + (float) potion / 8 * 18) + 1, 16, 16, 256f, diff --git a/shared/java/top/fpsmaster/ui/devspace/DevSpace.java b/shared/java/top/fpsmaster/ui/devspace/DevSpace.java index 8bf83714..473904c1 100644 --- a/shared/java/top/fpsmaster/ui/devspace/DevSpace.java +++ b/shared/java/top/fpsmaster/ui/devspace/DevSpace.java @@ -166,9 +166,7 @@ private void drawCodeEditorArea(int leftPanelWidth, int mouseX, int mouseY) { GL11.glEnable(GL11.GL_SCISSOR_TEST); Render2DUtils.doGlScissor(x + Math.max((int) (width * 0.2), 100) + 12, y + 36, (width-leftPanelWidth) - 15, height - 42, scaleFactor); } - codeEditor.draw(x + Math.max((int) (width * 0.2), 100) + 12, y + 36, (width-leftPanelWidth) - 17, height - 42, mouseX, mouseY, () -> { - drawCodeEditor(mouseX, mouseY); - }); + codeEditor.draw(x + Math.max((int) (width * 0.2), 100) + 12, y + 36, (width-leftPanelWidth) - 17, height - 42, mouseX, mouseY, () -> drawCodeEditor(mouseX, mouseY)); GL11.glDisable(GL11.GL_SCISSOR_TEST); } @@ -437,7 +435,7 @@ private void ensureCodesInitialized() { private void drawCodeEditor(int mouseX, int mouseY) { int left = Math.max((int) (width * 0.2), 100); ensureCodesInitialized(); - if (selectedLua == -1 || LuaManager.scripts.size() > 0) + if (selectedLua == -1 || !LuaManager.scripts.isEmpty()) selectedLua = 0; if (getCurrentScript() != null) { // handle keyboard diff --git a/shared/java/top/fpsmaster/ui/devspace/map/expressions/FunctionCallExpressionComponent.java b/shared/java/top/fpsmaster/ui/devspace/map/expressions/FunctionCallExpressionComponent.java index 310eeac5..2ca62754 100644 --- a/shared/java/top/fpsmaster/ui/devspace/map/expressions/FunctionCallExpressionComponent.java +++ b/shared/java/top/fpsmaster/ui/devspace/map/expressions/FunctionCallExpressionComponent.java @@ -38,7 +38,7 @@ public void draw(int x, int y, int mouseX, int mouseY) { } else { FPSMaster.fontManager.s16.drawString(", ", x + 1 + argumentX, y + 2, -1); } - } else { +// } else { // arg.draw(x + 10, y + height, mouseX, mouseY); // height += arg.height; } diff --git a/shared/java/top/fpsmaster/ui/mc/GuiMultiplayer.java b/shared/java/top/fpsmaster/ui/mc/GuiMultiplayer.java index 4acc6753..ade03187 100644 --- a/shared/java/top/fpsmaster/ui/mc/GuiMultiplayer.java +++ b/shared/java/top/fpsmaster/ui/mc/GuiMultiplayer.java @@ -82,12 +82,8 @@ public class GuiMultiplayer extends ScaledGuiScreen { this.mc.displayGuiScreen(guiyesno); } }, new Color(0, 0, 0, 140), new Color(113, 127, 254)); - GuiButton refresh = new GuiButton("刷新", () -> { - mc.displayGuiScreen(new GuiMultiplayer()); - }, new Color(0, 0, 0, 140), new Color(113, 127, 254)); - GuiButton back = new GuiButton("返回", () -> { - mc.displayGuiScreen(new MainMenu()); - }, new Color(0, 0, 0, 140), new Color(113, 127, 254)); + GuiButton refresh = new GuiButton("刷新", () -> mc.displayGuiScreen(new GuiMultiplayer()), new Color(0, 0, 0, 140), new Color(113, 127, 254)); + GuiButton back = new GuiButton("返回", () -> mc.displayGuiScreen(new MainMenu()), new Color(0, 0, 0, 140), new Color(113, 127, 254)); @Override @@ -103,16 +99,14 @@ public void initGui() { if (serverListRecommended.isEmpty()) { ClientThreadPool clientThreadPool = new ClientThreadPool(100); clientThreadPool.runnable(() -> { - String s = null; + String s; try { s = HttpRequest.get("https://service.fpsmaster.top/api/client/servers").getBody(); } catch (IOException e) { throw new RuntimeException(e); } JsonObject jsonObject = gson.fromJson(s, JsonObject.class); - jsonObject.get("data").getAsJsonArray().forEach(e -> { - serverListRecommended.add(new ServerListEntry(this, new ServerData(e.getAsJsonObject().get("name").getAsString() + " - " + e.getAsJsonObject().get("description").getAsString(), e.getAsJsonObject().get("address").getAsString(), false))); - }); + jsonObject.get("data").getAsJsonArray().forEach(e -> serverListRecommended.add(new ServerListEntry(this, new ServerData(e.getAsJsonObject().get("name").getAsString() + " - " + e.getAsJsonObject().get("description").getAsString(), e.getAsJsonObject().get("address").getAsString(), false)))); }); } } diff --git a/shared/java/top/fpsmaster/ui/mc/ServerListEntry.java b/shared/java/top/fpsmaster/ui/mc/ServerListEntry.java index 9da77721..d36bbbe7 100644 --- a/shared/java/top/fpsmaster/ui/mc/ServerListEntry.java +++ b/shared/java/top/fpsmaster/ui/mc/ServerListEntry.java @@ -110,7 +110,6 @@ public void drawEntry(int slotIndex, int x, int y, int listWidth, int slotHeight if (flag2) { l = 5; s1 = flag ? "Client out of date!" : "Server out of date!"; - s = this.server.playerList; } else if (this.server.field_78841_f && this.server.pingToServer != -2L) { if (this.server.pingToServer < 0L) { l = 5; @@ -130,7 +129,6 @@ public void drawEntry(int slotIndex, int x, int y, int listWidth, int slotHeight s1 = "(no connection)"; } else { s1 = this.server.pingToServer + "ms"; - s = this.server.playerList; } } else { k = 1; @@ -233,7 +231,7 @@ private void prepareServerIcon() { Validate.validState(bufferedimage.getHeight() == 64, "Must be 64 pixels high"); break label80; } catch (Throwable throwable) { - logger.error("Invalid icon for server " + this.server.serverName + " (" + this.server.serverIP + ")", throwable); + logger.error("Invalid icon for server {} ({})", this.server.serverName, this.server.serverIP, throwable); this.server.setBase64EncodedIconData(null); } finally { bytebuf.release(); diff --git a/shared/java/top/fpsmaster/ui/screens/mainmenu/MainMenu.java b/shared/java/top/fpsmaster/ui/screens/mainmenu/MainMenu.java index 61722b15..cac5d700 100644 --- a/shared/java/top/fpsmaster/ui/screens/mainmenu/MainMenu.java +++ b/shared/java/top/fpsmaster/ui/screens/mainmenu/MainMenu.java @@ -35,15 +35,9 @@ public class MainMenu extends ScaledGuiScreen { public MainMenu() { - singlePlayer = new MenuButton("mainmenu.single", () -> { - ProviderManager.mainmenuProvider.showSinglePlayer(this); - }); - multiPlayer = new MenuButton("mainmenu.multi", () -> { - mc.displayGuiScreen(new GuiMultiplayer()); - }); - options = new MenuButton("mainmenu.settings", () -> { - mc.displayGuiScreen(new GuiOptions(this, mc.gameSettings)); - }); + singlePlayer = new MenuButton("mainmenu.single", () -> ProviderManager.mainmenuProvider.showSinglePlayer(this)); + multiPlayer = new MenuButton("mainmenu.multi", () -> mc.displayGuiScreen(new GuiMultiplayer())); + options = new MenuButton("mainmenu.settings", () -> mc.displayGuiScreen(new GuiOptions(this, mc.gameSettings))); exit = new MenuButton("X", () -> mc.shutdown()); } diff --git a/shared/java/top/fpsmaster/ui/screens/oobe/impls/Login.java b/shared/java/top/fpsmaster/ui/screens/oobe/impls/Login.java index 44010d2d..2d939ef8 100644 --- a/shared/java/top/fpsmaster/ui/screens/oobe/impls/Login.java +++ b/shared/java/top/fpsmaster/ui/screens/oobe/impls/Login.java @@ -48,7 +48,9 @@ public Login(boolean isOOBE) { FPSMaster.accountManager.setToken(login.get("data").getAsJsonObject().get("token").getAsString()); } try { - FileUtils.saveTempValue("token", FPSMaster.accountManager.getToken()); + if (FPSMaster.accountManager != null) { + FileUtils.saveTempValue("token", FPSMaster.accountManager.getToken()); + } } catch (FileException e) { ExceptionHandler.handleFileException(e, "无法保存登录令牌"); } diff --git a/shared/java/top/fpsmaster/utils/Utility.java b/shared/java/top/fpsmaster/utils/Utility.java index 93b73ccb..3ac575a9 100644 --- a/shared/java/top/fpsmaster/utils/Utility.java +++ b/shared/java/top/fpsmaster/utils/Utility.java @@ -36,12 +36,7 @@ public static void sendClientNotify(String msg) { public static void sendClientDebug(String msg) { if (DevMode.INSTACE.dev) { - String msg1 = "§9[FPSMaster]§r " + msg; - if (ProviderManager.mcProvider.getWorld() != null) { - ProviderManager.mcProvider.printChatMessage(ProviderManager.utilityProvider.makeChatComponent(msg1)); - } else { - messages.add(msg1); - } + sendClientNotify(msg); } } diff --git a/shared/java/top/fpsmaster/utils/awt/AWTUtils.java b/shared/java/top/fpsmaster/utils/awt/AWTUtils.java index 536194a6..1d4dcd32 100644 --- a/shared/java/top/fpsmaster/utils/awt/AWTUtils.java +++ b/shared/java/top/fpsmaster/utils/awt/AWTUtils.java @@ -14,78 +14,6 @@ public class AWTUtils { private static final HashMap generated = new HashMap<>(); private static final HashMap generatedFull = new HashMap<>(); - public static ResourceLocation generateRoundImage(int width, int height, int radius, Color borderColor, int borderWidth) { - if (width <= 0 || height <= 0 || radius < 0 || borderWidth < 0) { - throw new IllegalArgumentException("Width, height must be positive; radius and borderWidth must be non-negative"); - } - - String key = width + "/" + height + "/" + radius + "/" + borderWidth + "/" + borderColor.getRGB(); - return generatedFull.computeIfAbsent(key, r -> { - int scaledWidth = width * 2; - int scaledHeight = height * 2; - int scaledRadius = radius * 2; - int scaledBorderWidth = borderWidth * 2; - - try { - BufferedImage bufferedImage = new BufferedImage(scaledWidth, scaledHeight, BufferedImage.TYPE_INT_ARGB); - Graphics2D graphics2D = bufferedImage.createGraphics(); - - graphics2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); - - // Clear with transparent background - graphics2D.setColor(new Color(0, 0, 0, 0)); - graphics2D.fillRect(0, 0, scaledWidth, scaledHeight); - - graphics2D.setComposite(AlphaComposite.SrcOver); - - // Draw the border if borderWidth > 0 - if (borderWidth > 0 && borderColor != null) { - graphics2D.setColor(borderColor); - RoundRectangle2D borderRect = new RoundRectangle2D.Float( - 0, - 0, - scaledWidth, - scaledHeight, - scaledRadius, - scaledRadius - ); - graphics2D.fill(borderRect); - } - - // Draw the inner white rectangle (accounting for border) - int innerX = scaledBorderWidth; - int innerY = scaledBorderWidth; - int innerWidth = scaledWidth - (scaledBorderWidth * 2); - int innerHeight = scaledHeight - (scaledBorderWidth * 2); - int innerRadius = Math.max(0, scaledRadius - (scaledBorderWidth * 2)); - - graphics2D.setColor(Color.WHITE); - RoundRectangle2D innerRect = new RoundRectangle2D.Float( - innerX, - innerY, - innerWidth, - innerHeight, - innerRadius, - innerRadius - ); - graphics2D.fill(innerRect); - - Minecraft mc = Minecraft.getMinecraft(); - if (mc == null || mc.getTextureManager() == null) { - return null; - } - graphics2D.dispose(); - - return mc.getTextureManager() - .getDynamicTextureLocation(r + "_full", new DynamicTexture(bufferedImage)); - } catch (Exception e) { - ClientLogger.error("An error occurred while generating round texture: " + r); - e.printStackTrace(); - return null; - } - }); - } - public static ResourceLocation generateRoundImage(int width, int height, int radius) { if (width <= 0 || height <= 0 || radius < 0) { throw new IllegalArgumentException("Width, height must be positive and radius must be non-negative"); diff --git a/shared/java/top/fpsmaster/utils/render/Render2DUtils.java b/shared/java/top/fpsmaster/utils/render/Render2DUtils.java index 4bd4c3ba..d891d304 100644 --- a/shared/java/top/fpsmaster/utils/render/Render2DUtils.java +++ b/shared/java/top/fpsmaster/utils/render/Render2DUtils.java @@ -275,15 +275,13 @@ public static void drawBlurArea(float x, float y, float width, float height, int } public static void drawBackground(int guiWidth, int guiHeight, int mouseX, int mouseY, float partialTicks, int zLevel) { - ResourceLocation textureLocation = null; + ResourceLocation textureLocation; if (FileUtils.hasBackground) { - if (textureLocation == null) { - textureLocation = new ResourceLocation("fpsmaster/gui/background.png"); - File file = FileUtils.background; - TextureManager textureManager = Minecraft.getMinecraft().getTextureManager(); - ThreadDownloadImageData textureArt = new ThreadDownloadImageData(file, null, null, null); - textureManager.loadTexture(textureLocation, textureArt); - } + textureLocation = new ResourceLocation("fpsmaster/gui/background.png"); + File file = FileUtils.background; + TextureManager textureManager = Minecraft.getMinecraft().getTextureManager(); + ThreadDownloadImageData textureArt = new ThreadDownloadImageData(file, null, null, null); + textureManager.loadTexture(textureLocation, textureArt); Render2DUtils.drawImage(textureLocation, 0f, 0f, guiWidth, guiHeight, -1); Render2DUtils.drawRect(0f, 0f, guiWidth, guiHeight, new Color(22, 22, 22, 50)); } else { diff --git a/shared/java/top/fpsmaster/utils/render/StencilUtil.java b/shared/java/top/fpsmaster/utils/render/StencilUtil.java index eb0ff905..698f4055 100644 --- a/shared/java/top/fpsmaster/utils/render/StencilUtil.java +++ b/shared/java/top/fpsmaster/utils/render/StencilUtil.java @@ -29,16 +29,7 @@ public static void end() { public static void draw(Runnable start, Runnable end) { GL11.glEnable(GL11.GL_STENCIL_TEST); - Minecraft mc = Minecraft.getMinecraft(); - mc.getFramebuffer().bindFramebuffer(false); - if (mc.getFramebuffer().depthBuffer > -1) { - setupFBO(mc.getFramebuffer()); - mc.getFramebuffer().depthBuffer = -1; - } - GL11.glClear(GL11.GL_STENCIL_BUFFER_BIT); - GL11.glStencilFunc(GL11.GL_ALWAYS, 1, 0xFF); - GL11.glStencilOp(GL11.GL_REPLACE, GL11.GL_REPLACE, GL11.GL_REPLACE); - GL11.glColorMask(false, false, false, false); + start(); start.run(); GL11.glStencilFunc(GL11.GL_EQUAL, 1, 0xFF); GL11.glStencilOp(GL11.GL_KEEP, GL11.GL_KEEP, GL11.GL_KEEP); diff --git a/shared/java/top/fpsmaster/utils/thirdparty/openai/OpenAI.java b/shared/java/top/fpsmaster/utils/thirdparty/openai/OpenAI.java index fed737b5..6f14c6c0 100644 --- a/shared/java/top/fpsmaster/utils/thirdparty/openai/OpenAI.java +++ b/shared/java/top/fpsmaster/utils/thirdparty/openai/OpenAI.java @@ -3,6 +3,7 @@ import com.google.gson.JsonArray; import com.google.gson.JsonObject; import com.google.gson.JsonParser; +import org.jetbrains.annotations.NotNull; import top.fpsmaster.FPSMaster; import top.fpsmaster.modules.logger.ClientLogger; import top.fpsmaster.utils.os.HttpRequest; @@ -52,6 +53,24 @@ public String requestNewAnswer(String question, JsonArray msgs) { } public String requestNewAnswer(String question) { + JsonObject body = getJsonObject(question); + + Map hashMap = new HashMap<>(); + hashMap.put("Content-Type", "application/json"); + hashMap.put("Authorization", "Bearer " + openAiKey); + + String text; + try { + text = HttpRequest.postJson(baseUrl + "/chat/completions", body, hashMap).getBody(); + } catch (Exception e) { + ClientLogger.error("Translator", e.toString()); + return ""; + } + + return getString(text); + } + + private @NotNull JsonObject getJsonObject(String question) { JsonObject systemRole = new JsonObject(); systemRole.addProperty("role", "system"); systemRole.addProperty("content", prompt); @@ -67,20 +86,7 @@ public String requestNewAnswer(String question) { JsonObject body = new JsonObject(); body.addProperty("model", model); body.add("messages", messages); - - Map hashMap = new HashMap<>(); - hashMap.put("Content-Type", "application/json"); - hashMap.put("Authorization", "Bearer " + openAiKey); - - String text; - try { - text = HttpRequest.postJson(baseUrl + "/chat/completions", body, hashMap).getBody(); - } catch (Exception e) { - ClientLogger.error("Translator", e.toString()); - return ""; - } - - return getString(text); + return body; } private String getString(String response) { diff --git a/shared/java/top/fpsmaster/utils/thirdparty/rawinput/RawInputMod.java b/shared/java/top/fpsmaster/utils/thirdparty/rawinput/RawInputMod.java index 01abb5c6..c4c10b95 100644 --- a/shared/java/top/fpsmaster/utils/thirdparty/rawinput/RawInputMod.java +++ b/shared/java/top/fpsmaster/utils/thirdparty/rawinput/RawInputMod.java @@ -15,11 +15,11 @@ public class RawInputMod { public static Controller[] controllers; public static int dx = 0; public static int dy = 0; - private String environment; public void start() { try { Minecraft.getMinecraft().mouseHelper = new RawMouseHelper(); + String environment; if (checkLibrary("jinput-dx8")){ environment = "DirectInputEnvironmentPlugin"; }else if (checkLibrary("jinput-raw")){ diff --git a/shared/java/top/fpsmaster/websocket/data/message/Packet.java b/shared/java/top/fpsmaster/websocket/data/message/Packet.java index 11d97be9..5bdbfcbf 100644 --- a/shared/java/top/fpsmaster/websocket/data/message/Packet.java +++ b/shared/java/top/fpsmaster/websocket/data/message/Packet.java @@ -20,7 +20,7 @@ public Packet parse(String json) { return (Packet) JsonUtils.parseJson(json, this.getClass()); } - public static Packet parsePacket(String json, Class packet) { + public static Packet parsePacket(String json, Class packet) { return (Packet) JsonUtils.parseJson(json, packet); } } diff --git a/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinGuiNewChat.java b/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinGuiNewChat.java index c4e46cb5..90c11a85 100644 --- a/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinGuiNewChat.java +++ b/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinGuiNewChat.java @@ -185,14 +185,9 @@ public void drawChat(int updateCounter) { m = mc.fontRendererObj.FONT_HEIGHT; GlStateManager.translate(-3.0F, 0.0F, 0.0F); int r = j * m + j; - n = l * m + l; - int s = this.scrollPos * n / j; - int t = n * n / r; - if (r != n) { - o = s > 0 ? 170 : 96; - int p = this.isScrolled ? 13382451 : 3355562; - Gui.drawRect(0, -s, 2, -s - t, module.backgroundColor.getColor().getRGB()); - Gui.drawRect(2, -s, 1, -s - t, module.backgroundColor.getColor().getRGB()); + if (r != 0) { + Gui.drawRect(0, 0, 2, 0, module.backgroundColor.getColor().getRGB()); + Gui.drawRect(2, 0, 1, 0, module.backgroundColor.getColor().getRGB()); } } @@ -231,10 +226,8 @@ public IChatComponent getChatComponent(int mouseX, int mouseY) { if (m >= 0 && m < this.drawnChatLines.size()) { ChatLine chatLine = this.drawnChatLines.get(m); int n = 0; - Iterator var12 = chatLine.getChatComponent().iterator(); - while (var12.hasNext()) { - IChatComponent iTextComponent = (IChatComponent) var12.next(); + for (IChatComponent iTextComponent : chatLine.getChatComponent()) { if (iTextComponent instanceof ChatComponentText) { if (BetterChat.using && module.betterFont.getValue()) { n += FPSMaster.fontManager.s16.getStringWidth(GuiUtilRenderComponents.func_178909_a(((ChatComponentText) iTextComponent).getChatComponentText_TextValue(), false)); diff --git a/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinGuiPlayerOverlay.java b/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinGuiPlayerOverlay.java index be4dd584..ab0d6da2 100644 --- a/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinGuiPlayerOverlay.java +++ b/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinGuiPlayerOverlay.java @@ -145,7 +145,7 @@ public void renderPlayerlist(int width, Scoreboard scoreboardIn, ScoreObjective GlStateManager.enableBlend(); GlStateManager.tryBlendFuncSeparate(770, 771, 1, 0); if (t < list.size()) { - NetworkPlayerInfo networkPlayerInfo2 = (NetworkPlayerInfo) list.get(t); + NetworkPlayerInfo networkPlayerInfo2 = list.get(t); String string2 = this.getPlayerName(networkPlayerInfo2); GameProfile gameProfile = networkPlayerInfo2.getGameProfile(); if (bl) { diff --git a/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinInventoryEffectRenderer.java b/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinInventoryEffectRenderer.java index 46126b05..e062527d 100644 --- a/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinInventoryEffectRenderer.java +++ b/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinInventoryEffectRenderer.java @@ -24,10 +24,8 @@ public class MixinInventoryEffectRenderer extends MixinGuiContainer{ @Inject(method = "updateActivePotionEffects", at = @At("RETURN")) private void renderPotionEffects(CallbackInfo ci) { boolean hasVisibleEffect = false; - Iterator var2 = mc.thePlayer.getActivePotionEffects().iterator(); - while(var2.hasNext()) { - PotionEffect potioneffect = (PotionEffect)var2.next(); + for (PotionEffect potioneffect : mc.thePlayer.getActivePotionEffects()) { Potion potion = Potion.potionTypes[potioneffect.getPotionID()]; if (potion.shouldRender(potioneffect)) { hasVisibleEffect = true; diff --git a/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinItemRenderer.java b/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinItemRenderer.java index e9df6860..144298c7 100644 --- a/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinItemRenderer.java +++ b/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinItemRenderer.java @@ -230,13 +230,13 @@ private void drawBlocking(float equippedProgress, float swingProgress) { @Overwrite public void renderItemInFirstPerson(float partialTicks) { float f = 1.0F - (this.prevEquippedProgress + (this.equippedProgress - this.prevEquippedProgress) * partialTicks); - AbstractClientPlayer abstractclientplayer = mc.thePlayer; + EntityPlayerSP abstractclientplayer = mc.thePlayer; float f1 = abstractclientplayer.getSwingProgress(partialTicks); float f2 = abstractclientplayer.prevRotationPitch + (abstractclientplayer.rotationPitch - abstractclientplayer.prevRotationPitch) * partialTicks; float f3 = abstractclientplayer.prevRotationYaw + (abstractclientplayer.rotationYaw - abstractclientplayer.prevRotationYaw) * partialTicks; this.rotateArroundXAndY(f2, f3); this.setLightMapFromPlayer(abstractclientplayer); - this.rotateWithPlayerRotations((EntityPlayerSP) abstractclientplayer, partialTicks); + this.rotateWithPlayerRotations(abstractclientplayer, partialTicks); GlStateManager.enableRescaleNormal(); GlStateManager.pushMatrix(); if (this.itemToRender != null) { diff --git a/v1.8.9/src/main/java/top/fpsmaster/minimap/Minimap.java b/v1.8.9/src/main/java/top/fpsmaster/minimap/Minimap.java index 4749fd83..d7836b8b 100644 --- a/v1.8.9/src/main/java/top/fpsmaster/minimap/Minimap.java +++ b/v1.8.9/src/main/java/top/fpsmaster/minimap/Minimap.java @@ -20,17 +20,16 @@ import net.minecraft.util.EnumWorldBlockLayer; import net.minecraft.util.ResourceLocation; import net.minecraft.world.EnumSkyBlock; -import net.minecraft.world.IBlockAccess; import net.minecraft.world.chunk.Chunk; import org.lwjgl.opengl.GL11; import org.lwjgl.opengl.GL14; import org.lwjgl.opengl.GLContext; +import top.fpsmaster.features.impl.interfaces.MiniMap; import top.fpsmaster.ui.minimap.animation.MinimapAnimation; import top.fpsmaster.ui.minimap.interfaces.Interface; import top.fpsmaster.ui.minimap.interfaces.InterfaceHandler; import top.fpsmaster.ui.minimap.minimap.DynamicTexture; import top.fpsmaster.ui.minimap.minimap.MinimapChunk; -import top.fpsmaster.utils.render.Render2DUtils; import java.awt.*; import java.awt.image.BufferedImage; @@ -42,8 +41,7 @@ import static top.fpsmaster.utils.Utility.mc; -public class Minimap -{ +public class Minimap { public Interface screen; public static final int frame = 9; public static int loadingSide; @@ -109,11 +107,11 @@ public class Minimap public static int getLoadSide() { return Minimap.enlargedMap ? 31 : Minimap.FBOMinimapSizes[2]; } - + public static int getUpdateRadius() { - return (int)Math.ceil(Minimap.loadingSide); + return (int) (double) Minimap.loadingSide; } - + public Minimap(final Interface i) { this.loadedCaving = -1; this.loadingCaving = -1; @@ -137,7 +135,7 @@ public Minimap(final Interface i) { this.screen = i; new Thread(this.loader).start(); } - + public static int loadBlockColourFromTexture(final IBlockState state, final Block b, final BlockPos pos, final boolean convert) { final int stateId = state.toString().hashCode(); Integer c = Minimap.blockColours.get(stateId); @@ -151,23 +149,19 @@ public static int loadBlockColourFromTexture(final IBlockState state, final Bloc name = texture.getIconName() + ".png"; if (b instanceof BlockGrass) { name = "minecraft:blocks/grass_top.png"; - } - else if (b == Blocks.red_mushroom_block) { + } else if (b == Blocks.red_mushroom_block) { name = "minecraft:blocks/mushroom_block_skin_red.png"; - } - else if (b == Blocks.brown_mushroom_block) { + } else if (b == Blocks.brown_mushroom_block) { name = "minecraft:blocks/mushroom_block_skin_brown.png"; - } - else if (b instanceof BlockOre && b != Blocks.quartz_ore) { + } else if (b instanceof BlockOre && b != Blocks.quartz_ore) { name = "minecraft:blocks/stone.png"; } if (convert) { name = name.replaceAll("_side", "_top").replaceAll("_front.png", "_top.png"); } - c = -1; String[] args = name.split(":"); if (args.length < 2) { - args = new String[] { "minecraft", args[0] }; + args = new String[]{"minecraft", args[0]}; } final Integer cachedColour = Minimap.textureColours.get(name); if (cachedColour == null) { @@ -175,9 +169,6 @@ else if (b instanceof BlockOre && b != Blocks.quartz_ore) { final IResource resource = Minecraft.getMinecraft().getResourceManager().getResource(location); final InputStream input = resource.getInputStream(); final BufferedImage img = TextureUtil.readBufferedImage(input); - red = 0; - green = 0; - blue = 0; int total = 64; final int tw = img.getWidth(); final int diff = tw / 8; @@ -186,8 +177,7 @@ else if (b instanceof BlockOre && b != Blocks.quartz_ore) { final int rgb = img.getRGB(i * diff, j * diff); if (rgb == 0) { --total; - } - else { + } else { red += (rgb >> 16 & 0xFF); green += (rgb >> 8 & 0xFF); blue += (rgb & 0xFF); @@ -203,45 +193,38 @@ else if (b instanceof BlockOre && b != Blocks.quartz_ore) { blue /= total; c = (0xFF000000 | red << 16 | green << 8 | blue); Minimap.textureColours.put(name, c); - } - else { + } else { c = cachedColour; } - } - catch (FileNotFoundException e) { + } catch (FileNotFoundException e) { if (convert) { return loadBlockColourFromTexture(state, b, pos, false); } c = b.getMapColor(state).colorValue; - if (name != null) { - Minimap.textureColours.put(name, c); - } + Minimap.textureColours.put(name, c); System.out.println("Block file not found: " + b.getLocalizedName()); - } - catch (Exception e2) { + } catch (Exception e2) { c = b.getMapColor(state).colorValue; if (name != null) { Minimap.textureColours.put(name, c); } System.out.println("Block " + b.getLocalizedName() + " has no texture, using material colour."); } - if (c != null) { - Minimap.blockColours.put(stateId, c); - } + Minimap.blockColours.put(stateId, c); } final int grassColor = b.colorMultiplier(Minecraft.getMinecraft().theWorld, pos); if (grassColor != 16777215) { final float rMultiplier = (c >> 16 & 0xFF) / 255.0f; final float gMultiplier = (c >> 8 & 0xFF) / 255.0f; final float bMultiplier = (c & 0xFF) / 255.0f; - red = (int)((grassColor >> 16 & 0xFF) * rMultiplier); - green = (int)((grassColor >> 8 & 0xFF) * gMultiplier); - blue = (int)((grassColor & 0xFF) * bMultiplier); + red = (int) ((grassColor >> 16 & 0xFF) * rMultiplier); + green = (int) ((grassColor >> 8 & 0xFF) * gMultiplier); + blue = (int) ((grassColor & 0xFF) * bMultiplier); c = (0xFF000000 | red << 16 | green << 8 | blue); } return c; } - + public boolean applyTransparentBlock(final Chunk bchunk, final Block b, final IBlockState state, final BlockPos globalPos, final BlockPos pos) { int red = 0; int green = 0; @@ -255,8 +238,7 @@ public boolean applyTransparentBlock(final Chunk bchunk, final Block b, final IB blue = (waterColor & 0xFF); intensity = 2; skip = true; - } - else if ((b.getBlockLayer() == EnumWorldBlockLayer.TRANSLUCENT || b instanceof BlockGlass)) { + } else if ((b.getBlockLayer() == EnumWorldBlockLayer.TRANSLUCENT || b instanceof BlockGlass)) { final int glassColor = loadBlockColourFromTexture(state, b, globalPos, true); red = (glassColor >> 16 & 0xFF); green = (glassColor >> 8 & 0xFF); @@ -278,9 +260,9 @@ else if ((b.getBlockLayer() == EnumWorldBlockLayer.TRANSLUCENT || b instanceof B blue = colours[2]; } this.divider += overlayIntensity; - this.underRed += (int)(red * overlayIntensity); - this.underGreen += (int)(green * overlayIntensity); - this.underBlue += (int)(blue * overlayIntensity); + this.underRed += (int) (red * overlayIntensity); + this.underGreen += (int) (green * overlayIntensity); + this.underBlue += (int) (blue * overlayIntensity); } this.sun -= b.getLightOpacity(); if (this.sun < 0) { @@ -289,7 +271,7 @@ else if ((b.getBlockLayer() == EnumWorldBlockLayer.TRANSLUCENT || b instanceof B } return skip; } - + public Block findBlock(final Chunk bchunk, final int insideX, final int insideZ, final int highY, final int lowY) { boolean underair = false; for (int i = highY; i >= lowY; --i) { @@ -299,11 +281,11 @@ public Block findBlock(final Chunk bchunk, final int insideX, final int insideZ, if (got != Blocks.torch) { if (got != Blocks.tallgrass) { this.blockY = i; - int color = 0; + int color; final BlockPos pos = new BlockPos(insideX, this.blockY, insideZ); final BlockPos globalPos = this.getGlobalBlockPos(bchunk.xPosition, bchunk.zPosition, insideX, this.blockY, insideZ); IBlockState state = bchunk.getBlockState(pos); - state = got.getActualState(state, mc.theWorld, globalPos); + state = got.getActualState(state, mc.theWorld, globalPos); if (!this.applyTransparentBlock(bchunk, got, state, globalPos, pos)) { color = loadBlockColourFromTexture(state, got, globalPos, true); if (color != 0) { @@ -314,41 +296,40 @@ public Block findBlock(final Chunk bchunk, final int insideX, final int insideZ, } } } - } - else if (got instanceof BlockAir) { + } else if (got instanceof BlockAir) { underair = true; } } return null; } - + public BlockPos getGlobalBlockPos(final int chunkX, final int chunkZ, final int x, final int y, final int z) { return new BlockPos(chunkX * 16 + x, y, chunkZ * 16 + z); } - + public float getBlockBrightness(final Chunk c, final BlockPos pos, final float min, final int sun, final boolean dayLight) { return (min + Math.max((dayLight ? Minimap.sunBrightness : 1.0f) * c.getLightFor(EnumSkyBlock.SKY, pos), c.getLightFor(EnumSkyBlock.BLOCK, pos))) / (15.0f + min); } - + public int[] getBrightestColour(int r, int g, int b) { final int max = Math.max(r, Math.max(g, b)); if (max == 0) { - return new int[] { r, g, b }; + return new int[]{r, g, b}; } r = 255 * r / max; g = 255 * g / max; b = 255 * b / max; - return new int[] { r, g, b }; + return new int[]{r, g, b}; } - + public boolean isGlowing(final Block b) { return b.getLightValue() >= 0.5; } - + public void loadBlockColor(final int par1, final int par2, final Chunk bchunk, final int chunkX, final int chunkZ) { final int insideX = par1 & 0xF; final int insideZ = par2 & 0xF; - final int playerY = (int)mc.thePlayer.posY; + final int playerY = (int) mc.thePlayer.posY; final int height = bchunk.getHeightValue(insideX, insideZ); final int highY = (this.loadingCaving != -1) ? this.loadingCaving : (height + 3); int lowY = (this.loadingCaving != -1) ? (playerY - 30) : 0; @@ -367,10 +348,10 @@ public void loadBlockColor(final int par1, final int par2, final Chunk bchunk, f this.isglowing = false; final Block block = this.findBlock(bchunk, insideX, insideZ, highY, lowY); this.isglowing = (block != null && !(block instanceof BlockOre) && this.isGlowing(block)); - float brightness = 1.0f; + float brightness; final BlockPos pos = new BlockPos(insideX, Math.min(this.blockY + 1, 255), insideZ); brightness = this.getBlockBrightness(bchunk, pos, 5.0f, this.sun, this.previousTransparentBlock == null); - + double secondaryB = 1.0; if (this.lastBlockY[insideX] <= 0) { this.lastBlockY[insideX] = this.blockY; @@ -385,7 +366,7 @@ public void loadBlockColor(final int par1, final int par2, final Chunk bchunk, f if (this.blockY > this.lastBlockY[insideX]) { secondaryB += 0.15; } - brightness *= (float)secondaryB; + brightness *= (float) secondaryB; this.lastBlockY[insideX] = this.blockY; if (this.blockColor == 0) { this.blockColor = 1; @@ -399,15 +380,15 @@ public void loadBlockColor(final int par1, final int par2, final Chunk bchunk, f i1 = colours[1]; j1 = colours[2]; } - l = (int)((l * brightness + this.underRed) / this.divider * this.postBrightness); + l = (int) ((l * brightness + this.underRed) / this.divider * this.postBrightness); if (l > 255) { l = 255; } - i1 = (int)((i1 * brightness + this.underGreen) / this.divider * this.postBrightness); + i1 = (int) ((i1 * brightness + this.underGreen) / this.divider * this.postBrightness); if (i1 > 255) { i1 = 255; } - j1 = (int)((j1 * brightness + this.underBlue) / this.divider * this.postBrightness); + j1 = (int) ((j1 * brightness + this.underBlue) / this.divider * this.postBrightness); if (j1 > 255) { j1 = 255; } @@ -427,11 +408,11 @@ public void loadBlockColor(final int par1, final int par2, final Chunk bchunk, f } chunk.colors[insideX][insideZ] = this.blockColor; } - + public int getMapCoord(final int side, final double coord) { return (myFloor(coord) >> 4) - side / 2; } - + public int getLoadedBlockColor(final int par1, final int par2) { final int cX = (par1 >> 4) - this.loadedMapX; final int cZ = (par2 >> 4) - this.loadedMapZ; @@ -444,7 +425,7 @@ public int getLoadedBlockColor(final int par1, final int par2) { } return 1; } - + public MinimapChunk[] getLoadedYChunks(final int par1) { final int cX = (par1 >> 4) - this.loadedMapX; if (cX < 0 || cX >= Minimap.loadedSide) { @@ -452,7 +433,7 @@ public MinimapChunk[] getLoadedYChunks(final int par1) { } return this.currentBlocks[cX]; } - + public int getLoadedBlockColor(final MinimapChunk[] yChunks, final int par1, final int par2) { final int cZ = (par2 >> 4) - this.loadedMapZ; if (cZ < 0 || cZ >= Minimap.loadedSide) { @@ -464,15 +445,15 @@ public int getLoadedBlockColor(final MinimapChunk[] yChunks, final int par1, fin } return 1; } - + public int chunkOverlay(final int color, final MinimapChunk c) { return color; } - + public static double getRenderAngle() { return getActualAngle(); } - + public static double getActualAngle() { double rotation = mc.thePlayer.rotationYaw; if (rotation < 0.0 || rotation > 360.0) { @@ -484,59 +465,58 @@ public static double getActualAngle() { } return angle; } - + public double getZoom() { return this.minimapZoom; } - + public void updateZoom() { double target = 2 * ((this.loadedCaving != -1) ? 3.0f : 1.0f); - + double off = target - this.minimapZoom; if (off > 0.01 || off < -0.01) { off = (float) MinimapAnimation.animate(off, 0.8); - } - else { + } else { off = 0.0; } this.minimapZoom = target - off; } - + public static double getEntityX(final Entity e, final float partial) { return e.lastTickPosX + (e.posX - e.lastTickPosX) * partial; } - + public static double getEntityZ(final Entity e, final float partial) { return e.lastTickPosZ + (e.posZ - e.lastTickPosZ) * partial; } - + public static void resetImage() { Minimap.toResetImage = true; } - + public static int myFloor(double d) { if (d < 0.0) { --d; } - return (int)d; + return (int) d; } - + public int getMinimapWidth() { - return 149; + return 149; } - + public int getBufferSize() { return Minimap.enlargedMap ? 512 : Minimap.bufferSizes[2]; } - + public int getFBOBufferSize() { return Minimap.enlargedMap ? 512 : Minimap.FBOBufferSizes[2]; } - + public static boolean usingFBO() { return Minimap.loadedFBO; } - + public void updateMapFrame(final int bufferSize, final float partial) { if (Minimap.toResetImage || usingFBO()) { this.bytes = new byte[bufferSize * bufferSize * 3]; @@ -562,8 +542,8 @@ public void updateMapFrame(final int bufferSize, final float partial) { final int chunkOffsetX = Minimap.mapUpdateX - this.loadedMapX; final int chunkOffsetZ = Minimap.mapUpdateZ - this.loadedMapZ; mapW = (mapH = Math.min(bufferSize, actualSize * 16)); - final double corner = Minimap.enlargedMap ? 0.0 : ((double)(int)(actualSize * (Math.sqrt(2.0) - 1.0) / Math.sqrt(2.0))); - final int cornerZoomed = (int)(corner + actualSize * Math.sqrt(0.5) * (1.0 - 1.0 / Minimap.zoom) - 1.0); + final double corner = Minimap.enlargedMap ? 0.0 : ((double) (int) (actualSize * (Math.sqrt(2.0) - 1.0) / Math.sqrt(2.0))); + final int cornerZoomed = (int) (corner + actualSize * Math.sqrt(0.5) * (1.0 - 1.0 / Minimap.zoom) - 1.0); final int thing = actualSize - 1; for (int chunkX = 0; chunkX < chunkAmount - chunkOffsetX; ++chunkX) { final int transformedX = chunkX + chunkOffsetX; @@ -607,8 +587,7 @@ public void updateMapFrame(final int bufferSize, final float partial) { } } } - } - else { + } else { byte currentState = this.drawYState; final double angle = Math.toRadians(getRenderAngle()); final double ps = Math.sin(3.141592653589793 - angle); @@ -624,18 +603,18 @@ public void updateMapFrame(final int bufferSize, final float partial) { final double offy = currentY / Minimap.zoom - halfHZoomed; this.putColor(this.bytes, currentX, currentY, this.getLoadedBlockColor(myFloor(playerX + psx + pc * offy), myFloor(playerZ + ps * offy - pcx)), bufferSize); } - currentState = (byte)((currentState != 1) ? 1 : 0); + currentState = (byte) ((currentState != 1) ? 1 : 0); } - this.drawYState = (byte)((this.drawYState != 1) ? 1 : 0); + this.drawYState = (byte) ((this.drawYState != 1) ? 1 : 0); final ByteBuffer buffer = Minimap.mapTexture.getBuffer(bufferSize); buffer.put(this.bytes); buffer.flip(); } } - + private int getCaving() { final int x = myFloor(mc.thePlayer.posX); - final int y = Math.max((int)mc.thePlayer.posY + 1, 0); + final int y = Math.max((int) mc.thePlayer.posY + 1, 0); final int z = myFloor(mc.thePlayer.posZ); final int chunkX = x >> 4; final int chunkZ = z >> 4; @@ -653,19 +632,18 @@ private int getCaving() { } return -1; } - + private void putColor(final byte[] bytes, final int x, final int y, final int color, final int size) { int pixel = (y * size + x) * 3; - bytes[pixel] = (byte)(color >> 16 & 0xFF); - bytes[++pixel] = (byte)(color >> 8 & 0xFF); - bytes[++pixel] = (byte)(color & 0xFF); + bytes[pixel] = (byte) (color >> 16 & 0xFF); + bytes[++pixel] = (byte) (color >> 8 & 0xFF); + bytes[++pixel] = (byte) (color & 0xFF); } - + public static void loadFrameBuffer() { if (!GLContext.getCapabilities().GL_EXT_framebuffer_object) { System.out.println("FBO not supported! Using minimap safe mode."); - } - else { + } else { if (!Minecraft.getMinecraft().gameSettings.fboEnable) { Minecraft.getMinecraft().gameSettings.setOptionValue(GameSettings.Options.FBO_ENABLE, 0); System.out.println("FBO is supported but off. Turning it on."); @@ -676,7 +654,7 @@ public static void loadFrameBuffer() { } Minimap.triedFBO = true; } - + public void renderFrameToFBO(final int bufferSize, final int viewW, final float sizeFix, final float partial, final boolean retryIfError) { Minimap.updatePause = true; final int chunkAmount = getLoadSide(); @@ -689,7 +667,7 @@ public void renderFrameToFBO(final int bufferSize, final int viewW, final float int offsetZ = zFloored & 0xF; final int mapX = this.getMapCoord(chunkAmount, playerX); final int mapZ = this.getMapCoord(chunkAmount, playerZ); - final boolean zooming = (int)Minimap.zoom != Minimap.zoom; + final boolean zooming = (int) Minimap.zoom != Minimap.zoom; final ByteBuffer buffer = Minimap.mapTexture.getBuffer(bufferSize); if (mapX != Minimap.mapUpdateX || mapZ != Minimap.mapUpdateZ || zooming || !retryIfError) { if (!Minimap.frameIsUpdating) { @@ -700,8 +678,7 @@ public void renderFrameToFBO(final int bufferSize, final int viewW, final float buffer.flip(); Minimap.bufferSizeToUpdate = -1; Minimap.frameUpdateNeeded = false; - } - else { + } else { offsetX += 16 * (mapX - Minimap.mapUpdateX); offsetZ += 16 * (mapZ - Minimap.mapUpdateZ); } @@ -712,21 +689,18 @@ public void renderFrameToFBO(final int bufferSize, final int viewW, final float RenderHelper.disableStandardItemLighting(); try { bindTextureBuffer(buffer, bufferSize, bufferSize, Minimap.mapTexture.getGlTextureId()); - } - catch (Exception e) { + } catch (Exception e) { if (retryIfError) { System.out.println("Error when binding texture buffer. Retrying..."); this.renderFrameToFBO(bufferSize, viewW, sizeFix, partial, false); - } - else { + } else { System.out.println("Error after retrying... :( Please report to Xaero96 on MinecraftForum of PlanetMinecraft!"); } } - + if (!zooming) { GL11.glTexParameteri(3553, 10240, 9728); - } - else { + } else { GL11.glTexParameteri(3553, 10240, 9729); } GlStateManager.clear(256); @@ -737,7 +711,7 @@ public void renderFrameToFBO(final int bufferSize, final int viewW, final float GlStateManager.matrixMode(5888); GL11.glPushMatrix(); GlStateManager.loadIdentity(); - + double xInsidePixel = getEntityX(mc.thePlayer, partial) - xFloored; if (xInsidePixel < 0.0) { ++xInsidePixel; @@ -749,10 +723,10 @@ public void renderFrameToFBO(final int bufferSize, final int viewW, final float zInsidePixel = 1.0 - zInsidePixel; final float halfW = mapW / 2.0f; final float halfWView = viewW / 2.0f; - final float angle = (float)(90.0 - getRenderAngle()); + final float angle = (float) (90.0 - getRenderAngle()); GlStateManager.translate(256.0f, 256.0f, -2000.0f); GlStateManager.scale(Minimap.zoom, Minimap.zoom, 1.0); - drawMyTexturedModalRect(-halfW - offsetX + 8.0f, -halfW - offsetZ + 7.0f, 0, 0, mapW + offsetX, mapW + offsetZ, bufferSize); + drawMyTexturedModalRect(-halfW - offsetX + 8.0f, -halfW - offsetZ + 7.0f, mapW + offsetX, mapW + offsetZ, bufferSize); Minimap.scalingFrameBuffer.unbindFramebuffer(); Minimap.rotationFrameBuffer.bindFramebuffer(false); GL11.glClear(16640); @@ -766,13 +740,13 @@ public void renderFrameToFBO(final int bufferSize, final int viewW, final float GlStateManager.translate(-xInsidePixel * Minimap.zoom, -zInsidePixel * Minimap.zoom, 0.0); GlStateManager.disableBlend(); GL11.glColor4f(1.0f, 1.0f, 1.0f, 100.0f); - drawMyTexturedModalRect(-256.0f, -256.0f, 0, 0, 512.0f, 512.0f, 512.0f); + drawMyTexturedModalRect(-256.0f, -256.0f, 512.0f, 512.0f, 512.0f); GL11.glColor4f(1.0f, 1.0f, 1.0f, 1.0f); GL11.glPopMatrix(); - + GL11.glTexParameteri(3553, 10240, 9729); GL11.glTexParameteri(3553, 10241, 9729); - + GlStateManager.enableBlend(); GL14.glBlendFuncSeparate(770, 771, 1, 771); GL11.glTexParameteri(3553, 10240, 9728); @@ -786,29 +760,29 @@ public void renderFrameToFBO(final int bufferSize, final int viewW, final float GlStateManager.matrixMode(5888); GL11.glPopMatrix(); } - - private static void drawMyTexturedModalRect(final float x, final float y, final int textureX, final int textureY, final float width, final float height, final float factor) { + + private static void drawMyTexturedModalRect(final float x, final float y, final float width, final float height, final float factor) { float f = 1.0F / factor; Tessellator tessellator = Tessellator.getInstance(); WorldRenderer worldrenderer = tessellator.getWorldRenderer(); worldrenderer.begin(7, DefaultVertexFormats.POSITION_TEX); - worldrenderer.pos(x + 0.0F, y + height, 0.0D).tex((float) (textureX) * f, ((float) textureY + height) * f).endVertex(); - worldrenderer.pos(x + width, y + height, 0.0D).tex(((float) textureX + width) * f, ((float) textureY + height) * f).endVertex(); - worldrenderer.pos(x + width, y + 0.0F, 0.0D).tex(((float) textureX + width) * f, (float) (textureY) * f).endVertex(); - worldrenderer.pos(x + 0.0F, y + 0.0F, 0.0D).tex((float) (textureX) * f, (float) (textureY) * f).endVertex(); + worldrenderer.pos(x + 0.0F, y + height, 0.0D).tex(0, height * f).endVertex(); + worldrenderer.pos(x + width, y + height, 0.0D).tex(width * f, height * f).endVertex(); + worldrenderer.pos(x + width, y + 0.0F, 0.0D).tex(width * f, f).endVertex(); + worldrenderer.pos(x + 0.0F, y + 0.0F, 0.0D).tex(0, f).endVertex(); tessellator.draw(); } - + public static void bindTextureBuffer(final ByteBuffer image, final int width, final int height, final int par0) { GL11.glBindTexture(3553, par0); GL11.glTexImage2D(3553, 0, 6407, width, height, 0, 6407, 5121, image); } - + public static boolean shouldRenderEntity(final Entity e) { return !e.isSneaking() && !e.isInvisible(); } - + static { Minimap.loadingSide = 16; Minimap.loadedSide = 16; @@ -817,45 +791,51 @@ public static boolean shouldRenderEntity(final Entity e) { mc = Minecraft.getMinecraft(); radarPlayers = new Color(255, 255, 255); radarShadow = new Color(0, 0, 0); - Minimap.loadedPlayers = new ArrayList(); - Minimap.loadedLiving = new ArrayList(); - Minimap.loadedHostile = new ArrayList(); - Minimap.loadedItems = new ArrayList(); - Minimap.loadedEntities = new ArrayList(); + Minimap.loadedPlayers = new ArrayList<>(); + Minimap.loadedLiving = new ArrayList<>(); + Minimap.loadedHostile = new ArrayList<>(); + Minimap.loadedItems = new ArrayList<>(); + Minimap.loadedEntities = new ArrayList<>(); Minimap.blocksLoaded = 0; Minimap.frameIsUpdating = false; Minimap.frameUpdateNeeded = false; Minimap.bufferSizeToUpdate = -1; Minimap.frameUpdatePartialTicks = 1.0f; Minimap.updatePause = false; - Minimap.textureColours = new HashMap(); - Minimap.blockColours = new HashMap(); + Minimap.textureColours = new HashMap<>(); + Minimap.blockColours = new HashMap<>(); Minimap.clearBlockColours = false; Minimap.toResetImage = true; Minimap.zoom = 1.0; - minimapSizes = new int[] { 112, 168, 224, 336 }; - bufferSizes = new int[] { 128, 256, 256, 512 }; - FBOMinimapSizes = new int[] { 11, 17, 21, 31 }; - FBOBufferSizes = new int[] { 256, 512, 512, 512 }; + minimapSizes = new int[]{112, 168, 224, 336}; + bufferSizes = new int[]{128, 256, 256, 512}; + FBOMinimapSizes = new int[]{11, 17, 21, 31}; + FBOBufferSizes = new int[]{256, 512, 512, 512}; Minimap.triedFBO = false; Minimap.loadedFBO = false; Minimap.mapTexture = new DynamicTexture(InterfaceHandler.mapTextures); } - - public class MapLoader implements Runnable - { + + public class MapLoader implements Runnable { @Override public void run() { int updateChunkX = 0; int updateChunkZ = 0; while (true) { + if(!MiniMap.using) { + try { + Thread.sleep(1000L); + continue; + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + } final long before = System.currentTimeMillis(); boolean sleep = true; try { if (mc.thePlayer == null || mc.theWorld == null) { Thread.sleep(100L); - } - else { + } else { if (updateChunkX == 0 && updateChunkZ == 0) { if (Minimap.clearBlockColours) { Minimap.clearBlockColours = false; @@ -886,11 +866,11 @@ public void run() { updateChunkX = (updateChunkX + 1) % Minimap.loadingSide; Minimap.this.lastBlockY = new int[16]; final EntityPlayer p = mc.thePlayer; - final ArrayList loadingPlayers = new ArrayList(); - final ArrayList loadingHostile = new ArrayList(); - final ArrayList loadingLiving = new ArrayList(); - final ArrayList loadingItems = new ArrayList(); - final ArrayList loadingEntities = new ArrayList(); + final ArrayList loadingPlayers = new ArrayList<>(); + final ArrayList loadingHostile = new ArrayList<>(); + final ArrayList loadingLiving = new ArrayList<>(); + final ArrayList loadingItems = new ArrayList<>(); + final ArrayList loadingEntities = new ArrayList<>(); for (int i = 0; i < mc.theWorld.loadedEntityList.size(); ++i) { try { final Entity e = mc.theWorld.loadedEntityList.get(i); @@ -903,32 +883,13 @@ public void run() { final double offy2 = offy * offy; final double maxDistance = 31250.0 / (Minimap.this.getZoom() * Minimap.this.getZoom()); if (offx2 <= maxDistance && offy2 <= maxDistance && offheight2 <= 400.0) { - ArrayList typeList = loadingEntities; - switch (type) { - case 1: { - typeList = loadingPlayers; - break; - } - case 2: { - typeList = loadingHostile; - break; - } - case 3: { - typeList = loadingLiving; - break; - } - case 4: { - typeList = loadingItems; - break; - } - } - typeList.add(e); - if (typeList.size() >= 100) { + loadingEntities.add(e); + if (loadingEntities.size() >= 100) { break; } } + } catch (Exception ignored) { } - catch (Exception e4) {} } Minimap.loadedPlayers = loadingPlayers; Minimap.loadedHostile = loadingHostile; @@ -950,26 +911,23 @@ public void run() { Minimap.bufferSizeToUpdate = -1; } } - } - catch (Exception e2) { + } catch (Exception e2) { e2.printStackTrace(); Minimap.frameIsUpdating = false; } - final int passed = (int)(System.currentTimeMillis() - before); + final int passed = (int) (System.currentTimeMillis() - before); try { if (sleep && passed <= 5) { Thread.sleep(5 - passed); - } - else { + } else { Thread.sleep(1L); } - } - catch (InterruptedException e3) { + } catch (InterruptedException e3) { e3.printStackTrace(); } } } - + public boolean updateChunk(final int x, final int z) { final int chunkX = Minimap.this.loadingMapX + x; final int chunkZ = Minimap.this.loadingMapZ + z; @@ -983,12 +941,11 @@ public boolean updateChunk(final int x, final int z) { current = Minimap.this.currentBlocks[xOld][zOld]; } final Chunk bchunk = mc.theWorld.getChunkFromChunkCoords(chunkX, chunkZ); - if ((int)Minimap.zoom == Minimap.zoom && (!bchunk.isLoaded() || ((fromCenterX > Minimap.updateRadius || fromCenterZ > Minimap.updateRadius || fromCenterX < -Minimap.updateRadius || fromCenterZ < -Minimap.updateRadius) && current != null))) { + if ((int) Minimap.zoom == Minimap.zoom && (!bchunk.isLoaded() || ((fromCenterX > Minimap.updateRadius || fromCenterZ > Minimap.updateRadius || fromCenterX < -Minimap.updateRadius || fromCenterZ < -Minimap.updateRadius) && current != null))) { if (current != null) { Minimap.this.loadingBlocks[x][z] = current; System.arraycopy(current.lastHeights, 0, Minimap.this.lastBlockY, 0, 16); - } - else { + } else { Minimap.this.lastBlockY = new int[16]; } return false; diff --git a/v1.8.9/src/main/java/top/fpsmaster/wrapper/ChatFormattingProvider.java b/v1.8.9/src/main/java/top/fpsmaster/wrapper/ChatFormattingProvider.java index 61144267..0cdce7a0 100644 --- a/v1.8.9/src/main/java/top/fpsmaster/wrapper/ChatFormattingProvider.java +++ b/v1.8.9/src/main/java/top/fpsmaster/wrapper/ChatFormattingProvider.java @@ -83,8 +83,7 @@ public static Collection getNames(boolean getColors, boolean getFormats) ChatFormattingProvider[] arr$ = values(); int len$ = arr$.length; - for (int i$ = 0; i$ < len$; ++i$) { - ChatFormattingProvider format = arr$[i$]; + for (ChatFormattingProvider format : arr$) { if ((!format.isColor() || getColors) && (!format.isFormat() || getFormats)) { result.add(format.getName()); } @@ -95,10 +94,8 @@ public static Collection getNames(boolean getColors, boolean getFormats) static { ChatFormattingProvider[] arr$ = values(); - int len$ = arr$.length; - for (int i$ = 0; i$ < len$; ++i$) { - ChatFormattingProvider format = arr$[i$]; + for (ChatFormattingProvider format : arr$) { FORMATTING_BY_CHAR.put(format.getChar(), format); FORMATTING_BY_NAME.put(format.getName(), format); } diff --git a/v1.8.9/src/main/java/top/fpsmaster/wrapper/SkinProvider.java b/v1.8.9/src/main/java/top/fpsmaster/wrapper/SkinProvider.java index 61e5f2dc..c266f2b1 100644 --- a/v1.8.9/src/main/java/top/fpsmaster/wrapper/SkinProvider.java +++ b/v1.8.9/src/main/java/top/fpsmaster/wrapper/SkinProvider.java @@ -29,7 +29,7 @@ public void updateSkin(String name, String uuid, String skin) { } } - HttpRequest.HttpResponseResult httpResponseResult = null; + HttpRequest.HttpResponseResult httpResponseResult; try { httpResponseResult = HttpRequest.get("https://api.mojang.com/users/profiles/minecraft/" + skin); } catch (IOException e) { diff --git a/v1.8.9/src/main/java/top/fpsmaster/wrapper/util/WrapperAxisAlignedBB.java b/v1.8.9/src/main/java/top/fpsmaster/wrapper/util/WrapperAxisAlignedBB.java index 04eef0a6..2e18263a 100644 --- a/v1.8.9/src/main/java/top/fpsmaster/wrapper/util/WrapperAxisAlignedBB.java +++ b/v1.8.9/src/main/java/top/fpsmaster/wrapper/util/WrapperAxisAlignedBB.java @@ -72,8 +72,8 @@ public double getMaxZ() { return axisAlignedBB.maxZ; } - public AxisAlignedBB expand(double x){ - axisAlignedBB = axisAlignedBB.expand(x, x, x); + public AxisAlignedBB expand(double e){ + axisAlignedBB = axisAlignedBB.expand(e, e, e); return axisAlignedBB; } From d351c20b4d5aa81dd7e407f1710824018c9a3f31 Mon Sep 17 00:00:00 2001 From: SuperSkidder Date: Mon, 21 Jul 2025 00:55:34 +0800 Subject: [PATCH 162/193] fix: memory leak --- shared/java/top/fpsmaster/ui/click/MainPanel.java | 12 ++++++------ shared/java/top/fpsmaster/utils/awt/AWTUtils.java | 2 -- .../top/fpsmaster/utils/render/Render2DUtils.java | 2 +- 3 files changed, 7 insertions(+), 9 deletions(-) diff --git a/shared/java/top/fpsmaster/ui/click/MainPanel.java b/shared/java/top/fpsmaster/ui/click/MainPanel.java index 223b966f..52ef8f54 100644 --- a/shared/java/top/fpsmaster/ui/click/MainPanel.java +++ b/shared/java/top/fpsmaster/ui/click/MainPanel.java @@ -158,13 +158,13 @@ public void render(int mouseX, int mouseY, float partialTicks) { categoryAnimation = (float) AnimationUtils.base(categoryAnimation, 30f, 0.15f); } - Render2DUtils.drawOptimizedRoundedRect( + Render2DUtils.drawRoundedRectImage( x + categoryAnimation / 50f, y + height / 2 - 74, categoryAnimation, 140, - 14, - new Color(0, 0, 0, 200).getRGB() + 20, + new Color(0, 0, 0, 200) ); Render2DUtils.drawRoundedRectImage( @@ -185,13 +185,13 @@ public void render(int mouseX, int mouseY, float partialTicks) { -1); float my = y + 60; - Render2DUtils.drawOptimizedRoundedRect( + Render2DUtils.drawRoundedRectImage( x + 4 + categoryAnimation / 50f, selection - 6, categoryAnimation - 8, 22f, - 10, - new Color(255, 255, 255).getRGB() + 20, + new Color(255, 255, 255) ); diff --git a/shared/java/top/fpsmaster/utils/awt/AWTUtils.java b/shared/java/top/fpsmaster/utils/awt/AWTUtils.java index 1d4dcd32..b32b87d1 100644 --- a/shared/java/top/fpsmaster/utils/awt/AWTUtils.java +++ b/shared/java/top/fpsmaster/utils/awt/AWTUtils.java @@ -56,8 +56,6 @@ public static ResourceLocation[] generateRound(int radius) { return generated.get(radius); } - if (radius <= 0) - radius = 1; try { String[] fileNames = {"lt.png", "rt.png", "lb.png", "rb.png"}; // 存储文件名 int radius2 = radius * 2; diff --git a/shared/java/top/fpsmaster/utils/render/Render2DUtils.java b/shared/java/top/fpsmaster/utils/render/Render2DUtils.java index d891d304..36fbba05 100644 --- a/shared/java/top/fpsmaster/utils/render/Render2DUtils.java +++ b/shared/java/top/fpsmaster/utils/render/Render2DUtils.java @@ -53,11 +53,11 @@ public static void drawOptimizedRoundedRect(float x, float y, float width, float } public static void drawOptimizedRoundedRect(float x, float y, float width, float height, int radius, int color, boolean rawImage) { + radius = (int) Math.min(Math.min(height, width) / 2, radius); if (width < radius * 2 || radius < 1) { drawRect(x, y, width, height, color); return; } - radius = (int) Math.min(Math.min(height, width) / 2, radius); ResourceLocation[] resourceLocations = AWTUtils.generateRound(radius); if (resourceLocations == null || resourceLocations.length == 0) { return; From 8cd5ff624aff19d433e33b7cb107d6835fd86057 Mon Sep 17 00:00:00 2001 From: SuperSkidder Date: Mon, 21 Jul 2025 01:03:12 +0800 Subject: [PATCH 163/193] fix: minimap thread has fucked shutdown --- .../main/java/top/fpsmaster/forge/api/IMinecraft.java | 1 + .../java/top/fpsmaster/forge/mixin/MixinMinecraft.java | 9 +++++++++ v1.8.9/src/main/java/top/fpsmaster/minimap/Minimap.java | 3 ++- 3 files changed, 12 insertions(+), 1 deletion(-) diff --git a/v1.8.9/src/main/java/top/fpsmaster/forge/api/IMinecraft.java b/v1.8.9/src/main/java/top/fpsmaster/forge/api/IMinecraft.java index b9105265..d901de1e 100644 --- a/v1.8.9/src/main/java/top/fpsmaster/forge/api/IMinecraft.java +++ b/v1.8.9/src/main/java/top/fpsmaster/forge/api/IMinecraft.java @@ -9,4 +9,5 @@ public interface IMinecraft { void arch$setSession(Session session); void arch$setLeftClickCounter(int c); void arch$setRightClickDelayTimer(int c); + boolean arch$getRunning(); } diff --git a/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinMinecraft.java b/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinMinecraft.java index 4d94653c..e79fefce 100644 --- a/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinMinecraft.java +++ b/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinMinecraft.java @@ -67,6 +67,10 @@ public abstract class MixinMinecraft implements IMinecraft { @Shadow public PlayerControllerMP playerController; + + @Shadow + boolean running; + @Shadow public abstract void displayGuiScreen(@Nullable GuiScreen guiScreenIn); @@ -254,4 +258,9 @@ public void keyEvent(CallbackInfo ci) { public void setTitle(CallbackInfo ci) { Display.setTitle(getClientTitle()); } + + @Override + public boolean arch$getRunning() { + return running; + } } diff --git a/v1.8.9/src/main/java/top/fpsmaster/minimap/Minimap.java b/v1.8.9/src/main/java/top/fpsmaster/minimap/Minimap.java index d7836b8b..d31f7c44 100644 --- a/v1.8.9/src/main/java/top/fpsmaster/minimap/Minimap.java +++ b/v1.8.9/src/main/java/top/fpsmaster/minimap/Minimap.java @@ -25,6 +25,7 @@ import org.lwjgl.opengl.GL14; import org.lwjgl.opengl.GLContext; import top.fpsmaster.features.impl.interfaces.MiniMap; +import top.fpsmaster.forge.api.IMinecraft; import top.fpsmaster.ui.minimap.animation.MinimapAnimation; import top.fpsmaster.ui.minimap.interfaces.Interface; import top.fpsmaster.ui.minimap.interfaces.InterfaceHandler; @@ -821,7 +822,7 @@ public class MapLoader implements Runnable { public void run() { int updateChunkX = 0; int updateChunkZ = 0; - while (true) { + while (((IMinecraft) mc).arch$getRunning()) { if(!MiniMap.using) { try { Thread.sleep(1000L); From 198c61a4050e46cdacde3c3534281da811c4f68d Mon Sep 17 00:00:00 2001 From: SuperSkidder Date: Mon, 21 Jul 2025 01:13:04 +0800 Subject: [PATCH 164/193] fix: hitboxes --- .../main/java/top/fpsmaster/wrapper/mods/WrapperHitboxes.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/v1.8.9/src/main/java/top/fpsmaster/wrapper/mods/WrapperHitboxes.java b/v1.8.9/src/main/java/top/fpsmaster/wrapper/mods/WrapperHitboxes.java index 2d9095f8..3298f5d0 100644 --- a/v1.8.9/src/main/java/top/fpsmaster/wrapper/mods/WrapperHitboxes.java +++ b/v1.8.9/src/main/java/top/fpsmaster/wrapper/mods/WrapperHitboxes.java @@ -23,6 +23,7 @@ public class WrapperHitboxes { public static void render(EventRender3D event, ColorSetting color) { + GlStateManager.pushMatrix(); GlStateManager.depthMask(false); GlStateManager.disableTexture2D(); GlStateManager.disableLighting(); @@ -45,5 +46,6 @@ public static void render(EventRender3D event, ColorSetting color) { GlStateManager.enableCull(); GlStateManager.disableBlend(); GlStateManager.depthMask(true); + GlStateManager.popMatrix(); } } From 7e693dc9e87890ff2aa80d026625a5a681987b91 Mon Sep 17 00:00:00 2001 From: SuperSkidder Date: Mon, 21 Jul 2025 15:32:07 +0800 Subject: [PATCH 165/193] fix: crash when click clientchat if not logged in fix: crash bug of resource pack image and some optimizations --- .../impl/interfaces/InventoryDisplay.java | 2 +- .../top/fpsmaster/utils/awt/AWTUtils.java | 18 ++++---- ...ractResourcePackMixin_DownscaleImages.java | 44 ------------------- .../fpsmaster/forge/mixin/MixinGuiChat.java | 27 +++++++----- 4 files changed, 25 insertions(+), 66 deletions(-) diff --git a/shared/java/top/fpsmaster/features/impl/interfaces/InventoryDisplay.java b/shared/java/top/fpsmaster/features/impl/interfaces/InventoryDisplay.java index 7597df4e..3573367d 100644 --- a/shared/java/top/fpsmaster/features/impl/interfaces/InventoryDisplay.java +++ b/shared/java/top/fpsmaster/features/impl/interfaces/InventoryDisplay.java @@ -6,6 +6,6 @@ public class InventoryDisplay extends InterfaceModule { public InventoryDisplay() { super("InventoryDisplay", Category.Interface); - addSettings(rounded, backgroundColor, bg, rounded, roundRadius); + addSettings(backgroundColor, bg, rounded, roundRadius); } } diff --git a/shared/java/top/fpsmaster/utils/awt/AWTUtils.java b/shared/java/top/fpsmaster/utils/awt/AWTUtils.java index b32b87d1..bec060a2 100644 --- a/shared/java/top/fpsmaster/utils/awt/AWTUtils.java +++ b/shared/java/top/fpsmaster/utils/awt/AWTUtils.java @@ -21,11 +21,9 @@ public static ResourceLocation generateRoundImage(int width, int height, int rad return generatedFull.computeIfAbsent(width + "/" + height + "/" + radius, r -> { int scaledWidth = width * 2; int scaledHeight = height * 2; - + BufferedImage bufferedImage = new BufferedImage(scaledWidth, scaledHeight, BufferedImage.TYPE_INT_ARGB); + Graphics2D graphics2D = bufferedImage.createGraphics(); try { - BufferedImage bufferedImage = new BufferedImage(scaledWidth, scaledHeight, BufferedImage.TYPE_INT_ARGB); - Graphics2D graphics2D = bufferedImage.createGraphics(); - graphics2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); graphics2D.setColor(new Color(0, 0, 0, 0)); graphics2D.fillRect(0, 0, bufferedImage.getWidth(), bufferedImage.getHeight()); @@ -39,7 +37,6 @@ public static ResourceLocation generateRoundImage(int width, int height, int rad if (mc == null || mc.getTextureManager() == null) { return null; } - graphics2D.dispose(); return mc.getTextureManager() .getDynamicTextureLocation(r + "_full", new DynamicTexture(bufferedImage)); @@ -47,6 +44,8 @@ public static ResourceLocation generateRoundImage(int width, int height, int rad ClientLogger.error("An error occurred while generating round texture: " + r); e.printStackTrace(); return null; + } finally { + graphics2D.dispose(); } }); } @@ -55,13 +54,12 @@ public static ResourceLocation[] generateRound(int radius) { if (generated.get(radius) != null) { return generated.get(radius); } + int radius2 = radius * 2; + BufferedImage bufferedImage = new BufferedImage(radius2, radius2, BufferedImage.TYPE_INT_ARGB); + java.awt.Graphics2D graphics2D = bufferedImage.createGraphics(); try { String[] fileNames = {"lt.png", "rt.png", "lb.png", "rb.png"}; // 存储文件名 - int radius2 = radius * 2; - - BufferedImage bufferedImage = new BufferedImage(radius2, radius2, BufferedImage.TYPE_INT_ARGB); - java.awt.Graphics2D graphics2D = bufferedImage.createGraphics(); graphics2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); graphics2D.setColor(Color.decode("#00000000")); graphics2D.fillRect(0, 0, bufferedImage.getWidth(), bufferedImage.getHeight()); @@ -93,6 +91,8 @@ public static ResourceLocation[] generateRound(int radius) { generated.put(radius, locations); } catch (Exception exception) { exception.printStackTrace(); + } finally { + graphics2D.dispose(); } return generated.get(radius); } diff --git a/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/AbstractResourcePackMixin_DownscaleImages.java b/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/AbstractResourcePackMixin_DownscaleImages.java index 994991d5..fe1070e0 100644 --- a/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/AbstractResourcePackMixin_DownscaleImages.java +++ b/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/AbstractResourcePackMixin_DownscaleImages.java @@ -27,12 +27,6 @@ public abstract class AbstractResourcePackMixin_DownscaleImages { return; } - // 检查是否是特殊材质(如附魔效果) - if (isSpecialTexture(image)) { - cir.setReturnValue(image); - return; - } - // 如果图片尺寸已经小于等于64x64,直接返回原图 if (image.getWidth() <= 64 && image.getHeight() <= 64) { cir.setReturnValue(image); @@ -53,42 +47,4 @@ public abstract class AbstractResourcePackMixin_DownscaleImages { } cir.setReturnValue(downscaledIcon); } - - /** - * 检查是否为特殊材质(如附魔效果) - * @param image 要检查的图片 - * @return 如果是特殊材质返回true - */ - private boolean isSpecialTexture(BufferedImage image) { - // 检查图片是否具有半透明像素(附魔效果通常有) - if (hasSemiTransparentPixels(image)) { - return true; - } - - // 可以添加其他特殊材质的检测条件 - return false; - } - - /** - * 检查图片是否包含半透明像素 - * @param image 要检查的图片 - * @return 如果包含半透明像素返回true - */ - private boolean hasSemiTransparentPixels(BufferedImage image) { - int width = image.getWidth(); - int height = image.getHeight(); - - // 只检查部分像素以提高性能 - for (int x = 0; x < width; x += Math.max(1, width / 10)) { - for (int y = 0; y < height; y += Math.max(1, height / 10)) { - int pixel = image.getRGB(x, y); - int alpha = (pixel >> 24) & 0xff; - // 如果有半透明像素(既不全透明也不全不透明) - if (alpha > 0 && alpha < 255) { - return true; - } - } - } - return false; - } } diff --git a/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinGuiChat.java b/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinGuiChat.java index a1c91523..9f64506c 100644 --- a/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinGuiChat.java +++ b/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinGuiChat.java @@ -3,6 +3,7 @@ import net.minecraft.client.gui.Gui; import net.minecraft.client.gui.GuiChat; import net.minecraft.client.gui.GuiScreen; +import org.java_websocket.enums.ReadyState; import org.lwjgl.input.Mouse; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Unique; @@ -24,21 +25,23 @@ public class MixinGuiChat extends GuiScreen { @Inject(method = "drawScreen", at = @At("HEAD")) public void drawScreen(int mouseX, int mouseY, float partialTicks, CallbackInfo ci) { - int width1 = mc.fontRendererObj.getStringWidth(FPSMaster.i18n.get("chat.mc")); - int width2 = mc.fontRendererObj.getStringWidth(FPSMaster.i18n.get("chat.irc")); + if (FPSMaster.INSTANCE.wsClient != null && FPSMaster.INSTANCE.wsClient.getReadyState() == ReadyState.OPEN) { + int width1 = mc.fontRendererObj.getStringWidth(FPSMaster.i18n.get("chat.mc")); + int width2 = mc.fontRendererObj.getStringWidth(FPSMaster.i18n.get("chat.irc")); - Gui.drawRect(2, this.height - 28, 2 + width1 + 4, this.height - 14, irc ? new Color(0, 0, 0, 180).getRGB() : new Color(80, 80, 80, 180).getRGB()); - mc.fontRendererObj.drawStringWithShadow(FPSMaster.i18n.get("chat.mc"), 4, this.height - 26, irc ? new Color(200, 200, 200).getRGB() : -1); + Gui.drawRect(2, this.height - 28, 2 + width1 + 4, this.height - 14, irc ? new Color(0, 0, 0, 180).getRGB() : new Color(80, 80, 80, 180).getRGB()); + mc.fontRendererObj.drawStringWithShadow(FPSMaster.i18n.get("chat.mc"), 4, this.height - 26, irc ? new Color(200, 200, 200).getRGB() : -1); - Gui.drawRect(2 + width1 + 4, this.height - 28, 2 + width1 + 6 + width2 + 2, this.height - 14, irc ? new Color(80, 80, 80, 180).getRGB() : new Color(0, 0, 0, 180).getRGB()); - mc.fontRendererObj.drawStringWithShadow(FPSMaster.i18n.get("chat.irc"), 4 + width1 + 4, this.height - 26, irc ? -1 : new Color(200, 200, 200).getRGB()); + Gui.drawRect(2 + width1 + 4, this.height - 28, 2 + width1 + 6 + width2 + 2, this.height - 14, irc ? new Color(80, 80, 80, 180).getRGB() : new Color(0, 0, 0, 180).getRGB()); + mc.fontRendererObj.drawStringWithShadow(FPSMaster.i18n.get("chat.irc"), 4 + width1 + 4, this.height - 26, irc ? -1 : new Color(200, 200, 200).getRGB()); - if (Mouse.isButtonDown(0)) { - if (Render2DUtils.isHovered(2, this.height - 28, width1 + 4, 12, mouseX, mouseY)) { - irc = false; - } else if (Render2DUtils.isHovered(2 + width1 + 4, this.height - 28, width2 + 2, 12, mouseX, mouseY)) { - irc = true; + if (Mouse.isButtonDown(0)) { + if (Render2DUtils.isHovered(2, this.height - 28, width1 + 4, 12, mouseX, mouseY)) { + irc = false; + } else if (Render2DUtils.isHovered(2 + width1 + 4, this.height - 28, width2 + 2, 12, mouseX, mouseY)) { + irc = true; + } } } } @@ -46,7 +49,7 @@ public void drawScreen(int mouseX, int mouseY, float partialTicks, CallbackInfo @Redirect(method = "keyTyped", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/GuiChat;sendChatMessage(Ljava/lang/String;)V")) public void sendChatMessage(GuiChat instance, String message) { - if (irc) { + if (irc && FPSMaster.INSTANCE.wsClient != null && FPSMaster.INSTANCE.wsClient.getReadyState() == ReadyState.OPEN) { FPSMaster.INSTANCE.wsClient.sendMessage(message); } else { instance.sendChatMessage(message); From 35da5a40d4ba4388e8757ad2f714b17eee5713d7 Mon Sep 17 00:00:00 2001 From: SuperSkidder Date: Mon, 21 Jul 2025 15:57:01 +0800 Subject: [PATCH 166/193] fix: load bug when cosmetic load failed fix: autogg bug --- shared/java/top/fpsmaster/features/impl/utility/AutoGG.java | 2 +- shared/java/top/fpsmaster/modules/account/Cosmetic.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/shared/java/top/fpsmaster/features/impl/utility/AutoGG.java b/shared/java/top/fpsmaster/features/impl/utility/AutoGG.java index e2b301eb..2d9c45c2 100644 --- a/shared/java/top/fpsmaster/features/impl/utility/AutoGG.java +++ b/shared/java/top/fpsmaster/features/impl/utility/AutoGG.java @@ -48,12 +48,12 @@ public void onPacket(EventPacket event) { if (hasPlayCommand) { if (autoPlay.getValue()) { FPSMaster.async.runnable(() -> { + Utility.sendClientNotify("Sending you to the next game in " + delay.getValue() + " seconds"); try { Thread.sleep(delay.getValue().longValue() * 1000); } catch (InterruptedException e) { throw new RuntimeException(e); } - Utility.sendClientNotify("Sending you to the next game in " + delay.getValue() + " seconds"); Utility.sendChatMessage(componentValue.substring(componentValue.indexOf("value='") + 7, componentValue.indexOf("'}"))); }); } diff --git a/shared/java/top/fpsmaster/modules/account/Cosmetic.java b/shared/java/top/fpsmaster/modules/account/Cosmetic.java index d48df695..4526a89b 100644 --- a/shared/java/top/fpsmaster/modules/account/Cosmetic.java +++ b/shared/java/top/fpsmaster/modules/account/Cosmetic.java @@ -55,11 +55,11 @@ public void load() { downloadImageData.setBufferedImage(frame.image); mc.getTextureManager().loadTexture(textureLocation, downloadImageData); } + loaded = true; } catch (IOException e) { throw new RuntimeException(e); } } }); - loaded = true; } } From f9270878de383f0589fed6b10a37390bf3243cec Mon Sep 17 00:00:00 2001 From: SuperSkidder Date: Mon, 21 Jul 2025 16:27:47 +0800 Subject: [PATCH 167/193] change: crosshair default config --- .../top/fpsmaster/features/impl/render/Crosshair.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/shared/java/top/fpsmaster/features/impl/render/Crosshair.java b/shared/java/top/fpsmaster/features/impl/render/Crosshair.java index 6282d3ac..3b8d970f 100644 --- a/shared/java/top/fpsmaster/features/impl/render/Crosshair.java +++ b/shared/java/top/fpsmaster/features/impl/render/Crosshair.java @@ -20,15 +20,15 @@ import java.awt.*; public class Crosshair extends Module { - private final NumberSetting dynamic = new NumberSetting("Dynamic", 4, 0, 10, 0.1); + private final NumberSetting dynamic = new NumberSetting("Dynamic", 3.0, 0, 10, 0.1); private final BooleanSetting outline = new BooleanSetting("Outline", true); - private final NumberSetting outlineWidth = new NumberSetting("OutlineWidth", 1, 0, 10, 0.1, outline::getValue); + private final NumberSetting outlineWidth = new NumberSetting("OutlineWidth", 0.8, 0, 10, 0.1, outline::getValue); private final BooleanSetting dot = new BooleanSetting("Dot", true); - private final NumberSetting gap = new NumberSetting("Gap", 6, 0, 10, 0.1); + private final NumberSetting gap = new NumberSetting("Gap", 3.5, 0, 10, 0.1); private final NumberSetting width = new NumberSetting("Width", 0.6, 0, 10, 0.1); - private final NumberSetting length = new NumberSetting("Length", 3.5, 0, 10, 0.1); + private final NumberSetting length = new NumberSetting("Length", 3.0, 0, 10, 0.1); private final ColorSetting color = new ColorSetting("Color", new Color(255, 255, 255)); - private final ColorSetting outlineColor = new ColorSetting("OutlineColor", new Color(161, 161, 161), outline::getValue); + private final ColorSetting outlineColor = new ColorSetting("OutlineColor", new Color(0, 0, 0), outline::getValue); private final ColorSetting enemyColor = new ColorSetting("Enemy", new Color(255, 55, 50)); private final ColorSetting friendColor = new ColorSetting("Friend", new Color(20, 255, 55)); From a3d71d5764443fc8eb81b2878ed17d9d37a0e1b4 Mon Sep 17 00:00:00 2001 From: SuperSkidder Date: Mon, 21 Jul 2025 16:38:59 +0800 Subject: [PATCH 168/193] feat: keystrokes font color --- .../top/fpsmaster/features/impl/interfaces/Keystrokes.java | 4 +++- .../top/fpsmaster/ui/custom/impl/KeystrokesComponent.java | 6 +++--- shared/resources/assets/minecraft/client/lang/en_us.lang | 2 ++ shared/resources/assets/minecraft/client/lang/zh_cn.lang | 2 ++ 4 files changed, 10 insertions(+), 4 deletions(-) diff --git a/shared/java/top/fpsmaster/features/impl/interfaces/Keystrokes.java b/shared/java/top/fpsmaster/features/impl/interfaces/Keystrokes.java index d54d9938..2df23f42 100644 --- a/shared/java/top/fpsmaster/features/impl/interfaces/Keystrokes.java +++ b/shared/java/top/fpsmaster/features/impl/interfaces/Keystrokes.java @@ -8,9 +8,11 @@ public class Keystrokes extends InterfaceModule { public static ColorSetting pressedColor = new ColorSetting("PressedColor", new Color(255, 255, 255, 120)); + public static ColorSetting fontColor = new ColorSetting("FontColor", new Color(255, 255, 255)); + public static ColorSetting pressedFontColor = new ColorSetting("PressedFontColor", new Color(201, 201, 201)); public Keystrokes() { super("Keystrokes", Category.Interface); - addSettings(fontShadow, betterFont, pressedColor, spacing, bg, backgroundColor, rounded, roundRadius); + addSettings(fontShadow, betterFont, pressedColor, fontColor, pressedFontColor, spacing, bg, backgroundColor, rounded, roundRadius); } } \ No newline at end of file diff --git a/shared/java/top/fpsmaster/ui/custom/impl/KeystrokesComponent.java b/shared/java/top/fpsmaster/ui/custom/impl/KeystrokesComponent.java index 3eb17bbe..c3b836c7 100644 --- a/shared/java/top/fpsmaster/ui/custom/impl/KeystrokesComponent.java +++ b/shared/java/top/fpsmaster/ui/custom/impl/KeystrokesComponent.java @@ -80,15 +80,15 @@ public void render(float x, float y, float speed, Color color, Color color1) { if (keyCode == -1) { pressed = Mouse.isButtonDown(0); drawRect(x + xOffset, y + yOffset, 28f, 18f, this.color.getColor()); - drawString(16, name, x + xOffset + 7, y + yOffset + 4, -1); + drawString(16, name, x + xOffset + 7, y + yOffset + 4, pressed ? Keystrokes.fontColor.getRGB() : Keystrokes.pressedFontColor.getRGB()); } else if (keyCode == -2) { pressed = Mouse.isButtonDown(1); drawRect(x + xOffset - 10, y + yOffset, 28f, 18f, this.color.getColor()); - drawString(16, name, x + xOffset - 4, y + yOffset + 4, -1); + drawString(16, name, x + xOffset - 4, y + yOffset + 4, pressed ? Keystrokes.fontColor.getRGB() : Keystrokes.pressedFontColor.getRGB()); } else { pressed = Keyboard.isKeyDown(keyCode); drawRect(x + xOffset, y + yOffset, 18f, 18f, this.color.getColor()); - drawString(16, name, x + xOffset + 9 - getStringWidth(16, name) / 2f, y + yOffset + 4, -1); + drawString(16, name, x + xOffset + 9 - getStringWidth(16, name) / 2f, y + yOffset + 4, pressed ? Keystrokes.fontColor.getRGB() : Keystrokes.pressedFontColor.getRGB()); } this.color.base(pressed ? color1 : color); diff --git a/shared/resources/assets/minecraft/client/lang/en_us.lang b/shared/resources/assets/minecraft/client/lang/en_us.lang index 30e4432d..20666e29 100644 --- a/shared/resources/assets/minecraft/client/lang/en_us.lang +++ b/shared/resources/assets/minecraft/client/lang/en_us.lang @@ -115,6 +115,8 @@ keystrokes.betterfont=Clean Font keystrokes.roundradius=Corner Radius keystrokes.background=Show Background keystrokes.spacing=Spacing +keystrokes.fontcolor=FontColor +keystrokes.pressedfontcolor=PressedFontColor potiondisplay=Potion HUD potiondisplay.desc=Displays active potion effects diff --git a/shared/resources/assets/minecraft/client/lang/zh_cn.lang b/shared/resources/assets/minecraft/client/lang/zh_cn.lang index 7dfa2119..3bb83bcc 100644 --- a/shared/resources/assets/minecraft/client/lang/zh_cn.lang +++ b/shared/resources/assets/minecraft/client/lang/zh_cn.lang @@ -115,6 +115,8 @@ keystrokes.betterfont=更好的字体 keystrokes.roundradius=圆角半径 keystrokes.background=背景 keystrokes.spacing=间距 +keystrokes.fontcolor=字体颜色 +keystrokes.pressedfontcolor=按下字体颜色 potiondisplay=药水显示 potiondisplay.desc=显示玩家的药水效果 From 9b46d3e0efadda01d266777d07a9e9995278a41c Mon Sep 17 00:00:00 2001 From: SuperSkidder Date: Mon, 21 Jul 2025 17:26:45 +0800 Subject: [PATCH 169/193] fix: music player skipping songs --- shared/java/top/fpsmaster/features/GlobalListener.java | 8 +++++++- .../java/top/fpsmaster/modules/music/netease/Music.java | 2 +- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/shared/java/top/fpsmaster/features/GlobalListener.java b/shared/java/top/fpsmaster/features/GlobalListener.java index 55c40fa8..15906867 100644 --- a/shared/java/top/fpsmaster/features/GlobalListener.java +++ b/shared/java/top/fpsmaster/features/GlobalListener.java @@ -15,6 +15,7 @@ import top.fpsmaster.modules.account.Cosmetic; import top.fpsmaster.modules.client.ClientUser; import top.fpsmaster.modules.music.MusicPlayer; +import top.fpsmaster.modules.music.netease.Music; import top.fpsmaster.ui.notification.NotificationManager; import top.fpsmaster.utils.Utility; import top.fpsmaster.utils.math.MathTimer; @@ -71,8 +72,13 @@ public void onTick(EventTick e) throws URISyntaxException { } catch (InterruptedException ex) { throw new RuntimeException(ex); } - if (MusicPlayer.isPlaying && MusicPlayer.getPlayProgress() > 0.999) { + if (MusicPlayer.isPlaying && MusicPlayer.getPlayProgress() > 0.999 && (Music.downloadThread == null || !Music.downloadThread.isAlive())) { MusicPlayer.playList.next(); + try { + Thread.sleep(20000); + } catch (InterruptedException ex) { + throw new RuntimeException(ex); + } } if (ProviderManager.mcProvider.getWorld() != null) { Utility.flush(); diff --git a/shared/java/top/fpsmaster/modules/music/netease/Music.java b/shared/java/top/fpsmaster/modules/music/netease/Music.java index ab26f875..5e8f4852 100644 --- a/shared/java/top/fpsmaster/modules/music/netease/Music.java +++ b/shared/java/top/fpsmaster/modules/music/netease/Music.java @@ -18,7 +18,7 @@ public class Music extends AbstractMusic { String imgURL; String musicURL; public String id; - static Thread downloadThread; + public static Thread downloadThread; public Music(long id, String name, String artists, String picUrl) { this.name = name; From b6fb5a0e22df441f9cd609512e22fa43a90c878e Mon Sep 17 00:00:00 2001 From: SuperSkidder Date: Tue, 22 Jul 2025 01:11:12 +0800 Subject: [PATCH 170/193] feat: new music panel fix some bugs some adjusts --- shared/java/top/fpsmaster/FPSMaster.java | 2 + .../fpsmaster/features/GlobalListener.java | 16 +- .../features/impl/optimizes/Performance.java | 2 +- .../features/impl/render/FireModifier.java | 2 +- .../fpsmaster/modules/account/Cosmetic.java | 3 +- .../modules/music/IngameOverlay.java | 2 +- .../fpsmaster/modules/music/JLayerHelper.java | 10 +- .../fpsmaster/modules/music/MusicPlayer.java | 21 +- .../top/fpsmaster/modules/music/Track.java | 123 ++++++ .../modules/music/netease/Music.java | 7 +- .../modules/music/netease/NeteaseApi.java | 28 ++ .../modules/music/netease/NeteaseProfile.java | 13 + .../netease/deserialize/MusicWrapper.java | 65 ++- .../top/fpsmaster/ui/click/MainPanel.java | 35 +- .../fpsmaster/ui/click/music/MusicPanel.java | 2 - .../ui/click/music/NewMusicPanel.java | 401 +++++++++++++++++- .../music/components/PLayListComponent.java | 7 - .../ui/custom/impl/LyricsComponent.java | 31 +- .../ui/custom/impl/MusicComponent.java | 25 +- .../ui/screens/mainmenu/MainMenu.java | 10 +- .../top/fpsmaster/utils/awt/KMeansUtil.java | 212 +++++++++ .../top/fpsmaster/utils/os/HttpRequest.java | 34 ++ .../fpsmaster/utils/render/Render2DUtils.java | 28 ++ 23 files changed, 984 insertions(+), 95 deletions(-) create mode 100644 shared/java/top/fpsmaster/modules/music/Track.java create mode 100644 shared/java/top/fpsmaster/modules/music/netease/NeteaseProfile.java delete mode 100644 shared/java/top/fpsmaster/ui/click/music/components/PLayListComponent.java create mode 100644 shared/java/top/fpsmaster/utils/awt/KMeansUtil.java diff --git a/shared/java/top/fpsmaster/FPSMaster.java b/shared/java/top/fpsmaster/FPSMaster.java index c935c08f..e21b9e9f 100644 --- a/shared/java/top/fpsmaster/FPSMaster.java +++ b/shared/java/top/fpsmaster/FPSMaster.java @@ -17,6 +17,7 @@ import top.fpsmaster.modules.music.MusicPlayer; import top.fpsmaster.modules.music.netease.NeteaseApi; import top.fpsmaster.ui.click.music.MusicPanel; +import top.fpsmaster.ui.click.music.NewMusicPanel; import top.fpsmaster.ui.custom.ComponentsManager; import top.fpsmaster.ui.screens.oobe.OOBEScreen; import top.fpsmaster.utils.GitInfo; @@ -102,6 +103,7 @@ private void initializeConfigures() throws Exception { MusicPlayer.setVolume(Float.parseFloat(configManager.configure.getOrCreate("volume", "1"))); NeteaseApi.cookies = FileUtils.readTempValue("cookies"); MusicPanel.nickname = FileUtils.readTempValue("nickname"); + NewMusicPanel.nickname = FileUtils.readTempValue("nickname"); accountManager.autoLogin(); } diff --git a/shared/java/top/fpsmaster/features/GlobalListener.java b/shared/java/top/fpsmaster/features/GlobalListener.java index 15906867..cb75ed39 100644 --- a/shared/java/top/fpsmaster/features/GlobalListener.java +++ b/shared/java/top/fpsmaster/features/GlobalListener.java @@ -72,14 +72,14 @@ public void onTick(EventTick e) throws URISyntaxException { } catch (InterruptedException ex) { throw new RuntimeException(ex); } - if (MusicPlayer.isPlaying && MusicPlayer.getPlayProgress() > 0.999 && (Music.downloadThread == null || !Music.downloadThread.isAlive())) { - MusicPlayer.playList.next(); - try { - Thread.sleep(20000); - } catch (InterruptedException ex) { - throw new RuntimeException(ex); - } - } +// if (MusicPlayer.isPlaying && MusicPlayer.getPlayProgress() > 0.999 && (Music.downloadThread == null || !Music.downloadThread.isAlive())) { +// MusicPlayer.playList.next(); +// try { +// Thread.sleep(20000); +// } catch (InterruptedException ex) { +// throw new RuntimeException(ex); +// } +// } if (ProviderManager.mcProvider.getWorld() != null) { Utility.flush(); } diff --git a/shared/java/top/fpsmaster/features/impl/optimizes/Performance.java b/shared/java/top/fpsmaster/features/impl/optimizes/Performance.java index 98a46f06..a95c310a 100644 --- a/shared/java/top/fpsmaster/features/impl/optimizes/Performance.java +++ b/shared/java/top/fpsmaster/features/impl/optimizes/Performance.java @@ -26,7 +26,7 @@ public class Performance extends Module { public static NumberSetting chunkUpdateLimit = new NumberSetting("ChunkUpdateLimit", 50, 0, 250, 1); public static NumberSetting fpsLimit = new NumberSetting("FPSLimit", 30, 0, 360, 1); public static NumberSetting entityLimit = new NumberSetting("EntityLimit", 200, 0, 800, 1); - public static NumberSetting particlesLimit = new NumberSetting("ParticlesLimit", 100, 0, 2000, 1); + public static NumberSetting particlesLimit = new NumberSetting("ParticlesLimit", 400, 0, 2000, 1); public Performance() { super("Performance", Category.OPTIMIZE); diff --git a/shared/java/top/fpsmaster/features/impl/render/FireModifier.java b/shared/java/top/fpsmaster/features/impl/render/FireModifier.java index fc59ea52..b9343fd9 100644 --- a/shared/java/top/fpsmaster/features/impl/render/FireModifier.java +++ b/shared/java/top/fpsmaster/features/impl/render/FireModifier.java @@ -11,7 +11,7 @@ public class FireModifier extends Module { public static boolean using = false; - public static final NumberSetting height = new NumberSetting("Height", 0.5, 0, 0.7, 0.1); + public static final NumberSetting height = new NumberSetting("Height", 0.2, 0, 0.7, 0.1); public static final BooleanSetting customColor = new BooleanSetting("CustomColor", false); public static final ColorSetting colorSetting = new ColorSetting("Color", new Color(255, 0, 0), customColor::getValue); diff --git a/shared/java/top/fpsmaster/modules/account/Cosmetic.java b/shared/java/top/fpsmaster/modules/account/Cosmetic.java index 4526a89b..e52858ab 100644 --- a/shared/java/top/fpsmaster/modules/account/Cosmetic.java +++ b/shared/java/top/fpsmaster/modules/account/Cosmetic.java @@ -41,8 +41,7 @@ public void load() { try { downloadImageData.setBufferedImage(HttpRequest.downloadImage(resource)); mc.getTextureManager().loadTexture(textureLocation, downloadImageData); - } catch (IOException e) { - throw new RuntimeException(e); + } catch (IOException ignored) { } } else if (resource.endsWith(".gif")) { try { diff --git a/shared/java/top/fpsmaster/modules/music/IngameOverlay.java b/shared/java/top/fpsmaster/modules/music/IngameOverlay.java index 3d0e8abc..1407c315 100644 --- a/shared/java/top/fpsmaster/modules/music/IngameOverlay.java +++ b/shared/java/top/fpsmaster/modules/music/IngameOverlay.java @@ -17,7 +17,7 @@ public class IngameOverlay { private static double[] smoothCurve = new double[0]; public static void onRender() { - if (MusicPlayer.playList.getCurrent() != -1) { + if (MusicPlayer.isPlaying) { ScaledResolution sr = new ScaledResolution(Utility.mc); double[] curve = MusicPlayer.getCurve(); if (curve.length != 0) { diff --git a/shared/java/top/fpsmaster/modules/music/JLayerHelper.java b/shared/java/top/fpsmaster/modules/music/JLayerHelper.java index 09162d27..d42b1cab 100644 --- a/shared/java/top/fpsmaster/modules/music/JLayerHelper.java +++ b/shared/java/top/fpsmaster/modules/music/JLayerHelper.java @@ -49,7 +49,7 @@ public static void seek(float progress) { } public static void updateLoudness() { - if (clip == null || audIn == null) return; + if (clip == null || audIn == null || !clip.isActive()) return; AudioFormat format = audIn.getFormat(); if (format.getEncoding() != AudioFormat.Encoding.PCM_SIGNED || format.getSampleSizeInBits() != 16) { @@ -155,6 +155,8 @@ public static void convert(String sourcePath, String targetPath) { public static void stop() { if (clip != null) { clip.stop(); + clip.close(); + clip = null; } } @@ -167,4 +169,10 @@ public static void start() { public static double getDuration() { return clip.getMicrosecondLength() / 1000000.0 / 60.0; } + + public static void pause() { + if (clip != null) { + clip.stop(); + } + } } diff --git a/shared/java/top/fpsmaster/modules/music/MusicPlayer.java b/shared/java/top/fpsmaster/modules/music/MusicPlayer.java index edbdc63e..9c845d7f 100644 --- a/shared/java/top/fpsmaster/modules/music/MusicPlayer.java +++ b/shared/java/top/fpsmaster/modules/music/MusicPlayer.java @@ -18,17 +18,23 @@ public class MusicPlayer { private static Thread playThread; + private static float pauseAt; + public static float getPlayProgress() { - if (isPlaying && JLayerHelper.clip != null) { + if (JLayerHelper.clip != null) { curPlayProgress = JLayerHelper.getProgress(); } return min(curPlayProgress, 1f); } public static void play() { - isPlaying = true; if (JLayerHelper.clip == null) return; + isPlaying = true; JLayerHelper.start(); + if (pauseAt != 0) { + JLayerHelper.seek(pauseAt); + pauseAt = 0; + } } public static double[] getCurve() { @@ -36,12 +42,15 @@ public static double[] getCurve() { } public static void pause() { - stop(); + if (JLayerHelper.clip == null) return; + isPlaying = false; + pauseAt = getPlayProgress(); + JLayerHelper.pause(); } public static void stop() { - isPlaying = false; if (JLayerHelper.clip == null) return; + isPlaying = false; JLayerHelper.stop(); } @@ -78,4 +87,8 @@ public static void setVolume(float volume) { JLayerHelper.setVolume(volume); FPSMaster.configManager.configure.set("volume", String.valueOf(volume)); } + + public float getPauseAt() { + return pauseAt; + } } diff --git a/shared/java/top/fpsmaster/modules/music/Track.java b/shared/java/top/fpsmaster/modules/music/Track.java new file mode 100644 index 00000000..c84ecdf7 --- /dev/null +++ b/shared/java/top/fpsmaster/modules/music/Track.java @@ -0,0 +1,123 @@ +package top.fpsmaster.modules.music; + +import net.minecraft.client.renderer.ThreadDownloadImageData; +import net.minecraft.util.ResourceLocation; +import top.fpsmaster.modules.music.netease.Music; +import top.fpsmaster.modules.music.netease.deserialize.MusicWrapper; +import top.fpsmaster.utils.awt.KMeansUtil; +import top.fpsmaster.utils.os.HttpRequest; + +import java.awt.*; +import java.awt.image.BufferedImage; +import java.util.ArrayList; +import java.util.LinkedList; + +import static top.fpsmaster.utils.Utility.mc; + +public class Track { + Long id; + String name; + String picUrl; + Color dominateColor; + Color fontColor = Color.WHITE; + LinkedList musics = new LinkedList<>(); + ResourceLocation coverResource; + boolean loaded = false; + + public Track(Long id, String name, String picUrl) { + this.id = id; + this.name = name; + this.picUrl = picUrl; + } + + public Color getDominateColor() { + return dominateColor; + } + + public void setDominateColor(Color dominateColor) { + this.dominateColor = dominateColor; + } + + public Color getFontColor() { + return fontColor; + } + + public void setFontColor(Color fontColor) { + this.fontColor = fontColor; + } + + public void loadTrack() { + coverResource = new ResourceLocation("music/track/" + id); + ThreadDownloadImageData downloadImageData = new ThreadDownloadImageData(null, null, coverResource, null); + try { + BufferedImage bufferedImageIn = HttpRequest.downloadImage(picUrl); + downloadImageData.setBufferedImage(bufferedImageIn); + mc.getTextureManager().loadTexture(coverResource, downloadImageData); + dominateColor = KMeansUtil.getOneDominantColor(bufferedImageIn); + float[] hsb = new float[3]; + Color.RGBtoHSB(dominateColor.getRed(), dominateColor.getGreen(), dominateColor.getBlue(), hsb); + if (hsb[2] < 0.5) { + fontColor = new Color(Color.HSBtoRGB(hsb[0], hsb[1] * 0.1f, 0.8f)); + } else { + fontColor = new Color(Color.HSBtoRGB(hsb[0], hsb[1] * 0.1f, 0.2f)); + } + } catch (Exception ignored) { + } + } + + public void loadMusic() { + if (musics == null || musics.isEmpty()) { + PlayList playList = MusicWrapper.searchList(id.toString()); + musics = playList.getMusics(); + loaded = true; + } + } + + public boolean isLoaded() { + return loaded; + } + + public void setLoaded(boolean loaded) { + this.loaded = loaded; + } + + public ResourceLocation getCoverResource() { + return coverResource; + } + + public void setCoverResource(ResourceLocation coverResource) { + this.coverResource = coverResource; + } + + public LinkedList getMusics() { + return musics; + } + + public void setMusics(LinkedList musics) { + this.musics = musics; + } + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getPicUrl() { + return picUrl; + } + + public void setPicUrl(String picUrl) { + this.picUrl = picUrl; + } +} diff --git a/shared/java/top/fpsmaster/modules/music/netease/Music.java b/shared/java/top/fpsmaster/modules/music/netease/Music.java index 5e8f4852..71e5664c 100644 --- a/shared/java/top/fpsmaster/modules/music/netease/Music.java +++ b/shared/java/top/fpsmaster/modules/music/netease/Music.java @@ -19,6 +19,7 @@ public class Music extends AbstractMusic { String musicURL; public String id; public static Thread downloadThread; + public float downloadProgress; public Music(long id, String name, String artists, String picUrl) { this.name = name; @@ -47,6 +48,7 @@ public void loadMusic() { @Override public void play() { + MusicPlayer.stop(); File flac = new File(FileUtils.music, FileUtils.fixName(name + "(" + id + ").flac")); File mp3 = new File(FileUtils.music, FileUtils.fixName(name + "(" + id + ").mp3")); if (flac.exists() || mp3.exists()) { @@ -56,6 +58,7 @@ public void play() { } else { MusicPlayer.playFile(mp3.getAbsolutePath()); } + MusicPlayer.isPlaying = true; }).start(); } else { downloadThread = new Thread(this::download); @@ -71,7 +74,9 @@ private void download() { new File(FileUtils.music, FileUtils.fixName(name + "(" + id + ").flac")) : new File(FileUtils.music, FileUtils.fixName(name + "(" + id + ").mp3")); if (!download.exists()) { - HttpRequest.downloadFile(musicURL, download.getAbsolutePath()); + HttpRequest.downloadFile(musicURL, download.getAbsolutePath(), (downloadedBytes, totalBytes) -> { + this.downloadProgress = downloadedBytes * 1.0f / totalBytes; + }); play(); } } catch (Exception e) { diff --git a/shared/java/top/fpsmaster/modules/music/netease/NeteaseApi.java b/shared/java/top/fpsmaster/modules/music/netease/NeteaseApi.java index 541db674..c17bee05 100644 --- a/shared/java/top/fpsmaster/modules/music/netease/NeteaseApi.java +++ b/shared/java/top/fpsmaster/modules/music/netease/NeteaseApi.java @@ -1,5 +1,6 @@ package top.fpsmaster.modules.music.netease; +import com.google.gson.JsonElement; import top.fpsmaster.utils.os.HttpRequest; import java.io.IOException; @@ -107,4 +108,31 @@ public static String getAnonymous() { throw new RuntimeException(e); } } + + public static String getTracksDaily() { + String url = BASE_URL + "recommend/resource?timestamp=" + System.currentTimeMillis(); + try { + return HttpRequest.getWithCookie(url, cookies).getBody(); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + public static String getProfile() { + String url = BASE_URL + "login/status?timestamp=" + System.currentTimeMillis(); + try { + return HttpRequest.getWithCookie(url, cookies).getBody(); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + public static String getTracksLiked(long uid) { + String url = BASE_URL + "user/playlist?uid="+uid+"×tamp=" + System.currentTimeMillis(); + try { + return HttpRequest.getWithCookie(url, cookies).getBody(); + } catch (IOException e) { + throw new RuntimeException(e); + } + } } diff --git a/shared/java/top/fpsmaster/modules/music/netease/NeteaseProfile.java b/shared/java/top/fpsmaster/modules/music/netease/NeteaseProfile.java new file mode 100644 index 00000000..2733ecd9 --- /dev/null +++ b/shared/java/top/fpsmaster/modules/music/netease/NeteaseProfile.java @@ -0,0 +1,13 @@ +package top.fpsmaster.modules.music.netease; + +public class NeteaseProfile { + public long id; + public String nickname; + public String avatarUrl; + + public NeteaseProfile(long id, String nickname, String avatarUrl) { + this.id = id; + this.nickname = nickname; + this.avatarUrl = avatarUrl; + } +} diff --git a/shared/java/top/fpsmaster/modules/music/netease/deserialize/MusicWrapper.java b/shared/java/top/fpsmaster/modules/music/netease/deserialize/MusicWrapper.java index 5a8d2b21..554e2f0c 100644 --- a/shared/java/top/fpsmaster/modules/music/netease/deserialize/MusicWrapper.java +++ b/shared/java/top/fpsmaster/modules/music/netease/deserialize/MusicWrapper.java @@ -1,20 +1,17 @@ package top.fpsmaster.modules.music.netease.deserialize; -import com.google.gson.Gson; -import com.google.gson.GsonBuilder; -import com.google.gson.JsonElement; -import com.google.gson.JsonObject; +import com.google.gson.*; import top.fpsmaster.modules.logger.ClientLogger; -import top.fpsmaster.modules.music.Line; -import top.fpsmaster.modules.music.Lyrics; -import top.fpsmaster.modules.music.PlayList; -import top.fpsmaster.modules.music.Word; +import top.fpsmaster.modules.music.*; import top.fpsmaster.modules.music.netease.Music; import top.fpsmaster.modules.music.netease.NeteaseApi; +import top.fpsmaster.modules.music.netease.NeteaseProfile; import top.fpsmaster.utils.Utility; import java.net.URLEncoder; +import java.util.ArrayList; import java.util.Iterator; +import java.util.List; public class MusicWrapper { private static final Gson gson = new GsonBuilder().create(); @@ -84,6 +81,27 @@ public static PlayList getSongsFromDaily() { return playList; } + public static ArrayList getTracksDaily() { + ArrayList trackList = new ArrayList<>(); + try { + JsonObject jsonObject = gson.fromJson(NeteaseApi.getTracksDaily(), JsonObject.class); + JsonArray tracks = jsonObject.getAsJsonArray("recommend"); + for (JsonElement track : tracks) { + JsonObject trackObject = track.getAsJsonObject(); + long id1 = trackObject.get("id").getAsLong(); + String name = trackObject.get("name").getAsString(); + String picUrl = trackObject.get("picUrl").getAsString(); + Track e = new Track(id1, name, picUrl); + e.loadTrack(); + trackList.add(e); + } + } catch (Exception e) { + e.printStackTrace(); + } + return trackList; + } + + public static void loadLyrics(Music music) { try { String verbatimLyrics = NeteaseApi.getVerbatimLyrics(music.id); @@ -201,4 +219,35 @@ public static JsonObject getLoginStatus(String key) { String json = NeteaseApi.checkLoginStatus(key); return gson.fromJson(json, JsonObject.class); } + + + public static NeteaseProfile getProfile() { + JsonObject jsonObject = gson.fromJson(NeteaseApi.getProfile(), JsonObject.class); + try { + JsonObject asJsonObject = jsonObject.get("data").getAsJsonObject().get("profile").getAsJsonObject(); + return new NeteaseProfile(asJsonObject.get("userId").getAsLong(), asJsonObject.get("nickname").getAsString(), asJsonObject.get("avatarUrl").getAsString()); + }catch (Exception ignored) { + return null; + } + } + + public static ArrayList getTracksLiked(long uid) { + ArrayList trackList = new ArrayList<>(); + try { + JsonObject jsonObject = gson.fromJson(NeteaseApi.getTracksLiked(uid), JsonObject.class); + JsonArray tracks = jsonObject.getAsJsonArray("playlist"); + for (JsonElement track : tracks) { + JsonObject trackObject = track.getAsJsonObject(); + long id1 = trackObject.get("id").getAsLong(); + String name = trackObject.get("name").getAsString(); + String picUrl = trackObject.get("coverImgUrl").getAsString(); + Track e = new Track(id1, name, picUrl); + e.loadTrack(); + trackList.add(e); + } + } catch (Exception e) { + e.printStackTrace(); + } + return trackList; + } } diff --git a/shared/java/top/fpsmaster/ui/click/MainPanel.java b/shared/java/top/fpsmaster/ui/click/MainPanel.java index 52ef8f54..29bc71cd 100644 --- a/shared/java/top/fpsmaster/ui/click/MainPanel.java +++ b/shared/java/top/fpsmaster/ui/click/MainPanel.java @@ -13,6 +13,7 @@ import top.fpsmaster.ui.click.component.ScrollContainer; import top.fpsmaster.ui.click.modules.ModuleRenderer; import top.fpsmaster.ui.click.music.MusicPanel; +import top.fpsmaster.ui.click.music.NewMusicPanel; import top.fpsmaster.utils.math.animation.Animation; import top.fpsmaster.utils.math.animation.AnimationUtils; import top.fpsmaster.utils.math.animation.Type; @@ -103,18 +104,17 @@ public void render(int mouseX, int mouseY, float partialTicks) { -1 ); - GL11.glEnable(GL11.GL_SCISSOR_TEST); - Render2DUtils.doGlScissor( - x, y + 10, width, - (height - 18), - scaleFactor - ); - moduleListAlpha = (float) AnimationUtils.base(moduleListAlpha, 255.0, 0.1f); if (curType == Category.Music) { - MusicPanel.draw(x + leftWidth, y, width - leftWidth, height, mouseX, mouseY, scaleFactor); + NewMusicPanel.draw(x + leftWidth, y, width - leftWidth, height, mouseX, mouseY, scaleFactor); } else { + GL11.glEnable(GL11.GL_SCISSOR_TEST); + Render2DUtils.doGlScissor( + x, y + 10, width, + (height - 18), + scaleFactor + ); modHeight = 20f; float containerWidth = width - leftWidth - 10; int finalMouseY = mouseY; @@ -140,16 +140,10 @@ public void render(int mouseX, int mouseY, float partialTicks) { } modsContainer.setHeight(modHeight); }); + GL11.glEnable(GL11.GL_BLEND); + GL11.glDisable(GL11.GL_SCISSOR_TEST); } -// Render2DUtils.drawRect( -// x + leftWidth, y, -// width - leftWidth, height, -// Render2DUtils.reAlpha(new Color(39, 39, 39), Render2DUtils.limit(255 - moduleListAlpha)) -// ); - - GL11.glEnable(GL11.GL_BLEND); - GL11.glDisable(GL11.GL_SCISSOR_TEST); if (Render2DUtils.isHoveredWithoutScale(x, (int) (y + height / 2 - 70), categoryAnimation, 140, mouseX, mouseY)) { @@ -239,7 +233,8 @@ public void updateScreen() { @Override public void initGui() { super.initGui(); - aiChatPanel.init(); +// aiChatPanel.init(); + NewMusicPanel.init(); scaleAnimation.fstart(0.8, 1.0, 0.2f, Type.EASE_IN_OUT_QUAD); close = false; @@ -274,7 +269,7 @@ public void onGuiClosed() { @Override public void keyTyped(char typedChar, int keyCode) throws IOException { - aiChatPanel.keyTyped(typedChar, keyCode); +// aiChatPanel.keyTyped(typedChar, keyCode); if (keyCode == 1) { if (scaleAnimation.end != 0.1) { @@ -290,7 +285,7 @@ public void keyTyped(char typedChar, int keyCode) throws IOException { } } - MusicPanel.keyTyped(typedChar, keyCode); + NewMusicPanel.keyTyped(typedChar, keyCode); super.keyTyped(typedChar, keyCode); } @@ -339,7 +334,7 @@ public void onClick(int mouseX, int mouseY, int mouseButton) { } if (curType == Category.Music) { - MusicPanel.mouseClicked(mouseX, mouseY, mouseButton); + NewMusicPanel.mouseClicked(mouseX, mouseY, mouseButton); } else { float modsY = y + 22f + modsContainer.getRealScroll(); for (ModuleRenderer m : mods) { diff --git a/shared/java/top/fpsmaster/ui/click/music/MusicPanel.java b/shared/java/top/fpsmaster/ui/click/music/MusicPanel.java index 0de604c3..d021e1a0 100644 --- a/shared/java/top/fpsmaster/ui/click/music/MusicPanel.java +++ b/shared/java/top/fpsmaster/ui/click/music/MusicPanel.java @@ -66,7 +66,6 @@ public static void mouseClicked(int mouseX, int mouseY, int btn) { if (Render2DUtils.isHovered(x, dY, width - 10f, 40f, mouseX, mouseY) && mouseY < y + height - 34 && mouseY > y + 34) { if (Mouse.isButtonDown(0)) { music.play(); - MusicPlayer.isPlaying = true; MusicPlayer.playList.current = MusicPlayer.playList.musics.indexOf(music); } } @@ -132,7 +131,6 @@ public static void mouseClicked(int mouseX, int mouseY, int btn) { if (MusicPlayer.isPlaying) { playProgress = MusicPlayer.getPlayProgress(); MusicPlayer.playList.pause(); - MusicPlayer.isPlaying = false; } else { FPSMaster.async.runnable(() -> { MusicPlayer.playList.current().play(); diff --git a/shared/java/top/fpsmaster/ui/click/music/NewMusicPanel.java b/shared/java/top/fpsmaster/ui/click/music/NewMusicPanel.java index 5f10088a..b099525a 100644 --- a/shared/java/top/fpsmaster/ui/click/music/NewMusicPanel.java +++ b/shared/java/top/fpsmaster/ui/click/music/NewMusicPanel.java @@ -1,43 +1,414 @@ package top.fpsmaster.ui.click.music; +import com.google.gson.JsonObject; +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.ThreadDownloadImageData; +import net.minecraft.client.renderer.texture.TextureManager; import net.minecraft.util.ResourceLocation; +import org.lwjgl.opengl.GL11; import top.fpsmaster.FPSMaster; -import top.fpsmaster.modules.music.PlayList; +import top.fpsmaster.exception.ExceptionHandler; +import top.fpsmaster.exception.FileException; +import top.fpsmaster.font.impl.UFontRenderer; +import top.fpsmaster.forge.api.IMinecraft; +import top.fpsmaster.modules.music.*; +import top.fpsmaster.modules.music.netease.Music; +import top.fpsmaster.modules.music.netease.NeteaseApi; +import top.fpsmaster.modules.music.netease.NeteaseProfile; +import top.fpsmaster.modules.music.netease.deserialize.MusicWrapper; +import top.fpsmaster.ui.click.component.ScrollContainer; +import top.fpsmaster.ui.common.TextField; +import top.fpsmaster.utils.os.FileUtils; import top.fpsmaster.utils.render.Render2DUtils; import java.awt.*; +import java.io.File; +import java.util.ArrayList; +import java.util.Base64; + +import static top.fpsmaster.utils.Utility.mc; public class NewMusicPanel { - private static Thread playThread; - private static final PlayList playList = new PlayList(); - private static final PlayList displayList = new PlayList(); + // Threads + private static Thread loginThread = null; + private static Thread songsLoadThread = null; + private static Thread playThread = null; + + // login + static boolean isWaitingLogin = false; + static int loginCode; + public static String nickname = ""; + private static String key; + private static ArrayList dailyTracks = new ArrayList<>(); + private static ArrayList likedTracks = new ArrayList<>(); + + static Track recommendTrack; + static Thread loadThread = null; + + // tracks + static Track currentTrack; + + public static Music playing; + static NeteaseProfile profile; + private static Track playingTrack; + + + // search + public static TextField searchField = new TextField(FPSMaster.fontManager.s14, "搜索歌曲", new Color(56, 56, 56).getRGB(), new Color(200, 200, 200).getRGB(), 50, NewMusicPanel::search); + static boolean searching = false; + + public static void search() { + FPSMaster.async.runnable(() -> { + searching = true; + currentTrack = new Track(-1L, "", ""); + PlayList playList = MusicWrapper.searchSongs(searchField.getText()); + currentTrack.setMusics(playList.musics); + currentTrack.setLoaded(true); + searching = false; + }); + } + + int mode = 0; + + public static void init() { + if (playThread == null) { + playThread = new Thread(() -> { + while (((IMinecraft) mc).arch$getRunning()) { + if (playing != null) { + // next song + if (MusicPlayer.getPlayProgress() > 0.999f) { + MusicPlayer.isPlaying = false; + nextSong(); + } + try { + Thread.sleep(5000); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + } else { + try { + Thread.sleep(10000); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + } + } + }); + playThread.start(); + } + if (loadThread == null || !loadThread.isAlive()) { + loadThread = new Thread(() -> { + profile = MusicWrapper.getProfile(); + if (recommendTrack == null || recommendTrack.getMusics().isEmpty()) { + recommendTrack = new Track(0L, "日推", ""); + recommendTrack.setMusics(MusicWrapper.getSongsFromDaily().musics); + recommendTrack.setLoaded(true); + } + if (dailyTracks.isEmpty()) { + dailyTracks = MusicWrapper.getTracksDaily(); + } + + if (likedTracks.isEmpty()) { + likedTracks = MusicWrapper.getTracksLiked(profile.id); + } + }); + loadThread.start(); + } + } + + private static void nextSong() { + int i = playingTrack.getMusics().indexOf(playing); + if (i + 1 >= playingTrack.getMusics().size()) { + i = 0; + } else { + i++; + } + playing = (Music) playingTrack.getMusics().get(i); + playing.play(); + } + + // containers + static ScrollContainer scrollContainer = new ScrollContainer(); + static ScrollContainer songsContainer = new ScrollContainer(); public static void draw(float x, int y, float width, float height, int mouseX, int mouseY, int scaleFactor) { Render2DUtils.drawImage(new ResourceLocation("client/gui/music.png"), x + 12, y + 14, 75, 16, -1); - FPSMaster.fontManager.s18.drawString("SuperSkidder", x + width - 80, y + 15, -1); + searchField.drawTextBox(x + 32, y + 14, 100, 16); + if (Render2DUtils.isHovered(x + 12, y + 14, 16, 16, mouseX, mouseY) && consumeClick(0)) { + currentTrack = null; + } + if (profile == null) { + int stringWidth = FPSMaster.fontManager.s16.getStringWidth(FPSMaster.i18n.get("music.notLoggedIn")); + Color color = new Color(162, 162, 162); + if (Render2DUtils.isHovered(x + width - stringWidth - 5, y + 15, stringWidth, 16f, mouseX, mouseY)) { + color = new Color(234, 234, 234); + if (consumeClick(0)) { + isWaitingLogin = true; + reloadImg(); + loginCode = 801; + } + } + FPSMaster.fontManager.s16.drawString(FPSMaster.i18n.get("music.notloggedin"), x + width - stringWidth - 10, y + 15, color.getRGB()); + } else { + int stringWidth = FPSMaster.fontManager.s16.getStringWidth(profile.nickname); + Render2DUtils.drawWebImage(profile.avatarUrl, x + width - stringWidth - 30, y + 14f, 16, 16); + FPSMaster.fontManager.s16.drawString(profile.nickname, x + width - stringWidth - 10, y + 15, -1); + if (Render2DUtils.isHovered(x + width - stringWidth - 10, y + 10, stringWidth, 16f, mouseX, mouseY)) { + if (consumeClick(0)) { + isWaitingLogin = true; + reloadImg(); + loginCode = 801; + } + } + } + + + if (searching) { + FPSMaster.fontManager.s22.drawCenteredString("搜索中...", x + width / 2, y + height / 2 - 20, -1); + } else { + if (currentTrack == null) { + GL11.glEnable(GL11.GL_SCISSOR_TEST); + Render2DUtils.doGlScissor(x + 12, y + 35, width - 12, height - 65, scaleFactor); + int finalY = (int) (y + scrollContainer.getScroll()); + scrollContainer.draw(x + 12, y + 35, width - 12, height - 65, mouseX, mouseY, () -> { + String recommendSong = ""; + + if (recommendTrack != null && !recommendTrack.getMusics().isEmpty()) { + recommendSong = recommendTrack.getMusics().get(0).name; + } + int tX = 0; + int tY = 60; + FPSMaster.fontManager.s22.drawString("推荐歌单", x + 20, finalY + 40, -1); + if (recommendTrack != null) + drawTrack(recommendTrack, "每日推荐", "每日推荐,从『" + recommendSong + "』听起", x + 20, finalY + 60, mouseX, mouseY, new Color(255, 73, 73, 200)); + tY = drawTracks(x, width, mouseX, mouseY, finalY, tX + 70, tY, dailyTracks); + tY += 120; + FPSMaster.fontManager.s22.drawString("收藏的歌单", x + 20, finalY + tY - 20, -1); + tY = drawTracks(x, width, mouseX, mouseY, finalY, tX, tY, likedTracks); + scrollContainer.setHeight(tY + 80); + }); + GL11.glDisable(GL11.GL_SCISSOR_TEST); + } else { + GL11.glEnable(GL11.GL_SCISSOR_TEST); + Render2DUtils.doGlScissor(x + 12, y + 35, width - 12, height - 65, scaleFactor); + if (!currentTrack.isLoaded() && (songsLoadThread == null || !songsLoadThread.isAlive())) { + songsLoadThread = new Thread(() -> { + currentTrack.loadMusic(); + }); + songsLoadThread.start(); + } + if (currentTrack.isLoaded()) { + int finalY = (int) (y + songsContainer.getScroll()); + songsContainer.draw(x + 12, y + 35, width - 12, height - 65, mouseX, mouseY, () -> { + int sY = 40; + for (AbstractMusic music : currentTrack.getMusics()) { + if (finalY + sY + 25 > y + 35 && finalY + sY < y + 35 + height - 65) { + Music neteaseMusic = (Music) music; + if (neteaseMusic.isLoadedImage) { + Render2DUtils.drawImage(new ResourceLocation("music/netease/" + neteaseMusic.id), x + 20, finalY + sY, 20f, 20f, -1); + } else { + Render2DUtils.drawOptimizedRoundedRect(x + 20, finalY + sY, 20f, 20f, new Color(200, 200, 200, 255)); + } + FPSMaster.fontManager.s18.drawString(neteaseMusic.name, x + 45, finalY + sY, -1); + FPSMaster.fontManager.s14.drawString(neteaseMusic.author, x + 45, finalY + sY + 10, new Color(200, 200, 200).getRGB()); - Render2DUtils.drawOptimizedRoundedRect(x + 20, y + 50, 100, 60, new Color(225,70,70)); - Render2DUtils.drawOptimizedRoundedRect(x + 20, y + 90, 100, 20, new Color(0,0,0,100)); - FPSMaster.fontManager.s24.drawString("每日推荐", x + 25, y + 55, -1); - FPSMaster.fontManager.s14.drawString("每日推荐,从『花日』听起", x + 25, y + 95, -1); + if (Render2DUtils.isHovered(x + 45, finalY + sY + 5, 45 + FPSMaster.fontManager.s18.getStringWidth(neteaseMusic.name), 18, mouseX, mouseY) && consumeClick(0)) { + playing = (Music) music; + playingTrack = currentTrack; + music.play(); + } + } + sY += 25; + } + songsContainer.setHeight(sY); + }); + } + GL11.glDisable(GL11.GL_SCISSOR_TEST); + } - Render2DUtils.drawOptimizedRoundedRect(x + 140, y + 50, 100, 60, new Color(113, 113, 113)); - Render2DUtils.drawOptimizedRoundedRect(x + 140, y + 90, 100, 20, new Color(0,0,0,100)); - FPSMaster.fontManager.s24.drawString("本地音乐", x + 145, y + 55, -1); - FPSMaster.fontManager.s14.drawString("共检测到22首本地音乐", x + 145, y + 95, -1); + Render2DUtils.drawRoundedRectImage(x + 1, y + height - 30, width - 2, 31, 10, new Color(0, 0, 0, 150)); + if (playing != null) { + UFontRenderer s14 = FPSMaster.fontManager.s14; + s14.drawString(s14.trimString(playing.name, 100, false), x + 30, y + height - 22, new Color(234, 234, 234).getRGB()); + s14.drawString(s14.trimString(playing.author, 60, false), x + 30, y + height - 12, new Color(124, 124, 124).getRGB()); - FPSMaster.fontManager.s22.drawString("收藏歌单", x + 20, y + 125, -1); + if (playing.isLoadedImage) { + Render2DUtils.drawImage(new ResourceLocation("music/netease/" + playing.id), x + 5, y + height - 25, 20f, 20f, -1); + } else { + Render2DUtils.drawOptimizedRoundedRect(x + 5, y + height - 25, 20f, 20f, new Color(200, 200, 200, 255)); + } + // 进度条 + if (Render2DUtils.isHovered(x + width / 2 - 80, y + height - 6, 160, 3, mouseX, mouseY)) { + Render2DUtils.drawRoundedRectImage(x + width / 2 - 80, y + height - 6, 160, 3, 3, new Color(95, 95, 95)); + if (consumeClick(0)) { + playing.seek((mouseX - (x + width / 2 - 80)) / 160f); + if (!MusicPlayer.isPlaying) + MusicPlayer.play(); + } + } else { + Render2DUtils.drawRoundedRectImage(x + width / 2 - 80, y + height - 6, 160, 3, 3, new Color(51, 51, 51)); + } + float playProgress = MusicPlayer.getPlayProgress(); + if (JLayerHelper.clip == null) { + Render2DUtils.drawRoundedRectImage(x + width / 2 - 80, y + height - 6, 160f * playing.downloadProgress, 3, 3, new Color(148, 148, 148)); + } else { + Render2DUtils.drawRoundedRectImage(x + width / 2 - 80, y + height - 6, 160f * playProgress, 3, 3, new Color(225, 73, 73)); + } + + // 操作按钮 + Render2DUtils.drawImage(new ResourceLocation("client/gui/settings/music/previous.png"), x + width / 2 - 35, y + height - 25, 16f, 16f, new Color(234, 234, 234)); + Render2DUtils.drawImage(MusicPlayer.isPlaying ? new ResourceLocation("client/gui/settings/music/pause.png") : new ResourceLocation("client/gui/settings/music/play.png"), x + width / 2 - 15, y + height - 26, 35 / 2f, 35 / 2f, -1); + Render2DUtils.drawImage(new ResourceLocation("client/gui/settings/music/next.png"), x + width / 2 + 5, y + height - 25, 16f, 16f, new Color(234, 234, 234)); + + if (JLayerHelper.clip != null) { + if (Render2DUtils.isHovered(x + width / 2 - 15, y + height - 26, 35 / 2f, 35 / 2f, mouseX, mouseY) && consumeClick(0)) { + if (MusicPlayer.isPlaying) + MusicPlayer.pause(); + else + MusicPlayer.play(); + } + + double duration = JLayerHelper.getDuration(); + int minutes = (int) (duration * playProgress); + int seconds = (int) ((duration * playProgress - minutes) * 60); + String progress = minutes + ":" + seconds; + String total = (int) duration + ":" + (int) ((duration - (int) duration) * 60); + s14.drawString(progress, x + width / 2 - 80 - s14.getStringWidth(progress) - 2, y + height - 10, new Color(160, 160, 160).getRGB()); + s14.drawString(total, x + width / 2 + 80 + 2, y + height - 10, new Color(160, 160, 160).getRGB()); + } + } + } + mouseButton = -1; + } + + private static int drawTracks(float x, float width, int mouseX, int mouseY, int finalY, int tX, int tY, ArrayList likedTracks) { + for (Track track : likedTracks) { + drawTrack(track, "", track.getName(), x + 20 + tX, finalY + tY, mouseX, mouseY, new Color(0, 0, 0, 100)); + tX += 70; + if (tX >= width - 40) { + tX = 0; + tY += 90; + } + } + return tY; + } + + + private static void drawTrack(Track track, String name, String desc, float x, float y, int mouseX, int mouseY, Color color) { + if (Render2DUtils.isHovered(x, y, 60, 82, mouseX, mouseY) && consumeClick(0)) { + currentTrack = track; + } + + Render2DUtils.drawOptimizedRoundedRect(x, y, 60, 82, track.getDominateColor() == null ? new Color(202, 112, 112) : track.getDominateColor()); + if (track != null && !track.getPicUrl().isEmpty()) { + Render2DUtils.drawImage(track.getCoverResource(), x, y, 60, 60, -1); + } else { + Render2DUtils.drawOptimizedRoundedRect(x, y, 60, 60, color); + } + FPSMaster.fontManager.s18.drawString(name, x + 5, y + 5, track.getFontColor().getRGB()); + String text = FPSMaster.fontManager.s16.trimString(desc, 60, false); + FPSMaster.fontManager.s14.drawString(text, x + 2, y + 62, track.getFontColor().getRGB()); + if (desc.length() > text.length()) { + String substring = desc.substring(text.length()); + substring = FPSMaster.fontManager.s16.trimString(substring, 60, false); + FPSMaster.fontManager.s14.drawString(substring, x + 2, y + 72, track.getFontColor().getRGB()); + } } + public static void keyTyped(char typedChar, int keyCode) { + searchField.textboxKeyTyped(typedChar, keyCode); + } + + + static int mouseButton = -1; + + public static void mouseClicked(int mouseX, int mouseY, int btn) { + mouseButton = btn; + searchField.mouseClicked(mouseX, mouseY, btn); + } + public static boolean consumeClick(int btn) { + boolean temp = mouseButton == btn; + if (temp) + mouseButton = -1; + return temp; } - public static void mouseClicked(int mouseX, int mouseY, int mouseButton) { + private static void reloadImg() { + loginThread = new Thread(() -> { + while (isWaitingLogin) { + try { + JsonObject loginStatus = MusicWrapper.getLoginStatus(key); + loginCode = loginStatus.get("code").getAsInt(); + if (loginCode == 802) { + String element = loginStatus.get("nickname").getAsString(); + if (element != null) { + nickname = element; + try { + FileUtils.saveTempValue("nickname", nickname); + } catch (FileException e) { + ExceptionHandler.handleFileException(e, "无法保存昵称"); + } + } + } + if (loginCode == 803) { + // parse cookie + String asString = loginStatus.get("cookie").getAsString(); + String result = "MUSIC_U=" + subString(asString, "MUSIC_U=", ";") + "; " + "NMTID=" + subString(asString, "NMTID=", ";"); + NeteaseApi.cookies = result; + + try { + FileUtils.saveTempValue("cookies", NeteaseApi.cookies); + System.out.println("cookies: " + NeteaseApi.cookies); + } catch (FileException e) { + ExceptionHandler.handleFileException(e, "无法保存cookies"); + } + } + Thread.sleep(1000); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + } + }); + FPSMaster.async.runnable(() -> { + key = MusicWrapper.getQRKey(); + if (key == null) return; + String base64 = MusicWrapper.getQRCodeImg(key); + // render base64 img data + TextureManager textureManager = Minecraft.getMinecraft().getTextureManager(); + // base64 decode + byte[] bytes = Base64.getDecoder().decode(base64); + // create resource location + ResourceLocation resourceLocation = new ResourceLocation("music/qr"); + File qr = new File(FileUtils.dir, "/music/qr.png"); + File qrf = new File(FileUtils.dir, "/music"); + qrf.mkdirs(); + try { + FileUtils.saveFileBytes("/music/qr.png", bytes); + ThreadDownloadImageData textureArt = new ThreadDownloadImageData(qr, null, null, null); + textureManager.loadTexture(resourceLocation, textureArt); + loginThread.start(); + } catch (FileException e) { + ExceptionHandler.handleFileException(e, "无法保存二维码图片"); + } + }); + } + + private static String subString(String input, String prefix, String suffix) { + int startIndex = input.indexOf(prefix); + if (startIndex != -1) { + int endIndex = input.indexOf(suffix, startIndex + prefix.length()); + if (endIndex != -1) { + return input.substring(startIndex + prefix.length(), endIndex); + } + } + return ""; } + } diff --git a/shared/java/top/fpsmaster/ui/click/music/components/PLayListComponent.java b/shared/java/top/fpsmaster/ui/click/music/components/PLayListComponent.java deleted file mode 100644 index 1d8a22ba..00000000 --- a/shared/java/top/fpsmaster/ui/click/music/components/PLayListComponent.java +++ /dev/null @@ -1,7 +0,0 @@ -package top.fpsmaster.ui.click.music.components; - -public class PLayListComponent { - int playListId; - - -} diff --git a/shared/java/top/fpsmaster/ui/custom/impl/LyricsComponent.java b/shared/java/top/fpsmaster/ui/custom/impl/LyricsComponent.java index 7cdbbc2d..05282c55 100644 --- a/shared/java/top/fpsmaster/ui/custom/impl/LyricsComponent.java +++ b/shared/java/top/fpsmaster/ui/custom/impl/LyricsComponent.java @@ -1,7 +1,10 @@ package top.fpsmaster.ui.custom.impl; +import net.minecraft.client.renderer.GlStateManager; +import org.lwjgl.opengl.GL11; import top.fpsmaster.features.impl.interfaces.LyricsDisplay; import top.fpsmaster.modules.music.*; +import top.fpsmaster.ui.click.music.NewMusicPanel; import top.fpsmaster.ui.custom.Component; import top.fpsmaster.ui.custom.Position; import top.fpsmaster.utils.math.animation.Animation; @@ -36,8 +39,12 @@ public void draw(float x, float y) { width = 200f; height = 70f; drawRect(x, y, width, height, mod.backgroundColor.getColor()); - y += 10; - AbstractMusic current = MusicPlayer.playList.current(); + if (((LyricsDisplay) mod).scale.getValue()) { + y += 10; + }else{ + y += 5; + } + AbstractMusic current = NewMusicPanel.playing; if (current != null && current.lyrics != null) { int curLine = -1; List lines = current.lyrics.lines; @@ -66,11 +73,15 @@ public void draw(float x, float y) { } if (curLine != -1) { - for (int j = curLine - 2; j <= curLine + 2; j++) { + for (int j = curLine - 3; j <= curLine + 2; j++) { if (j >= 0 && j < lines.size()) { Line line = lines.get(j); String content = line.getContent(); - float xOffset = x + (width - getStringWidth(20, content)) / 2; + float stringWidth = getStringWidth(20, content); + float xOffset = x + (width - stringWidth) / 2; + if (this.width < stringWidth + 10) { + this.width = stringWidth + 10; + } if (j == curLine) { line.animation = (float) AnimationUtils.base(line.animation, 0.0, 0.1f); line.alpha = (float) AnimationUtils.base(line.alpha, 1.0, 0.1f); @@ -95,17 +106,21 @@ private void drawLine(Line line, float xOffset, float y, int font, boolean curre if (lyrics.scale.getValue()) { //default scale ratio float scaleRatio = 1.0f; - if(line.finished || current) { + if(current) { line.scaleAnimation.start(1.0,1.3,0.3f,Type.LINEAR); - line.scaleAnimation.update(); - scaleRatio = (float) line.scaleAnimation.value; + }else{ + line.scaleAnimation.start(line.scaleAnimation.value,1.0,0.3f,Type.LINEAR); } + line.scaleAnimation.update(); + scaleRatio = (float) line.scaleAnimation.value; Render2DUtils.scaleStart(xOffset + (getStringWidth(20, line.getContent()) / 2.0f), y + (getStringHeight(20) / 2.0f), scaleRatio); + GL11.glTranslated(0, -8, 0); } for (Word word : line.words) { xOffset += current ? drawWord(word, xOffset, y, line) : drawWordBG(word, xOffset, y, line); } if (lyrics.scale.getValue()) { + GL11.glTranslated(0, 8, 0); Render2DUtils.scaleEnd(); } } @@ -115,7 +130,7 @@ private float drawWord(Word word, float xOffset, float y, Line line) { if (duration >= word.time) { float animation = 0.3f + (float) (duration - word.time) / word.duration; float animation2 = (float) (duration - word.time) / word.duration; - drawString(20, word.content, xOffset, y + 7 - Math.min(animation2, 1f) * 3, + drawString(20, word.content, xOffset, y + 7 - Math.min(animation2, 1f), Render2DUtils.reAlpha(LyricsDisplay.textColor.getColor(), (int) Math.min(animation * 255, 255)).getRGB()); }else { drawString(20, word.content, xOffset, y + 7, diff --git a/shared/java/top/fpsmaster/ui/custom/impl/MusicComponent.java b/shared/java/top/fpsmaster/ui/custom/impl/MusicComponent.java index 0d36828e..28415fd3 100644 --- a/shared/java/top/fpsmaster/ui/custom/impl/MusicComponent.java +++ b/shared/java/top/fpsmaster/ui/custom/impl/MusicComponent.java @@ -5,6 +5,7 @@ import top.fpsmaster.modules.music.AbstractMusic; import top.fpsmaster.modules.music.MusicPlayer; import top.fpsmaster.modules.music.netease.Music; +import top.fpsmaster.ui.click.music.NewMusicPanel; import top.fpsmaster.ui.custom.Component; import top.fpsmaster.ui.custom.Position; import top.fpsmaster.utils.math.animation.AnimationUtils; @@ -24,7 +25,7 @@ public MusicComponent() { } private void drawSong(float x, float y, float width, float height) { - Music current = (Music) MusicPlayer.playList.current(); + Music current = NewMusicPanel.playing; if (current == null) { return; } @@ -32,14 +33,16 @@ private void drawSong(float x, float y, float width, float height) { drawRect(x, y, songProgress, height, MusicOverlay.progressColor.getColor()); songProgress = (float) AnimationUtils.base(songProgress, (6 + (width - 6) * MusicPlayer.getPlayProgress()), 0.1); - Render2DUtils.drawImage( - new ResourceLocation("music/netease/" + current.id), - x + 5, - y + 5, - height - 10, - height - 10, - -1 - ); + if (current.isLoadedImage) { + Render2DUtils.drawImage( + new ResourceLocation("music/netease/" + current.id), + x + 5, + y + 5, + height - 10, + height - 10, + -1 + ); + } drawString(18, current.name, x + 40, y + 6, new Color(234, 234, 234).getRGB()); drawString(16, current.author, x + 40, y + 18, new Color(162, 162, 162).getRGB()); @@ -49,8 +52,8 @@ private void drawSong(float x, float y, float width, float height) { public void draw(float x, float y) { super.draw(x, y); - AbstractMusic current = MusicPlayer.playList.current(); - if (!MusicPlayer.playList.getMusics().isEmpty() && current != null) { + Music current = NewMusicPanel.playing; + if (current != null) { float width = Math.max( getStringWidth(18, current.name), getStringWidth(18, current.author) ); diff --git a/shared/java/top/fpsmaster/ui/screens/mainmenu/MainMenu.java b/shared/java/top/fpsmaster/ui/screens/mainmenu/MainMenu.java index cac5d700..ab3b58fc 100644 --- a/shared/java/top/fpsmaster/ui/screens/mainmenu/MainMenu.java +++ b/shared/java/top/fpsmaster/ui/screens/mainmenu/MainMenu.java @@ -44,11 +44,11 @@ public MainMenu() { @Override public void initGui() { ProviderManager.mainmenuProvider.initGui(); - if (!MusicPlayer.playList.getMusics().isEmpty()) { - if (MusicPlayer.isPlaying) { - MusicPlayer.playList.pause(); - } - } +// if (!MusicPlayer.playList.getMusics().isEmpty()) { +// if (MusicPlayer.isPlaying) { +// MusicPlayer.playList.pause(); +// } +// } } @Override diff --git a/shared/java/top/fpsmaster/utils/awt/KMeansUtil.java b/shared/java/top/fpsmaster/utils/awt/KMeansUtil.java new file mode 100644 index 00000000..8414d3df --- /dev/null +++ b/shared/java/top/fpsmaster/utils/awt/KMeansUtil.java @@ -0,0 +1,212 @@ +package top.fpsmaster.utils.awt; + +import org.lwjgl.Sys; + +import javax.imageio.ImageIO; +import java.awt.*; +import java.awt.image.BufferedImage; +import java.io.File; +import java.io.IOException; +import java.util.*; +import java.util.List; + +public class KMeansUtil { + static class ColorPoint { + public int r, g, b; + + public ColorPoint(int r, int g, int b) { + this.r = r; + this.g = g; + this.b = b; + } + + public double distanceTo(ColorPoint other) { + int dr = this.r - other.r; + int dg = this.g - other.g; + int db = this.b - other.b; + return Math.sqrt(dr * dr + dg * dg + db * db); + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + ColorPoint that = (ColorPoint) o; + return r == that.r && g == that.g && b == that.b; + } + + @Override + public int hashCode() { + return java.util.Objects.hash(r, g, b); + } + + @Override + public String toString() { + return "(" + r + ", " + g + ", " + b + ")"; + } + } + + public static Color getOneDominantColor(BufferedImage image) { + image = resizeImage(image,64); + List dominantColors = getDominantColorsKMeans(image, 1, 100); + return dominantColors.get(0); + } + + // K-Means 聚类算法的核心实现 + public static BufferedImage resizeImage(BufferedImage originalImage, int targetWidth) { + int originalWidth = originalImage.getWidth(); + int originalHeight = originalImage.getHeight(); + + // 如果目标宽度大于或等于原图宽度,则不进行缩放 + if (targetWidth >= originalWidth) { + return originalImage; + } + + double aspectRatio = (double) originalHeight / originalWidth; + int targetHeight = (int) (targetWidth * aspectRatio); + + BufferedImage resizedImage = new BufferedImage(targetWidth, targetHeight, BufferedImage.TYPE_INT_RGB); + Graphics2D g = resizedImage.createGraphics(); + + // 设置渲染质量,这里使用高质量缩放 + g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR); + g.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY); + g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + + g.drawImage(originalImage, 0, 0, targetWidth, targetHeight, null); + g.dispose(); + return resizedImage; + } + + // K-Means 聚类算法的核心实现,与之前版本相同,但使用 ColorPoint + public static List getDominantColorsKMeans(BufferedImage image, int k, int maxIterations) { + if (k <= 0) { + throw new IllegalArgumentException("K must be a positive integer."); + } + + List pixels = new ArrayList<>(); + int width = image.getWidth(); + int height = image.getHeight(); + + // 1. 提取所有像素颜色数据 + for (int y = 0; y < height; y++) { + for (int x = 0; x < width; x++) { + int rgb = image.getRGB(x, y); + // 忽略 Alpha 通道,只取 RGB + pixels.add(new ColorPoint((rgb >> 16) & 0xFF, (rgb >> 8) & 0xFF, rgb & 0xFF)); + } + } + + // 如果图片像素点少于 K,则直接返回所有像素颜色 + if (pixels.size() < k) { + System.out.println("Warning: Image has fewer pixels than K. Returning all unique pixels."); + return pixels.stream() + .map(cp -> new Color(cp.r, cp.g, cp.b)) + .distinct() // 移除重复颜色 + .collect(ArrayList::new, ArrayList::add, ArrayList::addAll); // Collectors.toList() 会生成不可变列表 + } + + + // 2. 初始化 K 个随机质心 + List centroids = new ArrayList<>(); + Random random = new Random(); + for (int i = 0; i < k; i++) { + centroids.add(pixels.get(random.nextInt(pixels.size()))); + } + + List oldCentroids; + for (int iter = 0; iter < maxIterations; iter++) { + oldCentroids = new ArrayList<>(centroids); + + // 存储每个质心对应的像素列表 + Map> clusters = new HashMap<>(); + // 为了解决HashMap键的引用问题,我们需要一个辅助映射来找到当前质心在clusters中的键 + Map centroidToMapKey = new HashMap<>(); + for (ColorPoint centroid : centroids) { + ColorPoint key = new ColorPoint(centroid.r, centroid.g, centroid.b); // 使用一个新实例作为Map的键 + clusters.put(key, new ArrayList<>()); + centroidToMapKey.put(centroid, key); + } + + // 3. 分配阶段:将每个像素分配到最近的质心 + for (ColorPoint pixel : pixels) { + ColorPoint closestCentroid = null; + double minDistance = Double.MAX_VALUE; + + for (ColorPoint centroid : centroids) { + double distance = pixel.distanceTo(centroid); + if (distance < minDistance) { + minDistance = distance; + closestCentroid = centroid; + } + } + if (closestCentroid != null) { + // 确保获取到的是clusters中实际的键引用 + clusters.get(centroidToMapKey.get(closestCentroid)).add(pixel); + } + } + + // 4. 更新阶段:重新计算质心 + List newCentroids = new ArrayList<>(); + for (ColorPoint centroid : centroids) { + // 查找对应的簇列表 + List clusterPixels = null; + for(Map.Entry> entry : clusters.entrySet()){ + if(entry.getKey().equals(centroid)){ + clusterPixels = entry.getValue(); + break; + } + } + + if (clusterPixels == null || clusterPixels.isEmpty()) { + newCentroids.add(new ColorPoint(centroid.r, centroid.g, centroid.b)); // 保持原质心,使用新实例 + continue; + } + + long sumR = 0, sumG = 0, sumB = 0; + for (ColorPoint pixel : clusterPixels) { + sumR += pixel.r; + sumG += pixel.g; + sumB += pixel.b; + } + newCentroids.add(new ColorPoint( + (int) (sumR / clusterPixels.size()), + (int) (sumG / clusterPixels.size()), + (int) (sumB / clusterPixels.size()) + )); + } + centroids = newCentroids; // 更新质心 + + // 5. 收敛判断:如果质心不再变化,则停止迭代 + boolean converged = true; + for (int i = 0; i < k; i++) { + // 确保索引不越界 + if (i >= centroids.size() || i >= oldCentroids.size() || + centroids.get(i).distanceTo(oldCentroids.get(i)) > 0.1) { + converged = false; + break; + } + } + if (converged) { + System.out.println("K-Means converged at iteration: " + (iter + 1)); + break; + } + } + + // 6. 返回最终的主导色 (质心) + List dominantColors = new ArrayList<>(); + for (ColorPoint centroid : centroids) { + dominantColors.add(new Color(centroid.r, centroid.g, centroid.b)); + } + return dominantColors; + } + + // 计算两个颜色点之间的欧几里得距离 (在 RGB 空间中) + // 参数修改为 List + private static double getEuclideanDistance(List pixel1, List pixel2) { + int dr = pixel1.get(0) - pixel2.get(0); + int dg = pixel1.get(1) - pixel2.get(1); + int db = pixel1.get(2) - pixel2.get(2); + return Math.sqrt(dr * dr + dg * dg + db * db); + } +} diff --git a/shared/java/top/fpsmaster/utils/os/HttpRequest.java b/shared/java/top/fpsmaster/utils/os/HttpRequest.java index c7552024..327e18eb 100644 --- a/shared/java/top/fpsmaster/utils/os/HttpRequest.java +++ b/shared/java/top/fpsmaster/utils/os/HttpRequest.java @@ -143,6 +143,40 @@ public static boolean downloadFile(String url, String filepath) { } } + public static boolean downloadFile(String url, String filepath, ProgressCallback callback) { + try { + HttpResponse response = HTTP_CLIENT.execute(new HttpGet(url)); + HttpEntity entity = response.getEntity(); + long totalSize = entity.getContentLength(); + + try (InputStream is = entity.getContent(); + FileOutputStream fos = new FileOutputStream(filepath)) { + + byte[] buffer = new byte[8192]; + int bytesRead; + long downloadedSize = 0; + + while ((bytesRead = is.read(buffer)) != -1) { + fos.write(buffer, 0, bytesRead); + downloadedSize += bytesRead; + + // Invoke progress callback if provided + if (callback != null) { + callback.onProgress(downloadedSize, totalSize); + } + } + return true; + } + } catch (Exception e) { + ClientLogger.error("Download failed: " + e.getMessage()); + return false; + } + } + + public interface ProgressCallback { + void onProgress(long downloadedBytes, long totalBytes); + } + // download file to buffer public static InputStream downloadFile(String url) { try { diff --git a/shared/java/top/fpsmaster/utils/render/Render2DUtils.java b/shared/java/top/fpsmaster/utils/render/Render2DUtils.java index 36fbba05..18493167 100644 --- a/shared/java/top/fpsmaster/utils/render/Render2DUtils.java +++ b/shared/java/top/fpsmaster/utils/render/Render2DUtils.java @@ -22,6 +22,7 @@ import top.fpsmaster.utils.awt.AWTUtils; import top.fpsmaster.utils.math.animation.AnimationUtils; import top.fpsmaster.utils.os.FileUtils; +import top.fpsmaster.utils.os.HttpRequest; import top.fpsmaster.utils.os.OSUtil; import top.fpsmaster.utils.render.shader.GLSLSandboxShader; import top.fpsmaster.utils.render.shader.KawaseBlur; @@ -30,6 +31,8 @@ import java.awt.*; import java.io.File; +import java.io.IOException; +import java.util.ArrayList; import static org.lwjgl.opengl.GL11.*; @@ -312,4 +315,29 @@ public static void drawBackground(int guiWidth, int guiHeight, int mouseX, int m } } } + + static ArrayList downloadingImages = new ArrayList<>(); + static ArrayList downloadedImages = new ArrayList<>(); + + + public static void drawWebImage(String url, float x, float y, int width, int height) { + if (downloadingImages.contains(url)){ + drawRoundedRectImage(x, y, width, height, 5, new Color(194, 194, 194, 255)); + } else if (downloadedImages.contains(url)) { + drawImage(new ResourceLocation(url), x, y, width, height, -1); + }else{ + downloadingImages.add(url); + FPSMaster.async.runnable(()->{ + ResourceLocation textureLocation = new ResourceLocation(url); + ThreadDownloadImageData downloadImageData = new ThreadDownloadImageData(null, null, textureLocation, null); + try { + downloadImageData.setBufferedImage(HttpRequest.downloadImage(url)); + mc.getTextureManager().loadTexture(textureLocation, downloadImageData); + } catch (IOException ignored) { + } + downloadedImages.add(url); + downloadingImages.remove(url); + }); + } + } } From 70879bfa4f1a78d1c534a552beb15d4a7f173344 Mon Sep 17 00:00:00 2001 From: SuperSkidder Date: Tue, 22 Jul 2025 01:17:36 +0800 Subject: [PATCH 171/193] feat: add some loading screen to music player --- .../java/top/fpsmaster/ui/click/music/NewMusicPanel.java | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/shared/java/top/fpsmaster/ui/click/music/NewMusicPanel.java b/shared/java/top/fpsmaster/ui/click/music/NewMusicPanel.java index b099525a..1d4ada1c 100644 --- a/shared/java/top/fpsmaster/ui/click/music/NewMusicPanel.java +++ b/shared/java/top/fpsmaster/ui/click/music/NewMusicPanel.java @@ -99,7 +99,9 @@ public static void init() { } if (loadThread == null || !loadThread.isAlive()) { loadThread = new Thread(() -> { - profile = MusicWrapper.getProfile(); + searching = true; + if (profile == null) + profile = MusicWrapper.getProfile(); if (recommendTrack == null || recommendTrack.getMusics().isEmpty()) { recommendTrack = new Track(0L, "日推", ""); recommendTrack.setMusics(MusicWrapper.getSongsFromDaily().musics); @@ -112,6 +114,7 @@ public static void init() { if (likedTracks.isEmpty()) { likedTracks = MusicWrapper.getTracksLiked(profile.id); } + searching = false; }); loadThread.start(); } @@ -166,7 +169,7 @@ public static void draw(float x, int y, float width, float height, int mouseX, i if (searching) { - FPSMaster.fontManager.s22.drawCenteredString("搜索中...", x + width / 2, y + height / 2 - 20, -1); + FPSMaster.fontManager.s22.drawCenteredString("加载中...", x + width / 2, y + height / 2 - 20, -1); } else { if (currentTrack == null) { GL11.glEnable(GL11.GL_SCISSOR_TEST); @@ -196,7 +199,9 @@ public static void draw(float x, int y, float width, float height, int mouseX, i Render2DUtils.doGlScissor(x + 12, y + 35, width - 12, height - 65, scaleFactor); if (!currentTrack.isLoaded() && (songsLoadThread == null || !songsLoadThread.isAlive())) { songsLoadThread = new Thread(() -> { + searching = true; currentTrack.loadMusic(); + searching = false; }); songsLoadThread.start(); } From 035e8c326616640c1104dee0fd52ca8927d1c88a Mon Sep 17 00:00:00 2001 From: SuperSkidder Date: Tue, 22 Jul 2025 01:19:45 +0800 Subject: [PATCH 172/193] fix: lyrics display width bug --- shared/java/top/fpsmaster/ui/custom/impl/LyricsComponent.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/shared/java/top/fpsmaster/ui/custom/impl/LyricsComponent.java b/shared/java/top/fpsmaster/ui/custom/impl/LyricsComponent.java index 05282c55..dbe38c2a 100644 --- a/shared/java/top/fpsmaster/ui/custom/impl/LyricsComponent.java +++ b/shared/java/top/fpsmaster/ui/custom/impl/LyricsComponent.java @@ -21,6 +21,8 @@ public LyricsComponent() { super(LyricsDisplay.class); x = 0.5f; y = 0.2f; + width = 200f; + height = 70f; position = Position.CT; } @@ -36,8 +38,6 @@ private long fromTimeTick(String timeTick) { @Override public void draw(float x, float y) { super.draw(x, y); - width = 200f; - height = 70f; drawRect(x, y, width, height, mod.backgroundColor.getColor()); if (((LyricsDisplay) mod).scale.getValue()) { y += 10; From ff0e6a462aa09b9af3b253ee72bfd1fcaa2ceca7 Mon Sep 17 00:00:00 2001 From: SuperSkidder Date: Tue, 22 Jul 2025 01:20:42 +0800 Subject: [PATCH 173/193] fix: lyrics display width bug (2) --- shared/java/top/fpsmaster/ui/custom/Component.java | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/shared/java/top/fpsmaster/ui/custom/Component.java b/shared/java/top/fpsmaster/ui/custom/Component.java index af3bcacb..322786ad 100644 --- a/shared/java/top/fpsmaster/ui/custom/Component.java +++ b/shared/java/top/fpsmaster/ui/custom/Component.java @@ -196,6 +196,18 @@ else if (y < guiHeight / 2f) changeY = Math.min(Math.max(changeY, 0f), guiHeight - height * scale); } + for (Component component : FPSMaster.componentsManager.components) { + if (component == this || !component.shouldDisplay()) { + continue; + } + // auto align + + if (Math.abs(changeX - component.getRealPosition()[0]) < 2){ + changeX = component.getRealPosition()[0]; + Render2DUtils.drawRect(component.getRealPosition()[0] - 0.5f, 0, 1, guiHeight, Color.WHITE); + } + } + this.x = changeX / guiWidth * 2f; this.y = changeY / guiHeight * 2f; } From 759f7d80d9e6cd48789b9c267dbeda3f440d754d Mon Sep 17 00:00:00 2001 From: SuperSkidder Date: Tue, 22 Jul 2025 01:20:53 +0800 Subject: [PATCH 174/193] Revert "fix: lyrics display width bug (2)" This reverts commit ff0e6a462aa09b9af3b253ee72bfd1fcaa2ceca7. --- shared/java/top/fpsmaster/ui/custom/Component.java | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/shared/java/top/fpsmaster/ui/custom/Component.java b/shared/java/top/fpsmaster/ui/custom/Component.java index 322786ad..af3bcacb 100644 --- a/shared/java/top/fpsmaster/ui/custom/Component.java +++ b/shared/java/top/fpsmaster/ui/custom/Component.java @@ -196,18 +196,6 @@ else if (y < guiHeight / 2f) changeY = Math.min(Math.max(changeY, 0f), guiHeight - height * scale); } - for (Component component : FPSMaster.componentsManager.components) { - if (component == this || !component.shouldDisplay()) { - continue; - } - // auto align - - if (Math.abs(changeX - component.getRealPosition()[0]) < 2){ - changeX = component.getRealPosition()[0]; - Render2DUtils.drawRect(component.getRealPosition()[0] - 0.5f, 0, 1, guiHeight, Color.WHITE); - } - } - this.x = changeX / guiWidth * 2f; this.y = changeY / guiHeight * 2f; } From b581495b238293cff4c1f4f4c2fc67f839e27cac Mon Sep 17 00:00:00 2001 From: SuperSkidder Date: Tue, 22 Jul 2025 01:21:14 +0800 Subject: [PATCH 175/193] fix: lyrics display width bug (2) --- shared/java/top/fpsmaster/ui/custom/impl/LyricsComponent.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/shared/java/top/fpsmaster/ui/custom/impl/LyricsComponent.java b/shared/java/top/fpsmaster/ui/custom/impl/LyricsComponent.java index dbe38c2a..818e983d 100644 --- a/shared/java/top/fpsmaster/ui/custom/impl/LyricsComponent.java +++ b/shared/java/top/fpsmaster/ui/custom/impl/LyricsComponent.java @@ -21,7 +21,6 @@ public LyricsComponent() { super(LyricsDisplay.class); x = 0.5f; y = 0.2f; - width = 200f; height = 70f; position = Position.CT; } @@ -79,6 +78,7 @@ public void draw(float x, float y) { String content = line.getContent(); float stringWidth = getStringWidth(20, content); float xOffset = x + (width - stringWidth) / 2; + width = 200f; if (this.width < stringWidth + 10) { this.width = stringWidth + 10; } From 9b7d4177bd0556a8b3f43046eb5917b05168011d Mon Sep 17 00:00:00 2001 From: SuperSkidder Date: Tue, 22 Jul 2025 12:34:09 +0800 Subject: [PATCH 176/193] feat: add game lag detection fix: reach display bug --- .../top/fpsmaster/event/EventDispatcher.java | 22 +++++ .../impl/interfaces/ReachDisplay.java | 3 +- .../forge/mixin/MixinEntityRenderer.java | 91 +++++++++++++++++++ 3 files changed, 114 insertions(+), 2 deletions(-) diff --git a/shared/java/top/fpsmaster/event/EventDispatcher.java b/shared/java/top/fpsmaster/event/EventDispatcher.java index d68b7fa6..c98fa13f 100644 --- a/shared/java/top/fpsmaster/event/EventDispatcher.java +++ b/shared/java/top/fpsmaster/event/EventDispatcher.java @@ -1,7 +1,9 @@ package top.fpsmaster.event; import top.fpsmaster.exception.ExceptionHandler; +import top.fpsmaster.modules.dev.DevMode; import top.fpsmaster.modules.logger.ClientLogger; +import top.fpsmaster.utils.Utility; import java.lang.reflect.Method; import java.util.HashMap; @@ -35,13 +37,27 @@ public static void unregisterListener(Object listener) { public static void dispatchEvent(Event event) { List listeners = eventListeners.get(event.getClass()); if (listeners != null) { + long l1 = System.currentTimeMillis(); for (Handler listener : listeners) { try { +// Map usedTime = new HashMap<>(); + long l = System.currentTimeMillis(); listener.invoke(event); + long time = System.currentTimeMillis() - l; +// usedTime.put(listener.getListener().getClass().getSimpleName(), time); + if (time > 3) { + String msg = "Event " + event.getClass().getSimpleName() + " in " + listener.listener.getClass().getSimpleName() + " took " + time + "ms to process"; + Utility.sendClientDebug(msg); + ClientLogger.warn(msg); + for (StackTraceElement stackTraceElement : Thread.currentThread().getStackTrace()) { + ClientLogger.warn(stackTraceElement.toString()); + } + } } catch (Throwable e) { ClientLogger.warn("Failed to dispatch event " + event.getClass().getSimpleName() + " to listener " + listener.getLog()); if (e instanceof Exception) { ExceptionHandler.handleModuleException((Exception) e, "Failed to dispatch event " + event.getClass().getSimpleName()); + e.printStackTrace(); } else { // For non-Exception Throwables, we still need to log them ClientLogger.error("Non-Exception Throwable: " + e.getMessage()); @@ -49,6 +65,12 @@ public static void dispatchEvent(Event event) { } } } + long time2 = System.currentTimeMillis() - l1; + if (time2 > 50) { + String msg = "Client events took " + time2 + "ms to process! please see logs to check it."; + Utility.sendClientDebug(msg); + ClientLogger.warn(msg); + } } } } diff --git a/shared/java/top/fpsmaster/features/impl/interfaces/ReachDisplay.java b/shared/java/top/fpsmaster/features/impl/interfaces/ReachDisplay.java index f211ffec..5051435a 100644 --- a/shared/java/top/fpsmaster/features/impl/interfaces/ReachDisplay.java +++ b/shared/java/top/fpsmaster/features/impl/interfaces/ReachDisplay.java @@ -23,6 +23,7 @@ public class ReachDisplay extends InterfaceModule { public static double reach = 0.0; public static ColorSetting textColor = new ColorSetting("TextColor", new Color(255, 255, 255)); + public static double distance; public ReachDisplay() { super("ReachDisplay", Category.Interface); @@ -33,10 +34,8 @@ public ReachDisplay() { public void onAttack(EventAttack e) { Entity entity = mc.getRenderViewEntity(); if (entity != null && ProviderManager.mcProvider.getWorld() != null) { - Vec3 vec3d = entity.getPositionEyes(ProviderManager.timerProvider.getRenderPartialTicks()); if (mc.objectMouseOver == null || mc.objectMouseOver.entityHit == null) return; - double distance = mc.objectMouseOver.hitVec.distanceTo(vec3d); reach = Double.parseDouble(String.format("%.2f", distance)); } } diff --git a/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinEntityRenderer.java b/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinEntityRenderer.java index 55ed8dd0..ec0b2e43 100644 --- a/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinEntityRenderer.java +++ b/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinEntityRenderer.java @@ -1,5 +1,7 @@ package top.fpsmaster.forge.mixin; +import com.google.common.base.Predicate; +import com.google.common.base.Predicates; import net.minecraft.block.Block; import net.minecraft.block.material.Material; import net.minecraft.block.state.IBlockState; @@ -11,6 +13,7 @@ import net.minecraft.client.shader.ShaderGroup; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.item.EntityItemFrame; import net.minecraft.entity.passive.EntityAnimal; import net.minecraft.util.*; import net.minecraftforge.client.ForgeHooksClient; @@ -27,6 +30,7 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; import top.fpsmaster.event.EventDispatcher; import top.fpsmaster.event.events.EventRender3D; +import top.fpsmaster.features.impl.interfaces.ReachDisplay; import top.fpsmaster.features.impl.optimizes.NoHurtCam; import top.fpsmaster.features.impl.optimizes.OldAnimations; import top.fpsmaster.features.impl.optimizes.SmoothZoom; @@ -34,6 +38,8 @@ import top.fpsmaster.features.impl.render.MinimizedBobbing; import top.fpsmaster.utils.math.MathUtils; +import java.util.List; + import static top.fpsmaster.utils.Utility.mc; @Mixin(EntityRenderer.class) @@ -295,4 +301,89 @@ public void freelook(float partialTicks, long nanoTime, CallbackInfo ci) { FreeLook.overrideMouse(); } + + @Shadow + private Entity pointedEntity; + + /** + * @author SuperSkidder + * @reason Reach Display + */ + @Overwrite + public void getMouseOver(float partialTicks) { + Entity entity = mc.getRenderViewEntity(); + if (entity != null && mc.theWorld != null) { + mc.mcProfiler.startSection("pick"); + mc.pointedEntity = null; + double d0 = (double) mc.playerController.getBlockReachDistance(); + mc.objectMouseOver = entity.rayTrace(d0, partialTicks); + double d1 = d0; + Vec3 vec3 = entity.getPositionEyes(partialTicks); + boolean flag = false; + int i = 3; + if (mc.playerController.extendedReach()) { + d0 = (double) 6.0F; + d1 = (double) 6.0F; + } else if (d0 > (double) 3.0F) { + flag = true; + } + + if (mc.objectMouseOver != null) { + d1 = mc.objectMouseOver.hitVec.distanceTo(vec3); + } + + Vec3 vec31 = entity.getLook(partialTicks); + Vec3 vec32 = vec3.addVector(vec31.xCoord * d0, vec31.yCoord * d0, vec31.zCoord * d0); + this.pointedEntity = null; + Vec3 vec33 = null; + float f = 1.0F; + List list = mc.theWorld.getEntitiesInAABBexcluding(entity, entity.getEntityBoundingBox().addCoord(vec31.xCoord * d0, vec31.yCoord * d0, vec31.zCoord * d0).expand((double) f, (double) f, (double) f), Predicates.and(EntitySelectors.NOT_SPECTATING, Entity::canBeCollidedWith)); + double d2 = d1; + + for (int j = 0; j < list.size(); ++j) { + Entity entity1 = (Entity) list.get(j); + float f1 = entity1.getCollisionBorderSize(); + AxisAlignedBB axisalignedbb = entity1.getEntityBoundingBox().expand((double) f1, (double) f1, (double) f1); + MovingObjectPosition movingobjectposition = axisalignedbb.calculateIntercept(vec3, vec32); + if (axisalignedbb.isVecInside(vec3)) { + if (d2 >= (double) 0.0F) { + this.pointedEntity = entity1; + vec33 = movingobjectposition == null ? vec3 : movingobjectposition.hitVec; + d2 = (double) 0.0F; + } + } else if (movingobjectposition != null) { + double d3 = vec3.distanceTo(movingobjectposition.hitVec); + if (d3 < d2 || d2 == (double) 0.0F) { + if (entity1 == entity.ridingEntity && !entity.canRiderInteract()) { + if (d2 == (double) 0.0F) { + this.pointedEntity = entity1; + vec33 = movingobjectposition.hitVec; + } + } else { + this.pointedEntity = entity1; + vec33 = movingobjectposition.hitVec; + d2 = d3; + } + } + } + } + + double v = vec3.distanceTo(vec33); + if (this.pointedEntity != null && flag && v > (double) 3.0F) { + this.pointedEntity = null; + mc.objectMouseOver = new MovingObjectPosition(MovingObjectPosition.MovingObjectType.MISS, vec33, (EnumFacing) null, new BlockPos(vec33)); + } + + if (this.pointedEntity != null && (d2 < d1 || mc.objectMouseOver == null)) { + mc.objectMouseOver = new MovingObjectPosition(this.pointedEntity, vec33); + if (this.pointedEntity instanceof EntityLivingBase || this.pointedEntity instanceof EntityItemFrame) { + mc.pointedEntity = this.pointedEntity; + ReachDisplay.distance = v; + } + } + + mc.mcProfiler.endSection(); + } + } + } From f1a3145e1744c953b5c63957b5183756b0c885c9 Mon Sep 17 00:00:00 2001 From: SuperSkidder Date: Tue, 22 Jul 2025 12:46:07 +0800 Subject: [PATCH 177/193] fix: reach display crash --- .../java/top/fpsmaster/forge/mixin/MixinEntityRenderer.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinEntityRenderer.java b/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinEntityRenderer.java index ec0b2e43..ba2cfd65 100644 --- a/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinEntityRenderer.java +++ b/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinEntityRenderer.java @@ -368,8 +368,9 @@ public void getMouseOver(float partialTicks) { } } - double v = vec3.distanceTo(vec33); - if (this.pointedEntity != null && flag && v > (double) 3.0F) { + double v = 0; + if (this.pointedEntity != null && flag && vec3.distanceTo(vec33) > (double) 3.0F) { + v = vec3.distanceTo(vec33); this.pointedEntity = null; mc.objectMouseOver = new MovingObjectPosition(MovingObjectPosition.MovingObjectType.MISS, vec33, (EnumFacing) null, new BlockPos(vec33)); } From 4e1545054b8e999515727fca9cb7ee1b632333c8 Mon Sep 17 00:00:00 2001 From: SuperSkidder Date: Tue, 22 Jul 2025 13:06:57 +0800 Subject: [PATCH 178/193] fix: some render bug --- .../fpsmaster/features/impl/render/DamageIndicator.java | 2 ++ .../java/top/fpsmaster/features/impl/utility/TNTTimer.java | 2 ++ .../top/fpsmaster/forge/mixin/MixinEntityRenderer.java | 5 ++++- .../java/top/fpsmaster/forge/mixin/MixinGuiIngame.java | 5 ----- .../top/fpsmaster/forge/mixin/MixinGuiIngameForge.java | 7 +++++++ .../java/top/fpsmaster/wrapper/mods/WrapperHitboxes.java | 5 +++-- 6 files changed, 18 insertions(+), 8 deletions(-) diff --git a/shared/java/top/fpsmaster/features/impl/render/DamageIndicator.java b/shared/java/top/fpsmaster/features/impl/render/DamageIndicator.java index 94ea4f73..d130f4ca 100644 --- a/shared/java/top/fpsmaster/features/impl/render/DamageIndicator.java +++ b/shared/java/top/fpsmaster/features/impl/render/DamageIndicator.java @@ -74,6 +74,7 @@ public void doRender(Damage indicator) { Minecraft mc = Minecraft.getMinecraft(); DecimalFormat df = new DecimalFormat("0.00"); String damage = df.format(-indicator.damage); + GL11.glPushAttrib(GL11.GL_ALPHA | GL11.GL_BLEND | GL11.GL_TEXTURE_2D | GL11.GL_LIGHTING | GL11.GL_DEPTH_TEST | GL11.GL_CULL_FACE); GL11.glPushMatrix(); GL11.glEnable(3042); GL11.glDisable(2929); @@ -115,6 +116,7 @@ public void doRender(Damage indicator) { GL11.glColor4f(1.0f, 1.0f, 1.0f, 1.0f); GL11.glNormal3f(1.0f, 1.0f, 1.0f); GL11.glPopMatrix(); + GL11.glPopAttrib(); } private static class Damage { diff --git a/shared/java/top/fpsmaster/features/impl/utility/TNTTimer.java b/shared/java/top/fpsmaster/features/impl/utility/TNTTimer.java index 7ff299a1..e5f2f671 100644 --- a/shared/java/top/fpsmaster/features/impl/utility/TNTTimer.java +++ b/shared/java/top/fpsmaster/features/impl/utility/TNTTimer.java @@ -38,6 +38,7 @@ public void onDisable() { public static void doRender(EntityTNTPrimed entity) { if (!using) return; Minecraft mc = Minecraft.getMinecraft(); + GL11.glPushAttrib(GL11.GL_ALPHA | GL11.GL_BLEND | GL11.GL_TEXTURE_2D | GL11.GL_LIGHTING | GL11.GL_DEPTH_TEST | GL11.GL_CULL_FACE); GL11.glPushMatrix(); GL11.glEnable(3042); GL11.glDisable(2929); @@ -67,6 +68,7 @@ public static void doRender(EntityTNTPrimed entity) { GL11.glColor4f(1.0f, 1.0f, 1.0f, 1.0f); GL11.glNormal3f(1.0f, 1.0f, 1.0f); GL11.glPopMatrix(); + GL11.glPopAttrib(); } private static void drawTime(EntityTNTPrimed entity) { diff --git a/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinEntityRenderer.java b/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinEntityRenderer.java index ba2cfd65..0aa01fe2 100644 --- a/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinEntityRenderer.java +++ b/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinEntityRenderer.java @@ -369,8 +369,11 @@ public void getMouseOver(float partialTicks) { } double v = 0; - if (this.pointedEntity != null && flag && vec3.distanceTo(vec33) > (double) 3.0F) { + if (vec33 != null) { v = vec3.distanceTo(vec33); + } + + if (this.pointedEntity != null && flag && v > (double) 3.0F) { this.pointedEntity = null; mc.objectMouseOver = new MovingObjectPosition(MovingObjectPosition.MovingObjectType.MISS, vec33, (EnumFacing) null, new BlockPos(vec33)); } diff --git a/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinGuiIngame.java b/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinGuiIngame.java index 70cc1958..c6475587 100644 --- a/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinGuiIngame.java +++ b/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinGuiIngame.java @@ -19,11 +19,6 @@ @Mixin(GuiIngame.class) public class MixinGuiIngame { - @Inject(method = "renderTooltip", at = @At("RETURN")) - private void renderTooltipPost(ScaledResolution sr, float partialTicks, CallbackInfo callbackInfo) { - EventDispatcher.dispatchEvent(new EventRender2D(partialTicks)); - } - @Inject(method = "showCrosshair", at = @At("HEAD"), cancellable = true) protected void showCrosshair(CallbackInfoReturnable cir) { if (Crosshair.using) diff --git a/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinGuiIngameForge.java b/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinGuiIngameForge.java index 5396e601..607e0c81 100644 --- a/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinGuiIngameForge.java +++ b/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinGuiIngameForge.java @@ -1,5 +1,6 @@ package top.fpsmaster.forge.mixin; +import net.minecraft.client.gui.ScaledResolution; import net.minecraft.client.renderer.GlStateManager; import net.minecraftforge.client.GuiIngameForge; import org.spongepowered.asm.mixin.Mixin; @@ -9,6 +10,7 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import top.fpsmaster.event.EventDispatcher; import top.fpsmaster.event.events.EventMotionBlur; +import top.fpsmaster.event.events.EventRender2D; import top.fpsmaster.features.impl.interfaces.CustomTitles; @Mixin(GuiIngameForge.class) @@ -18,6 +20,11 @@ public void motionblur(float partialTicks, CallbackInfo ci){ EventDispatcher.dispatchEvent(new EventMotionBlur()); } + @Inject(method = "renderTooltip", at = @At("RETURN")) + private void renderTooltipPost(ScaledResolution sr, float partialTicks, CallbackInfo callbackInfo) { + EventDispatcher.dispatchEvent(new EventRender2D(partialTicks)); + } + @Redirect(method = "renderTitle", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/GlStateManager;translate(FFF)V")) public void drawString(float x, float y, float z) { GlStateManager.translate(x + CustomTitles.getX(), y + CustomTitles.getY(), z); diff --git a/v1.8.9/src/main/java/top/fpsmaster/wrapper/mods/WrapperHitboxes.java b/v1.8.9/src/main/java/top/fpsmaster/wrapper/mods/WrapperHitboxes.java index 3298f5d0..1f062651 100644 --- a/v1.8.9/src/main/java/top/fpsmaster/wrapper/mods/WrapperHitboxes.java +++ b/v1.8.9/src/main/java/top/fpsmaster/wrapper/mods/WrapperHitboxes.java @@ -11,6 +11,7 @@ import net.minecraft.entity.player.EntityPlayer; import net.minecraft.util.AxisAlignedBB; import net.minecraft.util.Vec3; +import org.lwjgl.opengl.GL11; import top.fpsmaster.event.events.EventRender3D; import top.fpsmaster.features.settings.impl.ColorSetting; import top.fpsmaster.forge.api.IRenderManager; @@ -23,7 +24,7 @@ public class WrapperHitboxes { public static void render(EventRender3D event, ColorSetting color) { - GlStateManager.pushMatrix(); + GL11.glPushAttrib(GL11.GL_ALPHA | GL11.GL_BLEND | GL11.GL_TEXTURE_2D | GL11.GL_LIGHTING | GL11.GL_DEPTH_TEST | GL11.GL_CULL_FACE); GlStateManager.depthMask(false); GlStateManager.disableTexture2D(); GlStateManager.disableLighting(); @@ -46,6 +47,6 @@ public static void render(EventRender3D event, ColorSetting color) { GlStateManager.enableCull(); GlStateManager.disableBlend(); GlStateManager.depthMask(true); - GlStateManager.popMatrix(); + GL11.glPopAttrib(); } } From e92023135eeae7ab221d310d5fcdbbd35450d24c Mon Sep 17 00:00:00 2001 From: TeAnli <159260777+TeAnli@users.noreply.github.com> Date: Tue, 22 Jul 2025 16:19:28 +0800 Subject: [PATCH 179/193] fix: add music login and potion texture dislocation (#106) --- .../ui/click/music/NewMusicPanel.java | 236 ++++++++++-------- .../custom/impl/PotionDisplayComponent.java | 2 +- .../utils/math/animation/Animation.java | 3 + 3 files changed, 130 insertions(+), 111 deletions(-) diff --git a/shared/java/top/fpsmaster/ui/click/music/NewMusicPanel.java b/shared/java/top/fpsmaster/ui/click/music/NewMusicPanel.java index 1d4ada1c..fe27db88 100644 --- a/shared/java/top/fpsmaster/ui/click/music/NewMusicPanel.java +++ b/shared/java/top/fpsmaster/ui/click/music/NewMusicPanel.java @@ -18,6 +18,8 @@ import top.fpsmaster.modules.music.netease.deserialize.MusicWrapper; import top.fpsmaster.ui.click.component.ScrollContainer; import top.fpsmaster.ui.common.TextField; +import top.fpsmaster.utils.math.animation.Animation; +import top.fpsmaster.utils.math.animation.Type; import top.fpsmaster.utils.os.FileUtils; import top.fpsmaster.utils.render.Render2DUtils; @@ -52,8 +54,7 @@ public class NewMusicPanel { public static Music playing; static NeteaseProfile profile; private static Track playingTrack; - - + private static final Animation opacityAnimation = new Animation(); // search public static TextField searchField = new TextField(FPSMaster.fontManager.s14, "搜索歌曲", new Color(56, 56, 56).getRGB(), new Color(200, 200, 200).getRGB(), 50, NewMusicPanel::search); static boolean searching = false; @@ -135,7 +136,6 @@ private static void nextSong() { static ScrollContainer scrollContainer = new ScrollContainer(); static ScrollContainer songsContainer = new ScrollContainer(); - public static void draw(float x, int y, float width, float height, int mouseX, int mouseY, int scaleFactor) { Render2DUtils.drawImage(new ResourceLocation("client/gui/music.png"), x + 12, y + 14, 75, 16, -1); searchField.drawTextBox(x + 32, y + 14, 100, 16); @@ -166,126 +166,142 @@ public static void draw(float x, int y, float width, float height, int mouseX, i } } } - - - if (searching) { - FPSMaster.fontManager.s22.drawCenteredString("加载中...", x + width / 2, y + height / 2 - 20, -1); - } else { - if (currentTrack == null) { - GL11.glEnable(GL11.GL_SCISSOR_TEST); - Render2DUtils.doGlScissor(x + 12, y + 35, width - 12, height - 65, scaleFactor); - int finalY = (int) (y + scrollContainer.getScroll()); - scrollContainer.draw(x + 12, y + 35, width - 12, height - 65, mouseX, mouseY, () -> { - String recommendSong = ""; - - if (recommendTrack != null && !recommendTrack.getMusics().isEmpty()) { - recommendSong = recommendTrack.getMusics().get(0).name; - } - - int tX = 0; - int tY = 60; - FPSMaster.fontManager.s22.drawString("推荐歌单", x + 20, finalY + 40, -1); - if (recommendTrack != null) - drawTrack(recommendTrack, "每日推荐", "每日推荐,从『" + recommendSong + "』听起", x + 20, finalY + 60, mouseX, mouseY, new Color(255, 73, 73, 200)); - tY = drawTracks(x, width, mouseX, mouseY, finalY, tX + 70, tY, dailyTracks); - tY += 120; - FPSMaster.fontManager.s22.drawString("收藏的歌单", x + 20, finalY + tY - 20, -1); - tY = drawTracks(x, width, mouseX, mouseY, finalY, tX, tY, likedTracks); - scrollContainer.setHeight(tY + 80); - }); - GL11.glDisable(GL11.GL_SCISSOR_TEST); + if(isWaitingLogin) { + ResourceLocation resourceLocation = new ResourceLocation("music/qr"); + Render2DUtils.drawImage(resourceLocation, x + width / 2 - 45, y + height / 2 - 45, 90f, 90f, -1); + }else{ + if (searching) { + FPSMaster.fontManager.s22.drawCenteredString("加载中...", x + width / 2, y + height / 2 - 20, -1); } else { - GL11.glEnable(GL11.GL_SCISSOR_TEST); - Render2DUtils.doGlScissor(x + 12, y + 35, width - 12, height - 65, scaleFactor); - if (!currentTrack.isLoaded() && (songsLoadThread == null || !songsLoadThread.isAlive())) { - songsLoadThread = new Thread(() -> { - searching = true; - currentTrack.loadMusic(); - searching = false; - }); - songsLoadThread.start(); - } - if (currentTrack.isLoaded()) { - int finalY = (int) (y + songsContainer.getScroll()); - songsContainer.draw(x + 12, y + 35, width - 12, height - 65, mouseX, mouseY, () -> { - int sY = 40; - for (AbstractMusic music : currentTrack.getMusics()) { - if (finalY + sY + 25 > y + 35 && finalY + sY < y + 35 + height - 65) { - Music neteaseMusic = (Music) music; - if (neteaseMusic.isLoadedImage) { - Render2DUtils.drawImage(new ResourceLocation("music/netease/" + neteaseMusic.id), x + 20, finalY + sY, 20f, 20f, -1); - } else { - Render2DUtils.drawOptimizedRoundedRect(x + 20, finalY + sY, 20f, 20f, new Color(200, 200, 200, 255)); - } - FPSMaster.fontManager.s18.drawString(neteaseMusic.name, x + 45, finalY + sY, -1); - FPSMaster.fontManager.s14.drawString(neteaseMusic.author, x + 45, finalY + sY + 10, new Color(200, 200, 200).getRGB()); + if (currentTrack == null) { + GL11.glEnable(GL11.GL_SCISSOR_TEST); + Render2DUtils.doGlScissor(x + 12, y + 35, width - 12, height - 65, scaleFactor); + int finalY = (int) (y + scrollContainer.getScroll()); + scrollContainer.draw(x + 12, y + 35, width - 12, height - 65, mouseX, mouseY, () -> { + String recommendSong = ""; + + if (recommendTrack != null && !recommendTrack.getMusics().isEmpty()) { + recommendSong = recommendTrack.getMusics().get(0).name; + } - if (Render2DUtils.isHovered(x + 45, finalY + sY + 5, 45 + FPSMaster.fontManager.s18.getStringWidth(neteaseMusic.name), 18, mouseX, mouseY) && consumeClick(0)) { - playing = (Music) music; - playingTrack = currentTrack; - music.play(); + int tX = 0; + int tY = 60; + FPSMaster.fontManager.s22.drawString("推荐歌单", x + 20, finalY + 40, -1); + if (recommendTrack != null) + drawTrack(recommendTrack, "每日推荐", "每日推荐,从『" + recommendSong + "』听起", x + 20, finalY + 60, mouseX, mouseY, new Color(255, 73, 73, 200)); + tY = drawTracks(x, width, mouseX, mouseY, finalY, tX + 70, tY, dailyTracks); + tY += 120; + FPSMaster.fontManager.s22.drawString("收藏的歌单", x + 20, finalY + tY - 20, -1); + tY = drawTracks(x, width, mouseX, mouseY, finalY, tX, tY, likedTracks); + scrollContainer.setHeight(tY + 80); + }); + GL11.glDisable(GL11.GL_SCISSOR_TEST); + } else { + GL11.glEnable(GL11.GL_SCISSOR_TEST); + Render2DUtils.doGlScissor(x + 12, y + 35, width - 12, height - 65, scaleFactor); + if (!currentTrack.isLoaded() && (songsLoadThread == null || !songsLoadThread.isAlive())) { + songsLoadThread = new Thread(() -> { + searching = true; + currentTrack.loadMusic(); + searching = false; + }); + songsLoadThread.start(); + } + if (currentTrack.isLoaded()) { + int finalY = (int) (y + songsContainer.getScroll()); + songsContainer.draw(x + 12, y + 35, width - 12, height - 65, mouseX, mouseY, () -> { + int sY = 40; + for (AbstractMusic music : currentTrack.getMusics()) { + if (finalY + sY + 25 > y + 35 && finalY + sY < y + 35 + height - 65) { + Music neteaseMusic = (Music) music; + boolean isHovered = Render2DUtils.isHovered(x + 15, finalY + sY - 5, width - 25, 30, mouseX, mouseY); + if (isHovered) { + Render2DUtils.drawOptimizedRoundedRect(x + 15,finalY + sY - 5, width - 25, 30,new Color(255,255,255,50)); + if(consumeClick(0)){ + playing = (Music) music; + playingTrack = currentTrack; + music.play(); + } + } + if (neteaseMusic.isLoadedImage) { + Render2DUtils.drawImage(new ResourceLocation("music/netease/" + neteaseMusic.id), x + 20, finalY + sY, 20f, 20f, -1); + } else { + Render2DUtils.drawOptimizedRoundedRect(x + 20, finalY + sY, 20f, 20f, new Color(200, 200, 200, 255)); + } + FPSMaster.fontManager.s18.drawString(neteaseMusic.name, x + 45, finalY + sY, -1); + FPSMaster.fontManager.s14.drawString(neteaseMusic.author, x + 45, finalY + sY + 10, new Color(200, 200, 200).getRGB()); } + sY += 31; } - sY += 25; - } - songsContainer.setHeight(sY); - }); + songsContainer.setHeight(sY); + }); + } + GL11.glDisable(GL11.GL_SCISSOR_TEST); } - GL11.glDisable(GL11.GL_SCISSOR_TEST); - } - Render2DUtils.drawRoundedRectImage(x + 1, y + height - 30, width - 2, 31, 10, new Color(0, 0, 0, 150)); - if (playing != null) { - UFontRenderer s14 = FPSMaster.fontManager.s14; - s14.drawString(s14.trimString(playing.name, 100, false), x + 30, y + height - 22, new Color(234, 234, 234).getRGB()); - s14.drawString(s14.trimString(playing.author, 60, false), x + 30, y + height - 12, new Color(124, 124, 124).getRGB()); - - if (playing.isLoadedImage) { - Render2DUtils.drawImage(new ResourceLocation("music/netease/" + playing.id), x + 5, y + height - 25, 20f, 20f, -1); - } else { - Render2DUtils.drawOptimizedRoundedRect(x + 5, y + height - 25, 20f, 20f, new Color(200, 200, 200, 255)); - } - // 进度条 - if (Render2DUtils.isHovered(x + width / 2 - 80, y + height - 6, 160, 3, mouseX, mouseY)) { - Render2DUtils.drawRoundedRectImage(x + width / 2 - 80, y + height - 6, 160, 3, 3, new Color(95, 95, 95)); - if (consumeClick(0)) { - playing.seek((mouseX - (x + width / 2 - 80)) / 160f); - if (!MusicPlayer.isPlaying) - MusicPlayer.play(); + Render2DUtils.drawRoundedRectImage(x + 1, y + height - 30, width - 2, 31, 10, new Color(0, 0, 0, 150)); + if (playing != null) { + int opacity; + opacityAnimation.start(0,255,0.2f,Type.EASE_IN_QUAD); + if(!opacityAnimation.isFinished()){ + opacityAnimation.update(); + opacity = (int) opacityAnimation.value; + } else { + opacity = 255; } - } else { - Render2DUtils.drawRoundedRectImage(x + width / 2 - 80, y + height - 6, 160, 3, 3, new Color(51, 51, 51)); - } - float playProgress = MusicPlayer.getPlayProgress(); - if (JLayerHelper.clip == null) { - Render2DUtils.drawRoundedRectImage(x + width / 2 - 80, y + height - 6, 160f * playing.downloadProgress, 3, 3, new Color(148, 148, 148)); - } else { - Render2DUtils.drawRoundedRectImage(x + width / 2 - 80, y + height - 6, 160f * playProgress, 3, 3, new Color(225, 73, 73)); - } - // 操作按钮 - Render2DUtils.drawImage(new ResourceLocation("client/gui/settings/music/previous.png"), x + width / 2 - 35, y + height - 25, 16f, 16f, new Color(234, 234, 234)); - Render2DUtils.drawImage(MusicPlayer.isPlaying ? new ResourceLocation("client/gui/settings/music/pause.png") : new ResourceLocation("client/gui/settings/music/play.png"), x + width / 2 - 15, y + height - 26, 35 / 2f, 35 / 2f, -1); - Render2DUtils.drawImage(new ResourceLocation("client/gui/settings/music/next.png"), x + width / 2 + 5, y + height - 25, 16f, 16f, new Color(234, 234, 234)); - - if (JLayerHelper.clip != null) { - if (Render2DUtils.isHovered(x + width / 2 - 15, y + height - 26, 35 / 2f, 35 / 2f, mouseX, mouseY) && consumeClick(0)) { - if (MusicPlayer.isPlaying) - MusicPlayer.pause(); - else - MusicPlayer.play(); + UFontRenderer s14 = FPSMaster.fontManager.s14; + s14.drawString(s14.trimString(playing.name, 100, false), x + 30, y + height - 22, new Color(234, 234, 234, opacity).getRGB()); + s14.drawString(s14.trimString(playing.author, 60, false), x + 30, y + height - 12, new Color(124, 124, 124, opacity).getRGB()); + + if (playing.isLoadedImage) { + Render2DUtils.drawImage(new ResourceLocation("music/netease/" + playing.id), x + 5, y + height - 25, 20f, 20f, new Color(255,255,255,opacity)); + } else { + Render2DUtils.drawOptimizedRoundedRect(x + 5, y + height - 25, 20f, 20f, new Color(200, 200, 200, opacity)); + } + // 进度条 + if (Render2DUtils.isHovered(x + width / 2 - 80, y + height - 6, 160, 3, mouseX, mouseY)) { + Render2DUtils.drawRoundedRectImage(x + width / 2 - 80, y + height - 6, 160, 3, 3, new Color(95, 95, 95,opacity)); + if (consumeClick(0)) { + playing.seek((mouseX - (x + width / 2 - 80)) / 160f); + if (!MusicPlayer.isPlaying) + MusicPlayer.play(); + } + } else { + Render2DUtils.drawRoundedRectImage(x + width / 2 - 80, y + height - 6, 160, 3, 3, new Color(51, 51, 51,opacity)); + } + float playProgress = MusicPlayer.getPlayProgress(); + if (JLayerHelper.clip == null) { + Render2DUtils.drawRoundedRectImage(x + width / 2 - 80, y + height - 6, 160f * playing.downloadProgress, 3, 3, new Color(148, 148, 148,opacity)); + } else { + Render2DUtils.drawRoundedRectImage(x + width / 2 - 80, y + height - 6, 160f * playProgress, 3, 3, new Color(225, 73, 73,opacity)); } - double duration = JLayerHelper.getDuration(); - int minutes = (int) (duration * playProgress); - int seconds = (int) ((duration * playProgress - minutes) * 60); - String progress = minutes + ":" + seconds; - String total = (int) duration + ":" + (int) ((duration - (int) duration) * 60); - s14.drawString(progress, x + width / 2 - 80 - s14.getStringWidth(progress) - 2, y + height - 10, new Color(160, 160, 160).getRGB()); - s14.drawString(total, x + width / 2 + 80 + 2, y + height - 10, new Color(160, 160, 160).getRGB()); + // 操作按钮 + Render2DUtils.drawImage(new ResourceLocation("client/gui/settings/music/previous.png"), x + width / 2 - 35, y + height - 25, 16f, 16f, new Color(234, 234, 234,opacity)); + Render2DUtils.drawImage(MusicPlayer.isPlaying ? new ResourceLocation("client/gui/settings/music/pause.png") : new ResourceLocation("client/gui/settings/music/play.png"), x + width / 2 - 15, y + height - 26, 35 / 2f, 35 / 2f, new Color(255,255,255,opacity)); + Render2DUtils.drawImage(new ResourceLocation("client/gui/settings/music/next.png"), x + width / 2 + 5, y + height - 25, 16f, 16f, new Color(234, 234, 234,opacity)); + + if (JLayerHelper.clip != null) { + if (Render2DUtils.isHovered(x + width / 2 - 15, y + height - 26, 35 / 2f, 35 / 2f, mouseX, mouseY) && consumeClick(0)) { + if (MusicPlayer.isPlaying) + MusicPlayer.pause(); + else + MusicPlayer.play(); + } + + double duration = JLayerHelper.getDuration(); + int minutes = (int) (duration * playProgress); + int seconds = (int) ((duration * playProgress - minutes) * 60); + String progress = minutes + ":" + seconds; + String total = (int) duration + ":" + (int) ((duration - (int) duration) * 60); + s14.drawString(progress, x + width / 2 - 80 - s14.getStringWidth(progress) - 2, y + height - 10, new Color(160, 160, 160,opacity).getRGB()); + s14.drawString(total, x + width / 2 + 80 + 2, y + height - 10, new Color(160, 160, 160,opacity).getRGB()); + } } } } + mouseButton = -1; } diff --git a/shared/java/top/fpsmaster/ui/custom/impl/PotionDisplayComponent.java b/shared/java/top/fpsmaster/ui/custom/impl/PotionDisplayComponent.java index e9261f90..29223f2e 100644 --- a/shared/java/top/fpsmaster/ui/custom/impl/PotionDisplayComponent.java +++ b/shared/java/top/fpsmaster/ui/custom/impl/PotionDisplayComponent.java @@ -50,7 +50,7 @@ public void draw(float x, float y) { 0, 0, (potion % 8 * 18) + 1, - (198 + (float) potion / 8 * 18) + 1, + (198 + (float)(potion / 8) * 18) + 1, 16, 16, 256f, diff --git a/shared/java/top/fpsmaster/utils/math/animation/Animation.java b/shared/java/top/fpsmaster/utils/math/animation/Animation.java index 41aef620..9dbacce9 100644 --- a/shared/java/top/fpsmaster/utils/math/animation/Animation.java +++ b/shared/java/top/fpsmaster/utils/math/animation/Animation.java @@ -82,4 +82,7 @@ public void fstart(double start, double end, float duration, Type type) { isStarted = false; start(start, end, duration, type); } + public boolean isFinished() { + return this.value == this.end; + } } From 729aaf78ed0d695f1258ada1d624c24016124157 Mon Sep 17 00:00:00 2001 From: vlouboos Date: Tue, 22 Jul 2025 16:59:17 +0800 Subject: [PATCH 180/193] Patch command --- .../main/java/top/fpsmaster/forge/mixin/MixinGuiChat.java | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinGuiChat.java b/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinGuiChat.java index 9f64506c..78fae781 100644 --- a/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinGuiChat.java +++ b/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinGuiChat.java @@ -12,6 +12,7 @@ import org.spongepowered.asm.mixin.injection.Redirect; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import top.fpsmaster.FPSMaster; +import top.fpsmaster.utils.Utility; import top.fpsmaster.utils.render.Render2DUtils; import java.awt.*; @@ -49,8 +50,13 @@ public void drawScreen(int mouseX, int mouseY, float partialTicks, CallbackInfo @Redirect(method = "keyTyped", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/GuiChat;sendChatMessage(Ljava/lang/String;)V")) public void sendChatMessage(GuiChat instance, String message) { + message = message.trim(); if (irc && FPSMaster.INSTANCE.wsClient != null && FPSMaster.INSTANCE.wsClient.getReadyState() == ReadyState.OPEN) { - FPSMaster.INSTANCE.wsClient.sendMessage(message); + if (message.toLowerCase().startsWith("/")) { + Utility.sendClientMessage("\247cIRC不允许命令输入!"); + } else { + FPSMaster.INSTANCE.wsClient.sendMessage(message); + } } else { instance.sendChatMessage(message); } From 009be41d2fc34dce9bf3d385179b07dbf2217bbf Mon Sep 17 00:00:00 2001 From: vlouboos Date: Tue, 22 Jul 2025 18:08:24 +0800 Subject: [PATCH 181/193] Fold message --- .../features/impl/interfaces/BetterChat.java | 41 +++++++++++++++- .../interfaces/gui/IGuiNewChatProvider.java | 11 +++++ .../assets/minecraft/client/lang/en_us.lang | 1 + .../assets/minecraft/client/lang/zh_cn.lang | 1 + .../fpsmaster/forge/mixin/MixinGuiIngame.java | 8 ---- .../forge/mixin/MixinGuiNewChat.java | 47 ++++++++++++------- 6 files changed, 82 insertions(+), 27 deletions(-) create mode 100644 shared/java/top/fpsmaster/interfaces/gui/IGuiNewChatProvider.java diff --git a/shared/java/top/fpsmaster/features/impl/interfaces/BetterChat.java b/shared/java/top/fpsmaster/features/impl/interfaces/BetterChat.java index 1ca3dbae..6c32c6cc 100644 --- a/shared/java/top/fpsmaster/features/impl/interfaces/BetterChat.java +++ b/shared/java/top/fpsmaster/features/impl/interfaces/BetterChat.java @@ -1,15 +1,26 @@ package top.fpsmaster.features.impl.interfaces; +import net.minecraft.client.gui.ChatLine; +import net.minecraft.network.play.server.S02PacketChat; +import net.minecraft.util.ChatComponentText; +import top.fpsmaster.event.Subscribe; +import top.fpsmaster.event.events.EventPacket; import top.fpsmaster.features.impl.InterfaceModule; import top.fpsmaster.features.manager.Category; +import top.fpsmaster.features.settings.impl.BooleanSetting; +import top.fpsmaster.interfaces.gui.IGuiNewChatProvider; -public class BetterChat extends InterfaceModule { +import static top.fpsmaster.utils.Utility.mc; +public class BetterChat extends InterfaceModule { public static boolean using = false; + private final BooleanSetting foldMessage = new BooleanSetting("FoldMessage", false); + private String lastMessage = ""; + private int counter = 1; public BetterChat() { super("BetterChat", Category.Interface); - addSettings(backgroundColor, fontShadow, betterFont, bg); + addSettings(foldMessage, backgroundColor, fontShadow, betterFont, bg); } @Override @@ -23,4 +34,30 @@ public void onDisable() { super.onDisable(); using = false; } + + @Subscribe + public void onPacketReceive(EventPacket e) { + if (e.type == EventPacket.PacketType.SEND || !foldMessage.getValue()) return; + if (e.packet instanceof S02PacketChat) { + S02PacketChat packet = (S02PacketChat) e.packet; + if (packet.getType() == 2) return; + IGuiNewChatProvider chatProvider = (IGuiNewChatProvider) mc.ingameGUI.getChatGUI(); + if (chatProvider.getDrawnChatLines().isEmpty()) { + counter = 1; + lastMessage = packet.getChatComponent().getUnformattedText(); + return; + } + if (lastMessage.equals(packet.getChatComponent().getUnformattedText()) && packet.getChatComponent().getChatStyle().getChatHoverEvent() == null && packet.getChatComponent().getChatStyle().getChatClickEvent() == null) { + ChatLine c = chatProvider.getDrawnChatLines().get(0); + String text = packet.getChatComponent().getUnformattedText(); + c = new ChatLine(c.getUpdatedCounter(), new ChatComponentText(text + "\247r\247f [x" + ++counter + "]"), c.getChatLineID()); + chatProvider.getChatLines().set(0, c); + chatProvider.getDrawnChatLines().set(0, c); + e.cancel(); + } else { + counter = 1; + lastMessage = packet.getChatComponent().getUnformattedText(); + } + } + } } diff --git a/shared/java/top/fpsmaster/interfaces/gui/IGuiNewChatProvider.java b/shared/java/top/fpsmaster/interfaces/gui/IGuiNewChatProvider.java new file mode 100644 index 00000000..08602be2 --- /dev/null +++ b/shared/java/top/fpsmaster/interfaces/gui/IGuiNewChatProvider.java @@ -0,0 +1,11 @@ +package top.fpsmaster.interfaces.gui; + +import net.minecraft.client.gui.ChatLine; + +import java.util.List; + +public interface IGuiNewChatProvider { + List getChatLines(); + + List getDrawnChatLines(); +} diff --git a/shared/resources/assets/minecraft/client/lang/en_us.lang b/shared/resources/assets/minecraft/client/lang/en_us.lang index 20666e29..808593ec 100644 --- a/shared/resources/assets/minecraft/client/lang/en_us.lang +++ b/shared/resources/assets/minecraft/client/lang/en_us.lang @@ -67,6 +67,7 @@ betterchat.fontshadow=Font Shadow betterchat.betterfont=Clean Font betterchat.roundradius=Corner Radius betterchat.background=Show Background +betterchat.foldmessage=Fold Message combodisplay=Combo Counter combodisplay.desc=Displays current combo count diff --git a/shared/resources/assets/minecraft/client/lang/zh_cn.lang b/shared/resources/assets/minecraft/client/lang/zh_cn.lang index 3bb83bcc..1745388c 100644 --- a/shared/resources/assets/minecraft/client/lang/zh_cn.lang +++ b/shared/resources/assets/minecraft/client/lang/zh_cn.lang @@ -67,6 +67,7 @@ betterchat.fontshadow=字体阴影 betterchat.betterfont=更好的字体 betterchat.roundradius=圆角半径 betterchat.background=背景 +betterchat.foldmessage=折叠消息 combodisplay=连击显示 combodisplay.desc=显示连击数 diff --git a/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinGuiIngame.java b/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinGuiIngame.java index c6475587..9bf0e868 100644 --- a/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinGuiIngame.java +++ b/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinGuiIngame.java @@ -1,19 +1,13 @@ package top.fpsmaster.forge.mixin; -import net.minecraft.client.gui.FontRenderer; import net.minecraft.client.gui.GuiIngame; import net.minecraft.client.gui.ScaledResolution; -import net.minecraft.client.renderer.GlStateManager; import net.minecraft.scoreboard.ScoreObjective; 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.Redirect; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; -import top.fpsmaster.event.EventDispatcher; -import top.fpsmaster.event.events.EventRender2D; -import top.fpsmaster.features.impl.interfaces.CustomTitles; import top.fpsmaster.features.impl.interfaces.Scoreboard; import top.fpsmaster.features.impl.render.Crosshair; @@ -30,6 +24,4 @@ public void scoreboard(ScoreObjective objective, ScaledResolution scaledRes, Cal if (Scoreboard.using) ci.cancel(); } - - } diff --git a/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinGuiNewChat.java b/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinGuiNewChat.java index 90c11a85..e6a573fe 100644 --- a/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinGuiNewChat.java +++ b/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinGuiNewChat.java @@ -13,19 +13,22 @@ import top.fpsmaster.FPSMaster; import top.fpsmaster.forge.api.IChatLine; import top.fpsmaster.features.impl.interfaces.BetterChat; +import top.fpsmaster.interfaces.gui.IGuiNewChatProvider; import top.fpsmaster.utils.math.animation.AnimationUtils; import top.fpsmaster.utils.render.Render2DUtils; import java.awt.*; -import java.util.Iterator; +import java.util.Collections; import java.util.List; +import java.util.concurrent.atomic.AtomicInteger; import static top.fpsmaster.utils.Utility.mc; @Mixin(GuiNewChat.class) -public abstract class MixinGuiNewChat { +public abstract class MixinGuiNewChat implements IGuiNewChatProvider { - private boolean isChatOpenAnimationNeed = true; + @Unique + private boolean v1_8_9$isChatOpenAnimationNeed = true; @Shadow public abstract int getLineCount(); @@ -50,6 +53,8 @@ public abstract class MixinGuiNewChat { @Shadow private boolean isScrolled; + @Shadow @Final private List chatLines; + /** * @author SuperSkidder * @reason betterchat @@ -123,9 +128,8 @@ public void drawChat(int updateCounter) { } } else { BetterChat module = (BetterChat) FPSMaster.moduleManager.getModule(BetterChat.class); - - int i = this.getLineCount(); - int j = this.drawnChatLines.size(); + AtomicInteger i = new AtomicInteger(this.getLineCount()); + int j = drawnChatLines.size(); float f = mc.gameSettings.chatOpacity * 0.9F + 0.1F; if (j > 0) { boolean bl = this.getChatOpen(); @@ -135,23 +139,22 @@ public void drawChat(int updateCounter) { GlStateManager.pushMatrix(); GlStateManager.translate(2.0F, 8.0F, 0.0F); GlStateManager.scale(g, g, 1.0F); - int l = 0; int m; int n; int o; - for (m = 0; m + this.scrollPos < this.drawnChatLines.size() && m < i; ++m) { - ChatLine chatLine = this.drawnChatLines.get(m + this.scrollPos); + for (m = 0; m + this.scrollPos < drawnChatLines.size() && m < i.get(); ++m) { + ChatLine chatLine = drawnChatLines.get(m + this.scrollPos); if (chatLine != null) { - if (getChatOpen() && isChatOpenAnimationNeed) { - for (int i1 = 0; i1 + this.scrollPos < this.drawnChatLines.size() && i1 < i; ++i1) { - ChatLine chatline = this.drawnChatLines.get(i1 + this.scrollPos); + if (getChatOpen() && v1_8_9$isChatOpenAnimationNeed) { + for (int i1 = 0; i1 + this.scrollPos < drawnChatLines.size() && i1 < i.get(); ++i1) { + ChatLine chatline = drawnChatLines.get(i1 + this.scrollPos); ((IChatLine) chatline).setAnimation(100); } - isChatOpenAnimationNeed = false; + v1_8_9$isChatOpenAnimationNeed = false; } if (!getChatOpen()) { - isChatOpenAnimationNeed = true; + v1_8_9$isChatOpenAnimationNeed = true; } n = updateCounter - chatLine.getUpdatedCounter(); @@ -166,7 +169,7 @@ public void drawChat(int updateCounter) { if (alpha > 3) { int q = -m * 9; int alpha1 = (int) ((alpha / 255f) * module.backgroundColor.getColor().getAlpha()); - Gui.drawRect(-2, q - 9, k + 4, q, Render2DUtils.reAlpha(module.backgroundColor.getColor(), alpha1).getRGB()); + Gui.drawRect(-2, q - 8, k + 4, q + 1, Render2DUtils.reAlpha(module.backgroundColor.getColor(), alpha1).getRGB()); String string = chatLine.getChatComponent().getFormattedText(); GlStateManager.enableBlend(); if (module.betterFont.getValue()) { @@ -214,14 +217,14 @@ public IChatComponent getChatComponent(int mouseX, int mouseY) { j = MathHelper.floor_float((float) j / f); k = MathHelper.floor_float((float) k / f); if (j >= 0 && k >= 0) { - int l = Math.min(this.getLineCount(), this.drawnChatLines.size()); + AtomicInteger l = new AtomicInteger(Math.min(this.getLineCount(), this.drawnChatLines.size())); int fontHeight = mc.fontRendererObj.FONT_HEIGHT; BetterChat module = (BetterChat) FPSMaster.moduleManager.getModule(BetterChat.class); if (BetterChat.using && module.betterFont.getValue()) { fontHeight = FPSMaster.fontManager.s16.getHeight(); } - if (j <= MathHelper.floor_float((float) this.getChatWidth() / this.getChatScale()) && k < fontHeight * l + l) { + if (j <= MathHelper.floor_float((float) this.getChatWidth() / this.getChatScale()) && k < fontHeight * l.get() + l.get()) { int m = k / fontHeight + this.scrollPos; if (m >= 0 && m < this.drawnChatLines.size()) { ChatLine chatLine = this.drawnChatLines.get(m); @@ -261,4 +264,14 @@ public List spilt(IChatComponent chatComponent, int i, FontRende return GuiUtilRenderComponents.splitText(chatComponent, i, mc.fontRendererObj, false, false); } } + + @Override + public List getChatLines() { + return chatLines; + } + + @Override + public List getDrawnChatLines() { + return drawnChatLines; + } } From 78e52b3c48b138eb0324ea8cd78a961c8dae030f Mon Sep 17 00:00:00 2001 From: TeAnli <159260777+TeAnli@users.noreply.github.com> Date: Fri, 25 Jul 2025 15:36:03 +0800 Subject: [PATCH 182/193] New item count component and item multiple setting (#108) * feat: add lyric scale * feat: auto gg in kkcraft * fix: wavey cape tearing issue * feat: Add item count component * feat: Add multiple item setting * chore: Add items setting language support * fix: wrong word name --- .../impl/interfaces/ItemCountDisplay.java | 20 ++ .../features/impl/utility/AutoGG.java | 23 +- .../fpsmaster/features/manager/Module.java | 2 + .../features/manager/ModuleManager.java | 3 +- .../fpsmaster/features/settings/Setting.java | 2 +- .../settings/impl/MultipleItemSetting.java | 29 +++ .../modules/config/ConfigManager.java | 31 ++- .../top/fpsmaster/ui/click/MainPanel.java | 3 +- .../ui/click/modules/ModuleRenderer.java | 22 +- .../impl/MultipleItemSettingRender.java | 82 +++++++ .../ui/custom/ComponentsManager.java | 1 + .../impl/ItemCountDisplayComponent.java | 74 +++++++ .../ui/custom/impl/LyricsComponent.java | 30 ++- shared/java/top/fpsmaster/utils/Utility.java | 22 ++ .../fpsmaster/utils/world/PotionMetadata.java | 206 ++++++++++++++++++ .../assets/minecraft/client/lang/en_us.lang | 21 ++ .../assets/minecraft/client/lang/zh_cn.lang | 20 ++ .../fpsmaster/forge/mixin/MixinLayerCape.java | 17 +- 18 files changed, 564 insertions(+), 44 deletions(-) create mode 100644 shared/java/top/fpsmaster/features/impl/interfaces/ItemCountDisplay.java create mode 100644 shared/java/top/fpsmaster/features/settings/impl/MultipleItemSetting.java create mode 100644 shared/java/top/fpsmaster/ui/click/modules/impl/MultipleItemSettingRender.java create mode 100644 shared/java/top/fpsmaster/ui/custom/impl/ItemCountDisplayComponent.java create mode 100644 shared/java/top/fpsmaster/utils/world/PotionMetadata.java diff --git a/shared/java/top/fpsmaster/features/impl/interfaces/ItemCountDisplay.java b/shared/java/top/fpsmaster/features/impl/interfaces/ItemCountDisplay.java new file mode 100644 index 00000000..f7ef60a1 --- /dev/null +++ b/shared/java/top/fpsmaster/features/impl/interfaces/ItemCountDisplay.java @@ -0,0 +1,20 @@ +package top.fpsmaster.features.impl.interfaces; + +import top.fpsmaster.features.impl.InterfaceModule; +import top.fpsmaster.features.manager.Category; +import top.fpsmaster.features.settings.impl.ModeSetting; +import top.fpsmaster.features.settings.impl.MultipleItemSetting; + +public class ItemCountDisplay extends InterfaceModule { + + //TODO: Custom 自定义物品数量,建议添加MultipleSetting,便于让用户自动添加,暂未实现 + public ModeSetting modes = new ModeSetting("mode", 0, "potpvp", "uhc", "custom"); + + public MultipleItemSetting itemsSetting = new MultipleItemSetting("items",() -> modes.getValue() == 2); + + public ItemCountDisplay() { + super("ItemCountDisplay", Category.Interface); + addSettings(bg, backgroundColor ,rounded, roundRadius, betterFont, fontShadow, spacing, modes, itemsSetting); + } + +} diff --git a/shared/java/top/fpsmaster/features/impl/utility/AutoGG.java b/shared/java/top/fpsmaster/features/impl/utility/AutoGG.java index 2d9c45c2..6103f0e4 100644 --- a/shared/java/top/fpsmaster/features/impl/utility/AutoGG.java +++ b/shared/java/top/fpsmaster/features/impl/utility/AutoGG.java @@ -20,10 +20,10 @@ public class AutoGG extends Module { public BooleanSetting autoPlay = new BooleanSetting("AutoPlay", false); public NumberSetting delay = new NumberSetting("DelayToPlay", 5, 0, 10, 1, () -> autoPlay.getValue()); public TextSetting message = new TextSetting("Message", "gg"); - public ModeSetting servers = new ModeSetting("Servers", 0, "hypxiel"); + public ModeSetting servers = new ModeSetting("Servers", 0, "hypxiel", "kkcraft"); public String hypixelTrigger = "Reward Summary;1st Killer;Damage Dealt;奖励总览;击杀数第一名;造成伤害"; - + public String kkcraftTrigger = "获胜者;第一名杀手;击杀第一名"; public AutoGG() { super("AutoGG", Category.Utility); this.addSettings(autoPlay, delay, message, servers); @@ -32,12 +32,13 @@ public AutoGG() { @Subscribe public void onPacket(EventPacket event) { if (event.type == EventPacket.PacketType.RECEIVE && ProviderManager.packetChat.isPacket(event.packet)) { + String componentValue = ProviderManager.packetChat.getChatComponent(event.packet).toString(); + String chatMessage = ProviderManager.packetChat.getUnformattedText(event.packet); + boolean hasEndInformation = false; + Utility.sendClientMessage(componentValue); switch (servers.getValue()) { case 0: - String componentValue = ProviderManager.packetChat.getChatComponent(event.packet).toString(); boolean hasPlayCommand = componentValue.contains("ClickEvent{action=RUN_COMMAND, value='/play "); - String chatMessage = ProviderManager.packetChat.getUnformattedText(event.packet); - boolean hasEndInformation = false; for (String s : hypixelTrigger.split(";")) { hasEndInformation = StringUtils.stripControlCodes(chatMessage).contains(s); if (hasEndInformation) break; @@ -59,6 +60,18 @@ public void onPacket(EventPacket event) { } } break; + case 1: + for (String s : kkcraftTrigger.split(";")) { + hasEndInformation = StringUtils.stripControlCodes(chatMessage).contains(s); + if (hasEndInformation) break; + } + if (hasEndInformation) { + Utility.sendChatMessage(message.getValue()); + } + if(autoPlay.getValue()) { + Utility.sendClientNotify("AutoPlay is not supported at the moment in KKCraft"); + } + break; default: } diff --git a/shared/java/top/fpsmaster/features/manager/Module.java b/shared/java/top/fpsmaster/features/manager/Module.java index a3667cd8..9288c0ec 100644 --- a/shared/java/top/fpsmaster/features/manager/Module.java +++ b/shared/java/top/fpsmaster/features/manager/Module.java @@ -48,6 +48,8 @@ public void addSettings(Setting... settings) { this.settings.add(setting); } else if (setting instanceof ColorSetting) { this.settings.add(setting); + } else if (setting instanceof MultipleItemSetting) { + this.settings.add(setting); } } } diff --git a/shared/java/top/fpsmaster/features/manager/ModuleManager.java b/shared/java/top/fpsmaster/features/manager/ModuleManager.java index f774e916..1c61d541 100644 --- a/shared/java/top/fpsmaster/features/manager/ModuleManager.java +++ b/shared/java/top/fpsmaster/features/manager/ModuleManager.java @@ -13,7 +13,6 @@ import top.fpsmaster.interfaces.ProviderManager; import top.fpsmaster.modules.dev.DevMode; import top.fpsmaster.modules.logger.ClientLogger; -import top.fpsmaster.ui.click.CosmeticScreen; import top.fpsmaster.ui.click.MainPanel; import top.fpsmaster.ui.click.modules.ModuleRenderer; import top.fpsmaster.ui.devspace.DevSpace; @@ -123,7 +122,7 @@ public void init() { modules.add(new DirectionDisplay()); modules.add(new DamageIndicator()); modules.add(new TabOverlay()); - + modules.add(new ItemCountDisplay()); if (ProviderManager.constants.getVersion().equals("1.12.2")) { modules.add(new HideIndicator()); diff --git a/shared/java/top/fpsmaster/features/settings/Setting.java b/shared/java/top/fpsmaster/features/settings/Setting.java index 3966366b..637bbaa5 100644 --- a/shared/java/top/fpsmaster/features/settings/Setting.java +++ b/shared/java/top/fpsmaster/features/settings/Setting.java @@ -6,7 +6,7 @@ public class Setting { public String name; - T value; + public T value; public VisibleCondition visible; public Setting(String name, T value) { diff --git a/shared/java/top/fpsmaster/features/settings/impl/MultipleItemSetting.java b/shared/java/top/fpsmaster/features/settings/impl/MultipleItemSetting.java new file mode 100644 index 00000000..9aee9484 --- /dev/null +++ b/shared/java/top/fpsmaster/features/settings/impl/MultipleItemSetting.java @@ -0,0 +1,29 @@ +package top.fpsmaster.features.settings.impl; + +import net.minecraft.item.ItemStack; +import top.fpsmaster.features.settings.Setting; + +import java.util.ArrayList; + +public class MultipleItemSetting extends Setting> { + public static final int MAX_CAPACITY = 7; + public MultipleItemSetting(String name) { + super(name, new ArrayList<>()); + } + + public MultipleItemSetting(String name, VisibleCondition condition) { + super(name, new ArrayList<>(), condition); + } + + public void addItem(ItemStack itemStack) { + if (this.getValue().size() < MAX_CAPACITY) { + this.getValue().add(itemStack); + } + } + + public void removeItem(int index) { + ItemStack itemStack = this.getValue().get(index); + this.getValue().remove(itemStack); + } + +} diff --git a/shared/java/top/fpsmaster/modules/config/ConfigManager.java b/shared/java/top/fpsmaster/modules/config/ConfigManager.java index 9c3781e7..fc39a788 100644 --- a/shared/java/top/fpsmaster/modules/config/ConfigManager.java +++ b/shared/java/top/fpsmaster/modules/config/ConfigManager.java @@ -1,9 +1,8 @@ package top.fpsmaster.modules.config; -import com.google.gson.Gson; -import com.google.gson.GsonBuilder; -import com.google.gson.JsonElement; -import com.google.gson.JsonObject; +import com.google.gson.*; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; import top.fpsmaster.FPSMaster; import top.fpsmaster.exception.FileException; import top.fpsmaster.features.impl.optimizes.OldAnimations; @@ -17,8 +16,9 @@ import top.fpsmaster.ui.custom.Component; import top.fpsmaster.ui.custom.Position; import top.fpsmaster.utils.os.FileUtils; +import top.fpsmaster.utils.world.ItemsUtil; -import java.util.Map; +import java.util.*; public class ConfigManager { @@ -80,6 +80,18 @@ public void saveConfig(String name) throws FileException { moduleJson.addProperty("enabled", module.isEnabled()); moduleJson.addProperty("key", module.key); for (Setting setting : module.settings) { + if(setting instanceof MultipleItemSetting) { + MultipleItemSetting multipleItemSetting = (MultipleItemSetting) setting; + ArrayList value = multipleItemSetting.getValue(); + List items = new ArrayList<>(); + value.forEach((itemStack)->{ + items.add(Item.getIdFromItem(itemStack.getItem()) + "|" + itemStack.getMetadata()); + }); + JsonElement jsonTree = gson.toJsonTree(items); + moduleJson.add(setting.name, jsonTree); + continue; + } + String settingValue = setting.getValue().toString(); if (setting instanceof ColorSetting) { ColorSetting colorSetting = (ColorSetting) setting; @@ -140,6 +152,15 @@ public void loadConfig(String name) throws Exception { } else if (setting instanceof BindSetting) { BindSetting bindSetting = (BindSetting) setting; bindSetting.setValue(settingValue.getAsInt()); + } else if (setting instanceof MultipleItemSetting) { + MultipleItemSetting multipleItemSetting = (MultipleItemSetting) setting; + String[] itemInfoList = gson.fromJson(settingValue.getAsJsonArray(), String[].class); + for (String itemStack : itemInfoList) { + String[] item = itemStack.split("\\|"); + int id = Integer.parseInt(item[0]); + int metadata = Integer.parseInt(item[1]); + multipleItemSetting.addItem(ItemsUtil.getItemStackWithMetadata(Item.getItemById(id),metadata)); + } } } } diff --git a/shared/java/top/fpsmaster/ui/click/MainPanel.java b/shared/java/top/fpsmaster/ui/click/MainPanel.java index 29bc71cd..5cce94b4 100644 --- a/shared/java/top/fpsmaster/ui/click/MainPanel.java +++ b/shared/java/top/fpsmaster/ui/click/MainPanel.java @@ -12,7 +12,6 @@ import top.fpsmaster.ui.ai.AIChatPanel; import top.fpsmaster.ui.click.component.ScrollContainer; import top.fpsmaster.ui.click.modules.ModuleRenderer; -import top.fpsmaster.ui.click.music.MusicPanel; import top.fpsmaster.ui.click.music.NewMusicPanel; import top.fpsmaster.utils.math.animation.Animation; import top.fpsmaster.utils.math.animation.AnimationUtils; @@ -52,7 +51,7 @@ public class MainPanel extends ScaledGuiScreen { static int y = -1; static float width = 430f; static float height = 245.5f; - final float leftWidth = 50f; + public static final float leftWidth = 50f; public static String bindLock = ""; public static Module curModule = null; public static String dragLock = "null"; diff --git a/shared/java/top/fpsmaster/ui/click/modules/ModuleRenderer.java b/shared/java/top/fpsmaster/ui/click/modules/ModuleRenderer.java index 311d90fb..f373f634 100644 --- a/shared/java/top/fpsmaster/ui/click/modules/ModuleRenderer.java +++ b/shared/java/top/fpsmaster/ui/click/modules/ModuleRenderer.java @@ -28,22 +28,24 @@ public class ModuleRenderer extends ValueRender { ColorAnimation option = new ColorAnimation(); float optionX = 0; - public ModuleRenderer(Module mod) { - this.mod = mod; - content = new ColorAnimation(mod.isEnabled() ? new Color(66, 66, 66) : new Color(40, 40, 40)); - mod.settings.forEach(setting -> { + public ModuleRenderer(Module module) { + this.mod = module; + content = new ColorAnimation(module.isEnabled() ? new Color(66, 66, 66) : new Color(40, 40, 40)); + module.settings.forEach(setting -> { if (setting instanceof BooleanSetting) { - settingsRenderers.add(new BooleanSettingRender(mod, (BooleanSetting) setting)); + settingsRenderers.add(new BooleanSettingRender(module, (BooleanSetting) setting)); } else if (setting instanceof ModeSetting) { - settingsRenderers.add(new ModeSettingRender(mod, (ModeSetting) setting)); + settingsRenderers.add(new ModeSettingRender(module, (ModeSetting) setting)); } else if (setting instanceof TextSetting) { - settingsRenderers.add(new TextSettingRender(mod, (TextSetting) setting)); + settingsRenderers.add(new TextSettingRender(module, (TextSetting) setting)); } else if (setting instanceof NumberSetting) { - settingsRenderers.add(new NumberSettingRender(mod, (NumberSetting) setting)); + settingsRenderers.add(new NumberSettingRender(module, (NumberSetting) setting)); } else if (setting instanceof ColorSetting) { - settingsRenderers.add(new ColorSettingRender(mod, (ColorSetting) setting)); + settingsRenderers.add(new ColorSettingRender(module, (ColorSetting) setting)); } else if (setting instanceof BindSetting) { - settingsRenderers.add(new BindSettingRender(mod, (BindSetting) setting)); + settingsRenderers.add(new BindSettingRender(module, (BindSetting) setting)); + } else if(setting instanceof MultipleItemSetting) { + settingsRenderers.add(new MultipleItemSettingRender(module,(MultipleItemSetting)setting)); } }); } diff --git a/shared/java/top/fpsmaster/ui/click/modules/impl/MultipleItemSettingRender.java b/shared/java/top/fpsmaster/ui/click/modules/impl/MultipleItemSettingRender.java new file mode 100644 index 00000000..b5401499 --- /dev/null +++ b/shared/java/top/fpsmaster/ui/click/modules/impl/MultipleItemSettingRender.java @@ -0,0 +1,82 @@ +package top.fpsmaster.ui.click.modules.impl; + +import net.minecraft.item.ItemStack; +import top.fpsmaster.FPSMaster; +import top.fpsmaster.features.manager.Module; +import top.fpsmaster.features.settings.impl.MultipleItemSetting; +import top.fpsmaster.interfaces.ProviderManager; +import top.fpsmaster.ui.click.modules.SettingRender; +import top.fpsmaster.utils.render.Render2DUtils; +import top.fpsmaster.utils.world.ItemsUtil; + +import java.awt.*; +import java.util.Locale; + +public class MultipleItemSettingRender extends SettingRender { + public static final int xOffset = 14; + public static final int padding = 3; + public static final int itemHeight = 21; + public static final int buttonSize = 15; + + public MultipleItemSettingRender(Module module, MultipleItemSetting setting) { + super(setting); + this.mod = module; + } + private float itemWidth; + @Override + public void render(float x, float y, float width, float height, float mouseX, float mouseY, boolean custom) { + FPSMaster.fontManager.s16.drawString( + FPSMaster.i18n.get((mod.name + "." + setting.name).toLowerCase(Locale.getDefault())), + x + xOffset, y + 1, new Color(162, 162, 162).getRGB() + ); + Render2DUtils.drawOptimizedRoundedRect(x + xOffset, y + FPSMaster.fontManager.s16.getHeight() + 5, itemWidth + padding, this.height - 7, 3, new Color(80, 80, 80, 160).getRGB()); + int textWidth = FPSMaster.fontManager.s14.getStringWidth(FPSMaster.i18n.get(FPSMaster.i18n.get("ItemsSetting.heldItem".toLowerCase(Locale.getDefault())))); + FPSMaster.fontManager.s14.drawString(FPSMaster.i18n.get("ItemsSetting.heldItem".toLowerCase(Locale.getDefault())), x + xOffset + itemWidth - 30 - textWidth, y + 1, -1) ; + FPSMaster.fontManager.s22.drawString("+", x + xOffset + itemWidth - 12, y + 1, -1); + + Render2DUtils.drawOptimizedRoundedRect(x + xOffset, y + FPSMaster.fontManager.s16.getHeight() + 5, itemWidth + padding, this.height - 7, 3, new Color(80, 80, 80, 160).getRGB()); + + int index = 0; + this.itemWidth = width - (xOffset * 2); + for (ItemStack itemStack : setting.getValue()) { + Render2DUtils.drawOptimizedRoundedRect(x + xOffset + padding, y + FPSMaster.fontManager.s16.getHeight() + 5 + padding + (index * (itemHeight + padding)), itemWidth - padding, itemHeight, new Color(50, 50, 50, 120)); + ItemsUtil.renderItem(itemStack, x + (padding * 2) + 20f, (y + FPSMaster.fontManager.s16.getHeight() + 5 + padding * 2) + (index * (itemHeight + padding))); + renderButton(x + xOffset + itemWidth - (padding * 2) - buttonSize, (y + FPSMaster.fontManager.s16.getHeight() + 5 + padding * 2) + (index * (buttonSize + (padding * 3))), mouseX,mouseY ,"-"); + FPSMaster.fontManager.s14.drawString(itemStack.getDisplayName(), x + (padding * 2) + 45f, (y + FPSMaster.fontManager.s16.getHeight() + 5 + padding * 2) + (index * (buttonSize + (padding * 3))) + 5, -1); + index++; + } + if(setting.getValue().isEmpty()){ + this.height = itemHeight + 10; + FPSMaster.fontManager.s14.drawString(FPSMaster.i18n.get("ItemsSetting.isEmpty".toLowerCase(Locale.getDefault())), x + ((itemWidth - (padding * 2)) / 2), (y + FPSMaster.fontManager.s16.getHeight() + 5 + padding * 2) + 5, -1); + }else{ + this.height = (index * (itemHeight + padding)) + 10; + } + + } + + public void renderButton(float x, float y, float mouseX, float mouseY, String icon) { + Color color = new Color(70, 70, 70, 140); + if(Render2DUtils.isHovered(x,y,buttonSize,buttonSize,(int) mouseX,(int) mouseY)){ + color = new Color(120, 120, 120, 140); + } + Render2DUtils.drawOptimizedRoundedRect(x, y, buttonSize, buttonSize, color); + FPSMaster.fontManager.s16.drawString(icon, x + (buttonSize / 2.0f) - 2, y + (buttonSize / 2.0f) - 6, -1); + } + + @Override + public void mouseClick(float x, float y, float width, float height, float mouseX, float mouseY, int btn) { + if(Render2DUtils.isHovered(x + 10 + xOffset + itemWidth - 15, y - 3,10,10,(int)mouseX,(int)mouseY) && btn == 0){ + ItemStack heldItem = ProviderManager.mcProvider.getPlayer().getHeldItem(); + if(heldItem != null){ + this.setting.addItem(heldItem); + return; + } + } + //TODO: 转为使用迭代器Iterator实现 + for (int index = 0; index < setting.getValue().size(); index++) { + if (Render2DUtils.isHovered(x + 10 + xOffset + itemWidth - (padding * 2) - buttonSize, (y + FPSMaster.fontManager.s16.getHeight() + 5 + padding * 2) + (index * (buttonSize + (padding * 3))), buttonSize, buttonSize, (int) mouseX, (int) mouseY) && btn == 0) { + this.setting.removeItem(index); + } + } + } +} diff --git a/shared/java/top/fpsmaster/ui/custom/ComponentsManager.java b/shared/java/top/fpsmaster/ui/custom/ComponentsManager.java index 7a9cb3bf..51aaed75 100644 --- a/shared/java/top/fpsmaster/ui/custom/ComponentsManager.java +++ b/shared/java/top/fpsmaster/ui/custom/ComponentsManager.java @@ -37,6 +37,7 @@ public void init() { components.add(new ModsListComponent()); components.add(new MiniMapComponent()); components.add(new SprintComponent()); + components.add(new ItemCountDisplayComponent()); } // Get a component by its class type diff --git a/shared/java/top/fpsmaster/ui/custom/impl/ItemCountDisplayComponent.java b/shared/java/top/fpsmaster/ui/custom/impl/ItemCountDisplayComponent.java new file mode 100644 index 00000000..11ba905f --- /dev/null +++ b/shared/java/top/fpsmaster/ui/custom/impl/ItemCountDisplayComponent.java @@ -0,0 +1,74 @@ +package top.fpsmaster.ui.custom.impl; + +import net.minecraft.client.renderer.GlStateManager; +import net.minecraft.client.renderer.RenderHelper; +import net.minecraft.init.Items; +import net.minecraft.item.ItemStack; +import net.minecraft.potion.Potion; +import top.fpsmaster.features.impl.interfaces.ItemCountDisplay; +import top.fpsmaster.interfaces.ProviderManager; +import top.fpsmaster.ui.custom.Component; +import top.fpsmaster.utils.world.ItemsUtil; +import top.fpsmaster.utils.world.PotionMetadata; + +import java.util.*; +import java.util.concurrent.atomic.AtomicLong; +import java.util.stream.Collectors; + +import static top.fpsmaster.utils.Utility.mc; + +public class ItemCountDisplayComponent extends Component { + + private static final float DISPLAY_HEIGHT = 27; + private static final float ITEM_WIDTH = 17; + public Map modeItems = new HashMap<>(); + private List itemStacks = new ArrayList<>(); + public ItemCountDisplayComponent() { + super(ItemCountDisplay.class); + modeItems.put(0, + new ItemStack[]{ + ItemsUtil.getItemStack(Items.ender_pearl), + ItemsUtil.getItemStackWithMetadata(Items.potionitem, PotionMetadata.SPLASH_HEALING_II), + ItemsUtil.getItemStackWithMetadata(Items.potionitem, PotionMetadata.SPEED_II) + }); + modeItems.put(1, + new ItemStack[]{ + ItemsUtil.getItemStack(Items.golden_apple), + ItemsUtil.getItemStack(Items.arrow), + }); + + } + + @Override + public void draw(float x, float y) { + super.draw(x, y); + ItemCountDisplay displayModule = ((ItemCountDisplay) mod); + ItemStack[] mainInventory = ProviderManager.mcProvider.getPlayer().inventory.mainInventory; + + if(displayModule.modes.getValue() != 2) itemStacks = Arrays.stream(modeItems.get(displayModule.modes.getValue())).collect(Collectors.toList()); + else itemStacks = displayModule.itemsSetting.getValue(); + int index = 0; + for (ItemStack itemStack : itemStacks) { + AtomicLong count = new AtomicLong(); + Arrays.stream(mainInventory) + .filter((stack) -> { + if (stack == null) { + return false; + } + return stack.getItem() == itemStack.getItem() && stack.getMetadata() == itemStack.getMetadata(); + }) + .collect(Collectors.toList()) + .forEach((stack) -> count.addAndGet(stack.stackSize)); + float xOffset = x + index * (ITEM_WIDTH + mod.spacing.getValue().intValue()); + float textOffset = xOffset + 8f - (getStringWidth(20,String.valueOf(count)) / 2); + drawRect(xOffset,y,ITEM_WIDTH,DISPLAY_HEIGHT, mod.backgroundColor.getColor()); + ItemsUtil.renderItem(itemStack, xOffset, y); + drawString(20, String.valueOf(count), textOffset, y + ITEM_WIDTH, -1); + index++; + } + width = index * (ITEM_WIDTH + mod.spacing.getValue().intValue()); + height = DISPLAY_HEIGHT; + } + + +} diff --git a/shared/java/top/fpsmaster/ui/custom/impl/LyricsComponent.java b/shared/java/top/fpsmaster/ui/custom/impl/LyricsComponent.java index 818e983d..a15d4ef5 100644 --- a/shared/java/top/fpsmaster/ui/custom/impl/LyricsComponent.java +++ b/shared/java/top/fpsmaster/ui/custom/impl/LyricsComponent.java @@ -12,7 +12,9 @@ import top.fpsmaster.utils.math.animation.Type; import top.fpsmaster.utils.render.Render2DUtils; +import java.awt.*; import java.util.List; +import java.util.Objects; public class LyricsComponent extends Component { @@ -23,6 +25,7 @@ public LyricsComponent() { y = 0.2f; height = 70f; position = Position.CT; + allowScale = true; } private long fromTimeTick(String timeTick) { @@ -43,6 +46,7 @@ public void draw(float x, float y) { }else{ y += 5; } + y += (scale - 1) * 23; AbstractMusic current = NewMusicPanel.playing; if (current != null && current.lyrics != null) { int curLine = -1; @@ -77,22 +81,23 @@ public void draw(float x, float y) { Line line = lines.get(j); String content = line.getContent(); float stringWidth = getStringWidth(20, content); - float xOffset = x + (width - stringWidth) / 2; + float xOffset = x + (width - stringWidth) / 2 * scale ; width = 200f; - if (this.width < stringWidth + 10) { - this.width = stringWidth + 10; + + if (this.width < stringWidth + 10 ) { + this.width = stringWidth + 10 ; } if (j == curLine) { - line.animation = (float) AnimationUtils.base(line.animation, 0.0, 0.1f); - line.alpha = (float) AnimationUtils.base(line.alpha, 1.0, 0.1f); + line.animation = (float) AnimationUtils.base(line.animation, 0.0, 0.05f); + line.alpha = (float) AnimationUtils.base(line.alpha, 1.0, 0.05f); } else { - line.animation = (float) AnimationUtils.base(line.animation, j - curLine, 0.1f); + line.animation = (float) AnimationUtils.base(line.animation, j - curLine, 0.05f); line.alpha = (float) (Math.abs(j - curLine) == 1 ? - AnimationUtils.base(line.alpha, 1.0, 0.1f) : - AnimationUtils.base(line.alpha, 0.0, 0.1f)); + AnimationUtils.base(line.alpha, 1.0, 0.05f) : + AnimationUtils.base(line.alpha, 0.0, 0.05f)); } if (Math.abs(j - curLine) <= 1) { - drawLine(line, xOffset, y + line.animation * 20 + 20, 20,j == curLine); + drawLine(line, xOffset, y + line.animation * (20 * scale)+ 20, 20,j == curLine); } } } @@ -113,7 +118,8 @@ private void drawLine(Line line, float xOffset, float y, int font, boolean curre } line.scaleAnimation.update(); scaleRatio = (float) line.scaleAnimation.value; - Render2DUtils.scaleStart(xOffset + (getStringWidth(20, line.getContent()) / 2.0f), y + (getStringHeight(20) / 2.0f), scaleRatio); + + Render2DUtils.scaleStart(xOffset + (getStringWidth((int) (20 * scale), line.getContent()) / 2.0f), y + (getStringHeight(20) / 2.0f), scaleRatio); GL11.glTranslated(0, -8, 0); } for (Word word : line.words) { @@ -136,12 +142,12 @@ private float drawWord(Word word, float xOffset, float y, Line line) { drawString(20, word.content, xOffset, y + 7, Render2DUtils.reAlpha(LyricsDisplay.textColor.getColor(), (int) Math.min(line.alpha * 120, 255)).getRGB()); } - return getStringWidth(20, word.content); + return getStringWidth(20, word.content) * scale; } private float drawWordBG(Word word, float xOffset, float y, Line line) { drawString(20, word.content, xOffset, y + 5, Render2DUtils.reAlpha(LyricsDisplay.textBG.getColor(), (int) Math.min(line.alpha * 120, 255)).getRGB()); - return getStringWidth(20, word.content); + return getStringWidth(20, word.content) * scale; } } diff --git a/shared/java/top/fpsmaster/utils/Utility.java b/shared/java/top/fpsmaster/utils/Utility.java index 3ac575a9..bd2fa991 100644 --- a/shared/java/top/fpsmaster/utils/Utility.java +++ b/shared/java/top/fpsmaster/utils/Utility.java @@ -5,6 +5,8 @@ import top.fpsmaster.modules.dev.DevMode; import java.util.ArrayList; +import java.util.function.BiConsumer; +import java.util.function.Consumer; public class Utility { @@ -46,4 +48,24 @@ public static void flush() { } messages.clear(); } + /** + * withIndex实现streamAPI foreach循环附带index
+ * 用法: + * + * list.stream().forEach(Utility.withIndex((item,index)->{ + * ... + * })) + * + */ + public static Consumer withIndex(BiConsumer biConsumer) { + class IncrementInt{ + int i = 0; + public int getAndIncrement(){ + return i++; + } + } + IncrementInt incrementInt = new IncrementInt(); + return t -> biConsumer.accept(t, incrementInt.getAndIncrement()); + } + } diff --git a/shared/java/top/fpsmaster/utils/world/PotionMetadata.java b/shared/java/top/fpsmaster/utils/world/PotionMetadata.java new file mode 100644 index 00000000..72137ab8 --- /dev/null +++ b/shared/java/top/fpsmaster/utils/world/PotionMetadata.java @@ -0,0 +1,206 @@ +package top.fpsmaster.utils.world; // 替换为你的mod包名 + +import net.minecraft.potion.Potion; // 用于 Potion.heal.id 等 +import java.util.HashMap; +import java.util.Map; + + +public class PotionMetadata { + + public static final int SPLASH_POTION_COMMON_OFFSET = 16384; // 0x4000 + public static final int WATER_BOTTLE = 0; + + public static final int HEALING_I = 8197; + public static final int HEALING_II = 8261; + + public static final int HARMING_I = 8260; + public static final int HARMING_II = 8204; + + public static final int SPEED_I = 8258; + public static final int SPEED_II = 8226; + + public static final int SLOWNESS_I = 8202; + + public static final int STRENGTH_I = 8265; + public static final int STRENGTH_II = 8201; + + public static final int NIGHT_VISION_I = 8262; + + public static final int INVISIBILITY_I = 8230; + + public static final int POISON_I = 8264; + public static final int POISON_II = 8200; + + public static final int REGENERATION_I = 8257; + public static final int REGENERATION_II = 8225; + + public static final int FIRE_RESISTANCE_I = 8259; + + public static final int WATER_BREATHING_I = 8231; + + public static final int WEAKNESS_I = 8232; + + public static final int LEAPING_I = 8235; + public static final int LEAPING_II = 8203; + + public static final int SPLASH_WATER_BOTTLE = 16384; + + public static final int SPLASH_HEALING_I = 16388; + public static final int SPLASH_HEALING_II = 16421; + + public static final int SPLASH_HARMING_I = 16420; + public static final int SPLASH_HARMING_II = 16364; + + public static final int SPLASH_SPEED_I = 16418; + public static final int SPLASH_SPEED_II = 16386; + + public static final int SPLASH_SLOWNESS_I = 16362; + + public static final int SPLASH_STRENGTH_I = 16425; + public static final int SPLASH_STRENGTH_II = 16361; + + public static final int SPLASH_NIGHT_VISION_I = 16422; + + public static final int SPLASH_INVISIBILITY_I = 16390; + + public static final int SPLASH_POISON_I = 16424; + public static final int SPLASH_POISON_II = 16360; + + public static final int SPLASH_REGENERATION_I = 16417; + public static final int SPLASH_REGENERATION_II = 16385; + + public static final int SPLASH_FIRE_RESISTANCE_I = 16419; + + public static final int SPLASH_WATER_BREATHING_I = 16391; + + public static final int SPLASH_WEAKNESS_I = 16392; + + public static final int SPLASH_LEAPING_I = 16395; + public static final int SPLASH_LEAPING_II = 16363; + + private static final Map> basePotionMetadataMap = new HashMap<>(); + private static final Map> splashPotionMetadataMap = new HashMap<>(); + + static { + Map healingMap = new HashMap<>(); + healingMap.put(false, HEALING_I); + healingMap.put(true, HEALING_II); + basePotionMetadataMap.put(Potion.heal.id, healingMap); + + Map harmingMap = new HashMap<>(); + harmingMap.put(false, HARMING_I); + harmingMap.put(true, HARMING_II); + basePotionMetadataMap.put(Potion.harm.id, harmingMap); + + Map speedMap = new HashMap<>(); + speedMap.put(false, SPEED_I); + speedMap.put(true, SPEED_II); + basePotionMetadataMap.put(Potion.moveSpeed.id, speedMap); + + Map slownessMap = new HashMap<>(); + slownessMap.put(false, SLOWNESS_I); // Slowness usually no II + basePotionMetadataMap.put(Potion.moveSlowdown.id, slownessMap); + + Map strengthMap = new HashMap<>(); + strengthMap.put(false, STRENGTH_I); + strengthMap.put(true, STRENGTH_II); + basePotionMetadataMap.put(Potion.damageBoost.id, strengthMap); + + Map nightVisionMap = new HashMap<>(); + nightVisionMap.put(false, NIGHT_VISION_I); + basePotionMetadataMap.put(Potion.nightVision.id, nightVisionMap); + + Map invisibilityMap = new HashMap<>(); + invisibilityMap.put(false, INVISIBILITY_I); + basePotionMetadataMap.put(Potion.invisibility.id, invisibilityMap); + + Map poisonMap = new HashMap<>(); + poisonMap.put(false, POISON_I); + poisonMap.put(true, POISON_II); + basePotionMetadataMap.put(Potion.poison.id, poisonMap); + + Map regenerationMap = new HashMap<>(); + regenerationMap.put(false, REGENERATION_I); + regenerationMap.put(true, REGENERATION_II); + basePotionMetadataMap.put(Potion.regeneration.id, regenerationMap); + + Map fireResistanceMap = new HashMap<>(); + fireResistanceMap.put(false, FIRE_RESISTANCE_I); + basePotionMetadataMap.put(Potion.fireResistance.id, fireResistanceMap); + + Map waterBreathingMap = new HashMap<>(); + waterBreathingMap.put(false, WATER_BREATHING_I); + basePotionMetadataMap.put(Potion.waterBreathing.id, waterBreathingMap); + + Map weaknessMap = new HashMap<>(); + weaknessMap.put(false, WEAKNESS_I); + basePotionMetadataMap.put(Potion.weakness.id, weaknessMap); + + Map leapingMap = new HashMap<>(); + leapingMap.put(false, LEAPING_I); + leapingMap.put(true, LEAPING_II); + basePotionMetadataMap.put(Potion.jump.id, leapingMap); + + // 初始化可喷溅药水映射 + Map splashHealingMap = new HashMap<>(); + splashHealingMap.put(false, SPLASH_HEALING_I); + splashHealingMap.put(true, SPLASH_HEALING_II); + splashPotionMetadataMap.put(Potion.heal.id, splashHealingMap); + + Map splashHarmingMap = new HashMap<>(); + splashHarmingMap.put(false, SPLASH_HARMING_I); + splashHarmingMap.put(true, SPLASH_HARMING_II); + splashPotionMetadataMap.put(Potion.harm.id, splashHarmingMap); + + Map splashSpeedMap = new HashMap<>(); + splashSpeedMap.put(false, SPLASH_SPEED_I); + splashSpeedMap.put(true, SPLASH_SPEED_II); + splashPotionMetadataMap.put(Potion.moveSpeed.id, splashSpeedMap); + + Map splashSlownessMap = new HashMap<>(); + splashSlownessMap.put(false, SPLASH_SLOWNESS_I); + splashPotionMetadataMap.put(Potion.moveSlowdown.id, splashSlownessMap); + + Map splashStrengthMap = new HashMap<>(); + splashStrengthMap.put(false, SPLASH_STRENGTH_I); + splashStrengthMap.put(true, SPLASH_STRENGTH_II); + splashPotionMetadataMap.put(Potion.damageBoost.id, splashStrengthMap); + + Map splashNightVisionMap = new HashMap<>(); + splashNightVisionMap.put(false, SPLASH_NIGHT_VISION_I); + splashPotionMetadataMap.put(Potion.nightVision.id, splashNightVisionMap); + + Map splashInvisibilityMap = new HashMap<>(); + splashInvisibilityMap.put(false, SPLASH_INVISIBILITY_I); + splashPotionMetadataMap.put(Potion.invisibility.id, splashInvisibilityMap); + + Map splashPoisonMap = new HashMap<>(); + splashPoisonMap.put(false, SPLASH_POISON_I); + splashPoisonMap.put(true, SPLASH_POISON_II); + splashPotionMetadataMap.put(Potion.poison.id, splashPoisonMap); + + Map splashRegenerationMap = new HashMap<>(); + splashRegenerationMap.put(false, SPLASH_REGENERATION_I); + splashRegenerationMap.put(true, SPLASH_REGENERATION_II); + splashPotionMetadataMap.put(Potion.regeneration.id, splashRegenerationMap); + + Map splashFireResistanceMap = new HashMap<>(); + splashFireResistanceMap.put(false, SPLASH_FIRE_RESISTANCE_I); + splashPotionMetadataMap.put(Potion.fireResistance.id, splashFireResistanceMap); + + Map splashWaterBreathingMap = new HashMap<>(); + splashWaterBreathingMap.put(false, SPLASH_WATER_BREATHING_I); + splashPotionMetadataMap.put(Potion.waterBreathing.id, splashWaterBreathingMap); + + Map splashWeaknessMap = new HashMap<>(); + splashWeaknessMap.put(false, SPLASH_WEAKNESS_I); + splashPotionMetadataMap.put(Potion.weakness.id, splashWeaknessMap); + + Map splashLeapingMap = new HashMap<>(); + leapingMap.put(false, SPLASH_LEAPING_I); + leapingMap.put(true, SPLASH_LEAPING_II); + splashPotionMetadataMap.put(Potion.jump.id, splashLeapingMap); + } + + +} \ No newline at end of file diff --git a/shared/resources/assets/minecraft/client/lang/en_us.lang b/shared/resources/assets/minecraft/client/lang/en_us.lang index 808593ec..05bd34ae 100644 --- a/shared/resources/assets/minecraft/client/lang/en_us.lang +++ b/shared/resources/assets/minecraft/client/lang/en_us.lang @@ -220,6 +220,7 @@ autogg=AutoGG autogg.desc=Automatically send a custom message after a game has ended. autogg.servers=Servers autogg.servers.hypxiel=Hypxiel +autogg.servers.kkcraft=KKCraft autogg.message=Custom Message autogg.autoplay=Auto Play autogg.delaytoplay=Auto Play Delay @@ -383,6 +384,24 @@ targetdisplay.roundradius=Corner Radius targetdisplay.background=Show Background targetdisplay.omitname=Omit Long Names +itemcountdisplay=Item Count Display +itemcountdisplay.desc=Quick show your items count in hud +itemcountdisplay.round=Rounded Corners +itemcountdisplay.roundradius=Corner Radius +itemcountdisplay.background=Show Background +itemcountdisplay.backgroundcolor=Background Color +itemcountdisplay.betterfont=Clean Font +itemcountdisplay.fontshadow=Font Shadow +itemcountdisplay.spacing=Spacing +itemcountdisplay.mode=Mode +itemcountdisplay.mode.potpvp=Pot PVP +itemcountdisplay.mode.uhc=UHC +itemcountdisplay.mode.custom=Custom +itemcountdisplay.items=Items + +itemssetting.isempty=null +itemssetting.helditem=your current held item + minimizedbobbing=No Bobbing minimizedbobbing.desc=Removes all screen shake @@ -443,6 +462,8 @@ coordsdisplay.limitdisplayy=Y Limit coordsdisplay.roundradius=Corner Radius coordsdisplay.background=Show Background + + modslist=Mod List modslist.desc=Show enabled modules modslist.showtext=Show Custom Text diff --git a/shared/resources/assets/minecraft/client/lang/zh_cn.lang b/shared/resources/assets/minecraft/client/lang/zh_cn.lang index 1745388c..088dbbad 100644 --- a/shared/resources/assets/minecraft/client/lang/zh_cn.lang +++ b/shared/resources/assets/minecraft/client/lang/zh_cn.lang @@ -222,6 +222,7 @@ autogg=自动GG autogg.desc=游戏结束后自动地在发送你自定义的消息 autogg.servers=服务器列表 autogg.servers.hypxiel=Hypxiel +autogg.servers.kkcraft=KKCraft autogg.message=自定义消息 autogg.autoplay=自动重开 autogg.delaytoplay=自动重开延迟 @@ -385,6 +386,25 @@ targetdisplay.roundradius=圆角半径 targetdisplay.background=背景 targetdisplay.omitname=省略过长的名字 +itemcountdisplay=物品数量 +itemcountdisplay.desc=便捷的展示你的物品数量 +itemcountdisplay.round=背景圆角 +itemcountdisplay.roundradius=圆角半径 +itemcountdisplay.background=背景 +itemcountdisplay.backgroundcolor=背景颜色 +itemcountdisplay.betterfont=更好的字体 +itemcountdisplay.fontshadow=字体阴影 +itemcountdisplay.spacing=间距 +itemcountdisplay.mode=模式 +itemcountdisplay.mode.potpvp=Pot PVP +itemcountdisplay.mode.uhc=UHC +itemcountdisplay.mode.custom=自定义 + +itemcountdisplay.items=物品 + +itemssetting.isempty=空的 +itemssetting.helditem=你当前手持的物品 + minimizedbobbing=最小摇晃 minimizedbobbing.desc=停止全局的摇晃 diff --git a/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinLayerCape.java b/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinLayerCape.java index fd1bc8e2..5a7251c8 100644 --- a/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinLayerCape.java +++ b/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinLayerCape.java @@ -32,9 +32,13 @@ public abstract class MixinLayerCape implements LayerRenderer Date: Fri, 25 Jul 2025 17:53:53 +0800 Subject: [PATCH 183/193] fix: music login fix: compass display fix: compile error --- .../modules/music/netease/NeteaseApi.java | 48 +++++++++++++ .../netease/deserialize/MusicWrapper.java | 5 +- shared/java/top/fpsmaster/ui/Compass.java | 6 +- .../ui/click/music/NewMusicPanel.java | 27 +++++--- .../top/fpsmaster/utils/os/CryptUtils.java | 45 ++++++++++++ .../top/fpsmaster/utils/world/ItemsUtil.java | 68 +++++++++++++++++++ 6 files changed, 185 insertions(+), 14 deletions(-) create mode 100644 shared/java/top/fpsmaster/utils/world/ItemsUtil.java diff --git a/shared/java/top/fpsmaster/modules/music/netease/NeteaseApi.java b/shared/java/top/fpsmaster/modules/music/netease/NeteaseApi.java index c17bee05..c3558f00 100644 --- a/shared/java/top/fpsmaster/modules/music/netease/NeteaseApi.java +++ b/shared/java/top/fpsmaster/modules/music/netease/NeteaseApi.java @@ -1,15 +1,42 @@ package top.fpsmaster.modules.music.netease; import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; +import top.fpsmaster.utils.os.CryptUtils; import top.fpsmaster.utils.os.HttpRequest; import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.net.URLEncoder; +import java.util.Random; public class NeteaseApi { private static final String BASE_URL = "https://music.skidder.top/"; + public static JsonParser parser = new JsonParser(); public static String cookies = ""; + public static String encryptRequest(String text) { + String secKey = CryptUtils.createSecretKey(16); + // Key + String nonce = "0CoJUm6Qyw8W8jud"; + String encText = CryptUtils.aesEncrypt(CryptUtils.aesEncrypt(text, nonce), secKey); + String modulus = "00e0b509f6259df8642dbc35662901477df22677ec152b5ff68ace615bb7" + + "b725152b3ab17a876aea8a5aa76d2e417629ec4ee341f56135fccf695280" + + "104e0312ecbda92557c93870114af6c9d05c4f7f0c3685b7a46bee255932" + + "575cce10b424d813cfe4875d3e82047b97ddef52741d546b8e289dc6935b" + "3ece0462db0a22b8e7"; + String pubKey = "010001"; + String encSecKey = CryptUtils.rsaEncrypt(secKey, pubKey, modulus); + try { + return "params=" + URLEncoder.encode(encText, "UTF-8") + "&encSecKey=" + + URLEncoder.encode(encSecKey, "UTF-8"); + } catch (UnsupportedEncodingException e) { + return null; + } + } + + public static String getVerbatimLyrics(String id) { String url = BASE_URL + "lyric/new?id=" + id; try { @@ -73,6 +100,7 @@ public static String getDailyList() { } } + @Deprecated public static String getUniKey() { String url = BASE_URL + "login/qr/key?timestamp=" + System.currentTimeMillis(); try { @@ -82,6 +110,26 @@ public static String getUniKey() { } } + public static String getUniKeyNew() { + JsonObject obj = new JsonObject(); + obj.addProperty("type", 1); + + String data = encryptRequest(obj.toString()); + + HttpRequest.HttpResponseResult post = null; + try { + post = HttpRequest.post("https://music.163.com/weapi/login/qrcode/unikey?"+data,null); + } catch (IOException e) { + throw new RuntimeException(e); + } + if (post.isSuccess()) { + return ((JsonObject) parser.parse(post.getBody())).get("unikey").getAsString(); + }else{ + return null; + } + } + + public static String generateQRCode(String key) { String url = BASE_URL + "login/qr/create?key=" + key + "&qrimg=true×tamp=" + System.currentTimeMillis(); try { diff --git a/shared/java/top/fpsmaster/modules/music/netease/deserialize/MusicWrapper.java b/shared/java/top/fpsmaster/modules/music/netease/deserialize/MusicWrapper.java index 554e2f0c..f30a5f95 100644 --- a/shared/java/top/fpsmaster/modules/music/netease/deserialize/MusicWrapper.java +++ b/shared/java/top/fpsmaster/modules/music/netease/deserialize/MusicWrapper.java @@ -22,8 +22,9 @@ public static String getSongUrl(String id) { } public static String getQRKey() { - JsonObject jsonObject = gson.fromJson(NeteaseApi.getUniKey(), JsonObject.class); - return jsonObject == null ? null : jsonObject.getAsJsonObject("data").get("unikey").getAsString(); +// JsonObject jsonObject = gson.fromJson(NeteaseApi.getUniKeyNew(), JsonObject.class); +// return jsonObject == null ? null : jsonObject.get("unikey").getAsString(); + return NeteaseApi.getUniKeyNew(); } public static String getQRCodeImg(String key) { diff --git a/shared/java/top/fpsmaster/ui/Compass.java b/shared/java/top/fpsmaster/ui/Compass.java index 95742bc0..a9085f04 100644 --- a/shared/java/top/fpsmaster/ui/Compass.java +++ b/shared/java/top/fpsmaster/ui/Compass.java @@ -58,13 +58,13 @@ public void draw(ScaledResolution sr) { if (ProviderManager.mcProvider.getPlayer() == null) return; preRender(sr); - float center = sr.getScaledWidth() / 2f; + float center = Render2DUtils.getFixedBounds()[0] / 2; int count = 0; float yaaahhrewindTime = (ProviderManager.mcProvider.getPlayer().rotationYaw % 360) * 2 + 360 * 3; GL11.glPushMatrix(); GL11.glEnable(3089); int scaleFactor = Render2DUtils.fixScale(); - Render2DUtils.doGlScissor(sr.getScaledWidth() / 2f - 100, 25, 200, 25, scaleFactor); + Render2DUtils.doGlScissor(Render2DUtils.getFixedBounds()[0] / 2f - 100, 25, 200, 25, scaleFactor); for (Degree d : degrees) { float location = center + (count * 30) - yaaahhrewindTime; float completeLocation = d.type == 1 ? (location - FPSMaster.fontManager.s28.getStringWidth(d.text) / 2f) @@ -169,7 +169,7 @@ public static void preRender(ScaledResolution sr) { public static int opacity(ScaledResolution sr, float offset) { int op = 0; - float offs = 255 - Math.abs(sr.getScaledWidth() / 2f - offset) * 1.8f; + float offs = 255 - Math.abs(Render2DUtils.getFixedBounds()[0] / 2f - offset) * 1.8f; Color c = new Color(255, 255, 255, (int) Math.min(Math.max(0, offs), 255)); return c.getRGB(); } diff --git a/shared/java/top/fpsmaster/ui/click/music/NewMusicPanel.java b/shared/java/top/fpsmaster/ui/click/music/NewMusicPanel.java index fe27db88..0fb05ce3 100644 --- a/shared/java/top/fpsmaster/ui/click/music/NewMusicPanel.java +++ b/shared/java/top/fpsmaster/ui/click/music/NewMusicPanel.java @@ -103,19 +103,20 @@ public static void init() { searching = true; if (profile == null) profile = MusicWrapper.getProfile(); + if (profile != null) { + if (dailyTracks.isEmpty()) { + dailyTracks = MusicWrapper.getTracksDaily(); + } + if (likedTracks.isEmpty()) { + likedTracks = MusicWrapper.getTracksLiked(profile.id); + } + } + searching = false; if (recommendTrack == null || recommendTrack.getMusics().isEmpty()) { recommendTrack = new Track(0L, "日推", ""); recommendTrack.setMusics(MusicWrapper.getSongsFromDaily().musics); recommendTrack.setLoaded(true); } - if (dailyTracks.isEmpty()) { - dailyTracks = MusicWrapper.getTracksDaily(); - } - - if (likedTracks.isEmpty()) { - likedTracks = MusicWrapper.getTracksLiked(profile.id); - } - searching = false; }); loadThread.start(); } @@ -141,6 +142,11 @@ public static void draw(float x, int y, float width, float height, int mouseX, i searchField.drawTextBox(x + 32, y + 14, 100, 16); if (Render2DUtils.isHovered(x + 12, y + 14, 16, 16, mouseX, mouseY) && consumeClick(0)) { currentTrack = null; + isWaitingLogin = false; + if (loginThread != null) { + loginThread.interrupt(); + loginThread = null; + } } if (profile == null) { int stringWidth = FPSMaster.fontManager.s16.getStringWidth(FPSMaster.i18n.get("music.notLoggedIn")); @@ -386,7 +392,9 @@ private static void reloadImg() { try { FileUtils.saveTempValue("cookies", NeteaseApi.cookies); - System.out.println("cookies: " + NeteaseApi.cookies); + isWaitingLogin = false; + profile = MusicWrapper.getProfile(); + return; } catch (FileException e) { ExceptionHandler.handleFileException(e, "无法保存cookies"); } @@ -399,6 +407,7 @@ private static void reloadImg() { }); FPSMaster.async.runnable(() -> { key = MusicWrapper.getQRKey(); + System.out.println(key); if (key == null) return; String base64 = MusicWrapper.getQRCodeImg(key); // render base64 img data diff --git a/shared/java/top/fpsmaster/utils/os/CryptUtils.java b/shared/java/top/fpsmaster/utils/os/CryptUtils.java index 9ab9a2c3..002c6861 100644 --- a/shared/java/top/fpsmaster/utils/os/CryptUtils.java +++ b/shared/java/top/fpsmaster/utils/os/CryptUtils.java @@ -1,12 +1,15 @@ package top.fpsmaster.utils.os; import javax.crypto.Cipher; +import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.SecretKeySpec; +import java.math.BigInteger; import java.nio.charset.StandardCharsets; import java.security.Key; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.util.Base64; +import java.util.Random; public class CryptUtils { private static final String ALGORITHM = "AES"; @@ -82,4 +85,46 @@ public static String getSHA256Hash(String input) { return null; } } + + + public static String aesEncrypt(String text, String key) { + try { + IvParameterSpec iv = new IvParameterSpec("0102030405060708".getBytes(StandardCharsets.UTF_8)); + SecretKeySpec skeySpec = new SecretKeySpec(key.getBytes(StandardCharsets.UTF_8), "AES"); + + Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); + cipher.init(Cipher.ENCRYPT_MODE, skeySpec, iv); + + byte[] encrypted = cipher.doFinal(text.getBytes()); + + return Base64.getEncoder().encodeToString(encrypted); + } catch (Exception ex) { + return ""; + } + } + + public static String rsaEncrypt(String text, String pubKey, String modulus) { + text = new StringBuilder(text).reverse().toString(); + BigInteger rs = new BigInteger(String.format("%x", new BigInteger(1, text.getBytes())), 16) + .modPow(new BigInteger(pubKey, 16), new BigInteger(modulus, 16)); + StringBuilder r = new StringBuilder(rs.toString(16)); + if (r.length() >= 256) { + return r.substring(r.length() - 256); + } else { + while (r.length() < 256) { + r.insert(0, 0); + } + return r.toString(); + } + } + + + public static String createSecretKey(int length) { + String shits = "0123456789abcdefghijklmnopqrstuvwxyz"; + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < length; ++i) { + sb.append(shits.charAt(new Random().nextInt(shits.length()))); + } + return sb.toString(); + } } diff --git a/shared/java/top/fpsmaster/utils/world/ItemsUtil.java b/shared/java/top/fpsmaster/utils/world/ItemsUtil.java new file mode 100644 index 00000000..978b789d --- /dev/null +++ b/shared/java/top/fpsmaster/utils/world/ItemsUtil.java @@ -0,0 +1,68 @@ +package top.fpsmaster.utils.world; + +import net.minecraft.client.renderer.GlStateManager; +import net.minecraft.client.renderer.RenderHelper; +import net.minecraft.item.Item; +import net.minecraft.item.ItemPotion; +import net.minecraft.item.ItemStack; +import net.minecraft.potion.PotionEffect; +import top.fpsmaster.interfaces.ProviderManager; +import top.fpsmaster.utils.Utility; + +import java.util.List; + +public class ItemsUtil { + + public static ItemStack getItemStack(Item item) { + return new ItemStack(item); + } + public static ItemStack getItemStackWithMetadata(Item item, int metadata) { + ItemStack itemStack = new ItemStack(item); + itemStack.setItemDamage(metadata); + return itemStack; + + } + public static boolean isSplashPotion(ItemStack stack){ + if (stack == null) { + return false; + } + return stack.getItem() instanceof ItemPotion && ItemPotion.isSplash(stack.getMetadata()); + } + public static boolean isPotionEffect(ItemStack stack,int potionID) { + if (stack == null || !(stack.getItem() instanceof ItemPotion)) { + return false; + } + List effects = ((ItemPotion) stack.getItem()).getEffects(stack); + if (effects != null && !effects.isEmpty()) { + for (PotionEffect effect : effects) { + // 治疗药水的 Potion ID 是 Potion.heal.id + if (effect.getPotionID() == potionID) { + return true; + } + } + } + return false; + } + public static void renderItem(ItemStack itemStack, float x, float y) { + ItemStack copyItem = itemStack.copy(); + copyItem.stackSize = 1; + GlStateManager.pushMatrix(); + GlStateManager.disableCull(); + GlStateManager.disableBlend(); + GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F); + + GlStateManager.enableRescaleNormal(); + GlStateManager.enableBlend(); + GlStateManager.tryBlendFuncSeparate(770, 771, 1, 0); + RenderHelper.enableGUIStandardItemLighting(); + GlStateManager.pushMatrix(); + Utility.mc.getRenderItem().renderItemIntoGUI(copyItem, (int) x, (int) y); + GlStateManager.popMatrix(); + Utility.mc.getRenderItem().renderItemOverlays(ProviderManager.mcProvider.getFontRenderer(), copyItem, (int) x, (int) y); + + RenderHelper.disableStandardItemLighting(); + GlStateManager.disableRescaleNormal(); + GlStateManager.disableBlend(); + GlStateManager.popMatrix(); + } +} From 25e8fcd4b44cfbfcdf5d38e249b0b83416ff8715 Mon Sep 17 00:00:00 2001 From: SuperSkidder Date: Fri, 25 Jul 2025 17:57:37 +0800 Subject: [PATCH 184/193] fix: music login fix: compass display fix: compile error fix: gui multiplayer bug --- shared/java/top/fpsmaster/ui/mc/GuiMultiplayer.java | 1 + 1 file changed, 1 insertion(+) diff --git a/shared/java/top/fpsmaster/ui/mc/GuiMultiplayer.java b/shared/java/top/fpsmaster/ui/mc/GuiMultiplayer.java index ade03187..05b4ab8f 100644 --- a/shared/java/top/fpsmaster/ui/mc/GuiMultiplayer.java +++ b/shared/java/top/fpsmaster/ui/mc/GuiMultiplayer.java @@ -89,6 +89,7 @@ public class GuiMultiplayer extends ScaledGuiScreen { @Override public void initGui() { super.initGui(); + tab = 0; loadServerList(); serverListInternet.clear(); for (ServerData server : servers) { From 58fe0e911db1947d42679a033dc0cd4733f7dd90 Mon Sep 17 00:00:00 2001 From: TeAnli <159260777+TeAnli@users.noreply.github.com> Date: Fri, 25 Jul 2025 20:29:19 +0800 Subject: [PATCH 185/193] fix: delete test code (#109) --- .../java/top/fpsmaster/features/impl/utility/AutoGG.java | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/shared/java/top/fpsmaster/features/impl/utility/AutoGG.java b/shared/java/top/fpsmaster/features/impl/utility/AutoGG.java index 6103f0e4..bd81c606 100644 --- a/shared/java/top/fpsmaster/features/impl/utility/AutoGG.java +++ b/shared/java/top/fpsmaster/features/impl/utility/AutoGG.java @@ -35,7 +35,6 @@ public void onPacket(EventPacket event) { String componentValue = ProviderManager.packetChat.getChatComponent(event.packet).toString(); String chatMessage = ProviderManager.packetChat.getUnformattedText(event.packet); boolean hasEndInformation = false; - Utility.sendClientMessage(componentValue); switch (servers.getValue()) { case 0: boolean hasPlayCommand = componentValue.contains("ClickEvent{action=RUN_COMMAND, value='/play "); @@ -67,9 +66,9 @@ public void onPacket(EventPacket event) { } if (hasEndInformation) { Utility.sendChatMessage(message.getValue()); - } - if(autoPlay.getValue()) { - Utility.sendClientNotify("AutoPlay is not supported at the moment in KKCraft"); + if(autoPlay.getValue()) { + Utility.sendClientNotify("AutoPlay is not supported at the moment in KKCraft"); + } } break; default: From 3a93c5a84807f085eda5e0b01101e876a1a58fe1 Mon Sep 17 00:00:00 2001 From: vlouboos Date: Fri, 25 Jul 2025 21:40:18 +0800 Subject: [PATCH 186/193] Optimize code --- .../features/impl/utility/AutoGG.java | 63 +++++++++---------- 1 file changed, 30 insertions(+), 33 deletions(-) diff --git a/shared/java/top/fpsmaster/features/impl/utility/AutoGG.java b/shared/java/top/fpsmaster/features/impl/utility/AutoGG.java index bd81c606..315b1110 100644 --- a/shared/java/top/fpsmaster/features/impl/utility/AutoGG.java +++ b/shared/java/top/fpsmaster/features/impl/utility/AutoGG.java @@ -1,5 +1,7 @@ package top.fpsmaster.features.impl.utility; +import net.minecraft.event.ClickEvent; +import net.minecraft.util.IChatComponent; import net.minecraft.util.StringUtils; import top.fpsmaster.FPSMaster; import top.fpsmaster.event.Subscribe; @@ -11,9 +13,6 @@ import top.fpsmaster.features.settings.impl.NumberSetting; import top.fpsmaster.features.settings.impl.TextSetting; import top.fpsmaster.interfaces.ProviderManager; -import top.fpsmaster.modules.logger.ClientLogger; -import top.fpsmaster.ui.notification.Notification; -import top.fpsmaster.ui.notification.NotificationManager; import top.fpsmaster.utils.Utility; public class AutoGG extends Module { @@ -21,9 +20,9 @@ public class AutoGG extends Module { public NumberSetting delay = new NumberSetting("DelayToPlay", 5, 0, 10, 1, () -> autoPlay.getValue()); public TextSetting message = new TextSetting("Message", "gg"); public ModeSetting servers = new ModeSetting("Servers", 0, "hypxiel", "kkcraft"); + public String[] hypixelTrigger = new String[]{"Reward Summary", "1st Killer", "Damage Dealt", "奖励总览", "击杀数第一名", "造成伤害"}; + public String[] kkcraftTrigger = new String[]{"获胜者", "第一名杀手", "击杀第一名"}; - public String hypixelTrigger = "Reward Summary;1st Killer;Damage Dealt;奖励总览;击杀数第一名;造成伤害"; - public String kkcraftTrigger = "获胜者;第一名杀手;击杀第一名"; public AutoGG() { super("AutoGG", Category.Utility); this.addSettings(autoPlay, delay, message, servers); @@ -32,42 +31,40 @@ public AutoGG() { @Subscribe public void onPacket(EventPacket event) { if (event.type == EventPacket.PacketType.RECEIVE && ProviderManager.packetChat.isPacket(event.packet)) { - String componentValue = ProviderManager.packetChat.getChatComponent(event.packet).toString(); - String chatMessage = ProviderManager.packetChat.getUnformattedText(event.packet); - boolean hasEndInformation = false; + IChatComponent componentValue = ProviderManager.packetChat.getChatComponent(event.packet); + String chatMessage = componentValue.getUnformattedText(); switch (servers.getValue()) { case 0: - boolean hasPlayCommand = componentValue.contains("ClickEvent{action=RUN_COMMAND, value='/play "); - for (String s : hypixelTrigger.split(";")) { - hasEndInformation = StringUtils.stripControlCodes(chatMessage).contains(s); - if (hasEndInformation) break; - } - if (hasEndInformation) { - Utility.sendChatMessage("/ac " + message.getValue()); + for (String s : hypixelTrigger) { + if (StringUtils.stripControlCodes(chatMessage).contains(s)) { + Utility.sendChatMessage("/ac " + message.getValue()); + break; + } } - if (hasPlayCommand) { - if (autoPlay.getValue()) { - FPSMaster.async.runnable(() -> { + if (autoPlay.getValue()) { + for (IChatComponent chatComponent : componentValue.getSiblings()) { + ClickEvent clickEvent = chatComponent.getChatStyle().getChatClickEvent(); + if (clickEvent != null && clickEvent.getAction().equals(ClickEvent.Action.RUN_COMMAND) && clickEvent.getValue().trim().toLowerCase().startsWith("/play ")) { Utility.sendClientNotify("Sending you to the next game in " + delay.getValue() + " seconds"); - try { - Thread.sleep(delay.getValue().longValue() * 1000); - } catch (InterruptedException e) { - throw new RuntimeException(e); - } - Utility.sendChatMessage(componentValue.substring(componentValue.indexOf("value='") + 7, componentValue.indexOf("'}"))); - }); + FPSMaster.async.runnable(() -> { + try { + Thread.sleep(delay.getValue().longValue() * 1000); + Utility.sendChatMessage(clickEvent.getValue()); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + }); + } } } break; case 1: - for (String s : kkcraftTrigger.split(";")) { - hasEndInformation = StringUtils.stripControlCodes(chatMessage).contains(s); - if (hasEndInformation) break; - } - if (hasEndInformation) { - Utility.sendChatMessage(message.getValue()); - if(autoPlay.getValue()) { - Utility.sendClientNotify("AutoPlay is not supported at the moment in KKCraft"); + for (String s : kkcraftTrigger) { + if (StringUtils.stripControlCodes(chatMessage).contains(s)) { + Utility.sendChatMessage(message.getValue()); + if(autoPlay.getValue()) { + Utility.sendClientNotify("AutoPlay is not supported at the moment in KKCraft"); + } } } break; From adc0a428c8e54efb5c4290d8c1795efa6f49d8b4 Mon Sep 17 00:00:00 2001 From: vlouboos Date: Fri, 25 Jul 2025 21:52:45 +0800 Subject: [PATCH 187/193] Add delay for auto gg --- .../features/impl/utility/AutoGG.java | 60 +++++++++++-------- 1 file changed, 36 insertions(+), 24 deletions(-) diff --git a/shared/java/top/fpsmaster/features/impl/utility/AutoGG.java b/shared/java/top/fpsmaster/features/impl/utility/AutoGG.java index 315b1110..9a4503f4 100644 --- a/shared/java/top/fpsmaster/features/impl/utility/AutoGG.java +++ b/shared/java/top/fpsmaster/features/impl/utility/AutoGG.java @@ -14,14 +14,16 @@ import top.fpsmaster.features.settings.impl.TextSetting; import top.fpsmaster.interfaces.ProviderManager; import top.fpsmaster.utils.Utility; +import top.fpsmaster.utils.math.MathTimer; public class AutoGG extends Module { - public BooleanSetting autoPlay = new BooleanSetting("AutoPlay", false); - public NumberSetting delay = new NumberSetting("DelayToPlay", 5, 0, 10, 1, () -> autoPlay.getValue()); - public TextSetting message = new TextSetting("Message", "gg"); - public ModeSetting servers = new ModeSetting("Servers", 0, "hypxiel", "kkcraft"); - public String[] hypixelTrigger = new String[]{"Reward Summary", "1st Killer", "Damage Dealt", "奖励总览", "击杀数第一名", "造成伤害"}; - public String[] kkcraftTrigger = new String[]{"获胜者", "第一名杀手", "击杀第一名"}; + private final BooleanSetting autoPlay = new BooleanSetting("AutoPlay", false); + private final NumberSetting delay = new NumberSetting("DelayToPlay", 5, 0, 10, 1, () -> autoPlay.getValue()); + private final TextSetting message = new TextSetting("Message", "gg"); + private final ModeSetting servers = new ModeSetting("Servers", 0, "hypxiel", "kkcraft"); + private final String[] hypixelTrigger = new String[]{"Reward Summary", "1st Killer", "Damage Dealt", "奖励总览", "击杀数第一名", "造成伤害"}; + private final String[] kkcraftTrigger = new String[]{"获胜者", "第一名杀手", "击杀第一名"}; + private final MathTimer timer = new MathTimer(); public AutoGG() { super("AutoGG", Category.Utility); @@ -35,35 +37,45 @@ public void onPacket(EventPacket event) { String chatMessage = componentValue.getUnformattedText(); switch (servers.getValue()) { case 0: - for (String s : hypixelTrigger) { - if (StringUtils.stripControlCodes(chatMessage).contains(s)) { - Utility.sendChatMessage("/ac " + message.getValue()); - break; + if (timer.delay(10000)) { + for (String s : hypixelTrigger) { + if (StringUtils.stripControlCodes(chatMessage).contains(s)) { + Utility.sendChatMessage("/ac " + message.getValue()); + timer.reset(); + break; + } } } if (autoPlay.getValue()) { for (IChatComponent chatComponent : componentValue.getSiblings()) { ClickEvent clickEvent = chatComponent.getChatStyle().getChatClickEvent(); if (clickEvent != null && clickEvent.getAction().equals(ClickEvent.Action.RUN_COMMAND) && clickEvent.getValue().trim().toLowerCase().startsWith("/play ")) { - Utility.sendClientNotify("Sending you to the next game in " + delay.getValue() + " seconds"); - FPSMaster.async.runnable(() -> { - try { - Thread.sleep(delay.getValue().longValue() * 1000); - Utility.sendChatMessage(clickEvent.getValue()); - } catch (InterruptedException e) { - throw new RuntimeException(e); - } - }); + if (delay.getValue().doubleValue() > 0) { + Utility.sendClientNotify("Sending you to the next game in " + delay.getValue() + " seconds"); + FPSMaster.async.runnable(() -> { + try { + Thread.sleep(delay.getValue().longValue() * 1000); + Utility.sendChatMessage(clickEvent.getValue()); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + }); + } else { + Utility.sendChatMessage(clickEvent.getValue()); + } } } } break; case 1: - for (String s : kkcraftTrigger) { - if (StringUtils.stripControlCodes(chatMessage).contains(s)) { - Utility.sendChatMessage(message.getValue()); - if(autoPlay.getValue()) { - Utility.sendClientNotify("AutoPlay is not supported at the moment in KKCraft"); + if (timer.delay(10000)) { + for (String s : kkcraftTrigger) { + if (StringUtils.stripControlCodes(chatMessage).contains(s)) { + Utility.sendChatMessage(message.getValue()); + timer.reset(); + if (autoPlay.getValue()) { + Utility.sendClientNotify("AutoPlay is not supported in KKCraft yet"); + } } } } From 79085cdfb213af8cf56e9b81bc7428a3a5b3dc48 Mon Sep 17 00:00:00 2001 From: vlouboos Date: Fri, 25 Jul 2025 21:55:06 +0800 Subject: [PATCH 188/193] Optimize --- shared/java/top/fpsmaster/features/impl/utility/AutoGG.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/shared/java/top/fpsmaster/features/impl/utility/AutoGG.java b/shared/java/top/fpsmaster/features/impl/utility/AutoGG.java index 9a4503f4..60ee6d24 100644 --- a/shared/java/top/fpsmaster/features/impl/utility/AutoGG.java +++ b/shared/java/top/fpsmaster/features/impl/utility/AutoGG.java @@ -18,7 +18,7 @@ public class AutoGG extends Module { private final BooleanSetting autoPlay = new BooleanSetting("AutoPlay", false); - private final NumberSetting delay = new NumberSetting("DelayToPlay", 5, 0, 10, 1, () -> autoPlay.getValue()); + private final NumberSetting delay = new NumberSetting("DelayToPlay", 5, 0, 10, 1, autoPlay::getValue); private final TextSetting message = new TextSetting("Message", "gg"); private final ModeSetting servers = new ModeSetting("Servers", 0, "hypxiel", "kkcraft"); private final String[] hypixelTrigger = new String[]{"Reward Summary", "1st Killer", "Damage Dealt", "奖励总览", "击杀数第一名", "造成伤害"}; @@ -51,7 +51,7 @@ public void onPacket(EventPacket event) { ClickEvent clickEvent = chatComponent.getChatStyle().getChatClickEvent(); if (clickEvent != null && clickEvent.getAction().equals(ClickEvent.Action.RUN_COMMAND) && clickEvent.getValue().trim().toLowerCase().startsWith("/play ")) { if (delay.getValue().doubleValue() > 0) { - Utility.sendClientNotify("Sending you to the next game in " + delay.getValue() + " seconds"); + Utility.sendClientNotify("Sending you to the next game in " + delay.getValue().intValue() + " seconds"); FPSMaster.async.runnable(() -> { try { Thread.sleep(delay.getValue().longValue() * 1000); From 157648f7f9e25fe9b78ee0948b3ca445c9fa3cad Mon Sep 17 00:00:00 2001 From: SuperSkidder Date: Sat, 26 Jul 2025 21:30:35 +0800 Subject: [PATCH 189/193] fix: correct wrong name fix bugs --- .../features/impl/utility/AutoGG.java | 2 +- .../mixin/MixinAbstractClientPlayer.java | 20 ++++++++++--------- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/shared/java/top/fpsmaster/features/impl/utility/AutoGG.java b/shared/java/top/fpsmaster/features/impl/utility/AutoGG.java index 6103f0e4..a8b2f643 100644 --- a/shared/java/top/fpsmaster/features/impl/utility/AutoGG.java +++ b/shared/java/top/fpsmaster/features/impl/utility/AutoGG.java @@ -20,7 +20,7 @@ public class AutoGG extends Module { public BooleanSetting autoPlay = new BooleanSetting("AutoPlay", false); public NumberSetting delay = new NumberSetting("DelayToPlay", 5, 0, 10, 1, () -> autoPlay.getValue()); public TextSetting message = new TextSetting("Message", "gg"); - public ModeSetting servers = new ModeSetting("Servers", 0, "hypxiel", "kkcraft"); + public ModeSetting servers = new ModeSetting("Servers", 0, "hypixel", "kkcraft"); public String hypixelTrigger = "Reward Summary;1st Killer;Damage Dealt;奖励总览;击杀数第一名;造成伤害"; public String kkcraftTrigger = "获胜者;第一名杀手;击杀第一名"; diff --git a/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinAbstractClientPlayer.java b/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinAbstractClientPlayer.java index d530de9f..be8a7ec8 100644 --- a/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinAbstractClientPlayer.java +++ b/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinAbstractClientPlayer.java @@ -38,16 +38,18 @@ public void customFov(CallbackInfoReturnable cir) { f = 1.0F; } - if (this.isUsingItem() && this.getItemInUse().getItem() == Items.bow) { - int i = this.getItemInUseDuration(); - float f1 = (float) i / 20.0F; - if (f1 > 1.0F) { - f1 = 1.0F; - } else { - f1 *= f1; - } + if (!CustomFOV.noBowFov.getValue()) { + if (this.isUsingItem() && this.getItemInUse().getItem() == Items.bow) { + int i = this.getItemInUseDuration(); + float f1 = (float) i / 20.0F; + if (f1 > 1.0F) { + f1 = 1.0F; + } else { + f1 *= f1; + } - f *= 1.0F - f1 * 0.15F; + f *= 1.0F - f1 * 0.15F; + } } cir.setReturnValue(f); } From f1fd888708475d52d43460f228f0a2f2d2d255b5 Mon Sep 17 00:00:00 2001 From: SuperSkidder Date: Tue, 29 Jul 2025 02:14:28 +0800 Subject: [PATCH 190/193] fix: hitboxes render bug --- .../fpsmaster/wrapper/mods/WrapperHitboxes.java | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/v1.8.9/src/main/java/top/fpsmaster/wrapper/mods/WrapperHitboxes.java b/v1.8.9/src/main/java/top/fpsmaster/wrapper/mods/WrapperHitboxes.java index 1f062651..64ca4d7b 100644 --- a/v1.8.9/src/main/java/top/fpsmaster/wrapper/mods/WrapperHitboxes.java +++ b/v1.8.9/src/main/java/top/fpsmaster/wrapper/mods/WrapperHitboxes.java @@ -24,13 +24,14 @@ public class WrapperHitboxes { public static void render(EventRender3D event, ColorSetting color) { - GL11.glPushAttrib(GL11.GL_ALPHA | GL11.GL_BLEND | GL11.GL_TEXTURE_2D | GL11.GL_LIGHTING | GL11.GL_DEPTH_TEST | GL11.GL_CULL_FACE); +// GL11.glPushAttrib(GL11.GL_ALPHA | GL11.GL_BLEND | GL11.GL_TEXTURE_2D | GL11.GL_LIGHTING | GL11.GL_DEPTH_TEST | GL11.GL_CULL_FACE); + GlStateManager.pushAttrib(); GlStateManager.depthMask(false); GlStateManager.disableTexture2D(); - GlStateManager.disableLighting(); +// GlStateManager.disableLighting(); GlStateManager.disableCull(); - GlStateManager.disableBlend(); - + GlStateManager.enableBlend(); + GlStateManager.enableAlpha(); for (Entity entity : Minecraft.getMinecraft().theWorld.loadedEntityList.stream().filter(e -> e != Minecraft.getMinecraft().thePlayer && !e.isInvisible()).collect(Collectors.toList())) { AxisAlignedBB axisalignedbb = entity.getEntityBoundingBox(); double d0 = entity.lastTickPosX + (entity.posX - entity.lastTickPosX) * ProviderManager.timerProvider.getRenderPartialTicks(); @@ -43,10 +44,11 @@ public static void render(EventRender3D event, ColorSetting color) { RenderGlobal.drawOutlinedBoundingBox(axisalignedbb1, color.getColor().getRed(), color.getColor().getGreen(), color.getColor().getBlue(), color.getColor().getAlpha()); } GlStateManager.enableTexture2D(); - GlStateManager.enableLighting(); +// GlStateManager.enableLighting(); GlStateManager.enableCull(); GlStateManager.disableBlend(); GlStateManager.depthMask(true); - GL11.glPopAttrib(); + GlStateManager.popAttrib(); + } } From 7847c98523240eb0349abb1886f54038ea35a3b0 Mon Sep 17 00:00:00 2001 From: SuperSkidder Date: Tue, 29 Jul 2025 12:10:05 +0800 Subject: [PATCH 191/193] feat: music player volume adjustment fix: hitboxes render bug --- .../top/fpsmaster/modules/music/netease/Music.java | 2 +- .../top/fpsmaster/ui/click/music/NewMusicPanel.java | 12 ++++++++++++ .../top/fpsmaster/wrapper/mods/WrapperHitboxes.java | 3 +-- 3 files changed, 14 insertions(+), 3 deletions(-) diff --git a/shared/java/top/fpsmaster/modules/music/netease/Music.java b/shared/java/top/fpsmaster/modules/music/netease/Music.java index 71e5664c..1661f571 100644 --- a/shared/java/top/fpsmaster/modules/music/netease/Music.java +++ b/shared/java/top/fpsmaster/modules/music/netease/Music.java @@ -33,7 +33,6 @@ public Music(long id, String name, String artists, String picUrl) { public void loadMusic() { try { if (ProviderManager.worldClientProvider.getWorld() == null) return; - MusicWrapper.loadLyrics(this); File artist = new File(FileUtils.artists, FileUtils.fixName(name + "(" + id + ").png")); if (!artist.exists()) { HttpRequest.downloadFile(imgURL + "?param=90y90", artist.getAbsolutePath()); @@ -49,6 +48,7 @@ public void loadMusic() { @Override public void play() { MusicPlayer.stop(); + MusicWrapper.loadLyrics(this); File flac = new File(FileUtils.music, FileUtils.fixName(name + "(" + id + ").flac")); File mp3 = new File(FileUtils.music, FileUtils.fixName(name + "(" + id + ").mp3")); if (flac.exists() || mp3.exists()) { diff --git a/shared/java/top/fpsmaster/ui/click/music/NewMusicPanel.java b/shared/java/top/fpsmaster/ui/click/music/NewMusicPanel.java index 0fb05ce3..78aa8c62 100644 --- a/shared/java/top/fpsmaster/ui/click/music/NewMusicPanel.java +++ b/shared/java/top/fpsmaster/ui/click/music/NewMusicPanel.java @@ -5,6 +5,7 @@ import net.minecraft.client.renderer.ThreadDownloadImageData; import net.minecraft.client.renderer.texture.TextureManager; import net.minecraft.util.ResourceLocation; +import org.lwjgl.input.Mouse; import org.lwjgl.opengl.GL11; import top.fpsmaster.FPSMaster; import top.fpsmaster.exception.ExceptionHandler; @@ -288,6 +289,17 @@ public static void draw(float x, int y, float width, float height, int mouseX, i Render2DUtils.drawImage(MusicPlayer.isPlaying ? new ResourceLocation("client/gui/settings/music/pause.png") : new ResourceLocation("client/gui/settings/music/play.png"), x + width / 2 - 15, y + height - 26, 35 / 2f, 35 / 2f, new Color(255,255,255,opacity)); Render2DUtils.drawImage(new ResourceLocation("client/gui/settings/music/next.png"), x + width / 2 + 5, y + height - 25, 16f, 16f, new Color(234, 234, 234,opacity)); + // 音量键 + Render2DUtils.drawImage(new ResourceLocation("client/textures/ui/volume.png"), x + width - 62, y + height - 16, 7f, 7f, new Color(234, 234, 234,opacity)); + Render2DUtils.drawRoundedRectImage(x + width - 50, y + height - 13, 30f, 2f,1, new Color(108, 108, 108)); + float volume = MusicPlayer.getVolume(); + Render2DUtils.drawRoundedRectImage(x + width - 50, y + height - 13, 30f * volume, 2f,1, new Color(255,255,255)); + if (Render2DUtils.isHovered(x + width - 50, y + height - 13, 30f, 2f, mouseX, mouseY) && Mouse.isButtonDown(0)){ + float newVolume = (mouseX - (x + width - 50)) / 30f; + MusicPlayer.setVolume(newVolume); + } + + if (JLayerHelper.clip != null) { if (Render2DUtils.isHovered(x + width / 2 - 15, y + height - 26, 35 / 2f, 35 / 2f, mouseX, mouseY) && consumeClick(0)) { if (MusicPlayer.isPlaying) diff --git a/v1.8.9/src/main/java/top/fpsmaster/wrapper/mods/WrapperHitboxes.java b/v1.8.9/src/main/java/top/fpsmaster/wrapper/mods/WrapperHitboxes.java index 64ca4d7b..774c8714 100644 --- a/v1.8.9/src/main/java/top/fpsmaster/wrapper/mods/WrapperHitboxes.java +++ b/v1.8.9/src/main/java/top/fpsmaster/wrapper/mods/WrapperHitboxes.java @@ -30,8 +30,7 @@ public static void render(EventRender3D event, ColorSetting color) { GlStateManager.disableTexture2D(); // GlStateManager.disableLighting(); GlStateManager.disableCull(); - GlStateManager.enableBlend(); - GlStateManager.enableAlpha(); + GlStateManager.disableAlpha(); for (Entity entity : Minecraft.getMinecraft().theWorld.loadedEntityList.stream().filter(e -> e != Minecraft.getMinecraft().thePlayer && !e.isInvisible()).collect(Collectors.toList())) { AxisAlignedBB axisalignedbb = entity.getEntityBoundingBox(); double d0 = entity.lastTickPosX + (entity.posX - entity.lastTickPosX) * ProviderManager.timerProvider.getRenderPartialTicks(); From 9e4299c88b23a7579669eccdb8d1e5ec14407897 Mon Sep 17 00:00:00 2001 From: SuperSkidder Date: Tue, 29 Jul 2025 12:22:52 +0800 Subject: [PATCH 192/193] optimize: render --- .../top/fpsmaster/ui/click/MainPanel.java | 8 +- .../top/fpsmaster/utils/render/Bounding.java | 12 ++ .../fpsmaster/utils/render/Render2DUtils.java | 162 ++++++++++-------- .../utils/render/shader/KawaseBloom.java | 2 +- 4 files changed, 104 insertions(+), 80 deletions(-) create mode 100644 shared/java/top/fpsmaster/utils/render/Bounding.java diff --git a/shared/java/top/fpsmaster/ui/click/MainPanel.java b/shared/java/top/fpsmaster/ui/click/MainPanel.java index 5cce94b4..b34bd9b9 100644 --- a/shared/java/top/fpsmaster/ui/click/MainPanel.java +++ b/shared/java/top/fpsmaster/ui/click/MainPanel.java @@ -145,7 +145,7 @@ public void render(int mouseX, int mouseY, float partialTicks) { - if (Render2DUtils.isHoveredWithoutScale(x, (int) (y + height / 2 - 70), categoryAnimation, 140, mouseX, mouseY)) { + if (Render2DUtils.isHovered(x, (int) (y + height / 2 - 70), categoryAnimation, 140, mouseX, mouseY)) { categoryAnimation = (float) AnimationUtils.base(categoryAnimation, 100f, 0.15f); } else { categoryAnimation = (float) AnimationUtils.base(categoryAnimation, 30f, 0.15f); @@ -196,7 +196,7 @@ public void render(int mouseX, int mouseY, float partialTicks) { ); for (CategoryComponent m : categories) { - if (Render2DUtils.isHoveredWithoutScale(x, my - 6, leftWidth - 10, 20f, mouseX, mouseY)) { + if (Render2DUtils.isHovered(x, my - 6, leftWidth - 10, 20f, mouseX, mouseY)) { m.categorySelectionColor.base(new Color(70, 70, 70)); } else { m.categorySelectionColor.base(Render2DUtils.reAlpha(new Color(70, 70, 70), 0)); @@ -299,7 +299,7 @@ public void onClick(int mouseX, int mouseY, int mouseButton) { mc.displayGuiScreen(new CosmeticScreen()); } } - if (!Render2DUtils.isHoveredWithoutScale(x, y, width, height, mouseX, mouseY)) return; + if (!Render2DUtils.isHovered(x, y, width, height, mouseX, mouseY)) return; // if (mouseButton == 0 && Render2DUtils.isHoveredWithoutScale( // x + leftWidth, y, width - leftWidth, 20f, mouseX, mouseY @@ -321,7 +321,7 @@ public void onClick(int mouseX, int mouseY, int mouseButton) { return; float my = y + 60f; for (Category c : Category.values()) { - if (Render2DUtils.isHoveredWithoutScale(x, my - 8, leftWidth, 24f, mouseX, mouseY)) { + if (Render2DUtils.isHovered(x, my - 8, leftWidth, 24f, mouseX, mouseY)) { wheelTemp = 0f; modsWheel = 0f; if (curType != c) { diff --git a/shared/java/top/fpsmaster/utils/render/Bounding.java b/shared/java/top/fpsmaster/utils/render/Bounding.java new file mode 100644 index 00000000..dc5bd430 --- /dev/null +++ b/shared/java/top/fpsmaster/utils/render/Bounding.java @@ -0,0 +1,12 @@ +package top.fpsmaster.utils.render; + +public class Bounding { + public int x, y, width, height; + + public Bounding(int x, int y, int width, int height) { + this.x = x; + this.y = y; + this.width = width; + this.height = height; + } +} diff --git a/shared/java/top/fpsmaster/utils/render/Render2DUtils.java b/shared/java/top/fpsmaster/utils/render/Render2DUtils.java index 18493167..2745d4c7 100644 --- a/shared/java/top/fpsmaster/utils/render/Render2DUtils.java +++ b/shared/java/top/fpsmaster/utils/render/Render2DUtils.java @@ -37,6 +37,7 @@ import static org.lwjgl.opengl.GL11.*; public class Render2DUtils extends Utility { + // AWT public static void drawOptimizedRoundedRect(float x, float y, float width, float height, Color color) { drawOptimizedRoundedRect(x, y, width, height, 3, color.getRGB()); } @@ -76,6 +77,37 @@ public static void drawOptimizedRoundedRect(float x, float y, float width, float drawImage(resourceLocations[3], x + width - radius, y + height - radius, radius, radius, color, rawImage); } + static ArrayList downloadingImages = new ArrayList<>(); + static ArrayList downloadedImages = new ArrayList<>(); + + + public static void drawWebImage(String url, float x, float y, int width, int height) { + if (downloadingImages.contains(url)){ + drawRoundedRectImage(x, y, width, height, 5, new Color(194, 194, 194, 255)); + } else if (downloadedImages.contains(url)) { + drawImage(new ResourceLocation(url), x, y, width, height, -1); + }else{ + downloadingImages.add(url); + FPSMaster.async.runnable(()->{ + ResourceLocation textureLocation = new ResourceLocation(url); + ThreadDownloadImageData downloadImageData = new ThreadDownloadImageData(null, null, textureLocation, null); + try { + downloadImageData.setBufferedImage(HttpRequest.downloadImage(url)); + mc.getTextureManager().loadTexture(textureLocation, downloadImageData); + } catch (IOException ignored) { + } + downloadedImages.add(url); + downloadingImages.remove(url); + }); + } + } + + // vanilla + public static void drawRect(float x, float y, float width, float height, Color color) { + drawRect(x, y, width, height, color.getRGB()); + } + + public static void drawImage(ResourceLocation res, float x, float y, float width, float height, Color color) { drawImage(res, x, y, width, height, color.getRGB(), false); } @@ -110,20 +142,18 @@ public static void drawRoundedRectImage(float x, float y, float width, float hei } } - public static void drawRect(float x, float y, float width, float height, Color color) { - drawRect(x, y, width, height, color.getRGB()); - } - - public static Color reAlpha(Color color, int alpha) { - return new Color(color.getRed(), color.getGreen(), color.getBlue(), limit(alpha)); + public static void drawHue(float x, float y, int width, float height) { + float hue = 0; + float increment = 1.0F / height; + for (int i = 0; i < height; i++) { + drawRect(x, y + i, width, 1, Color.getHSBColor(hue, 1.0F, 1.0F).getRGB()); + hue += increment; + } } - public static int limit(double i) { - if (i > 255) - return 255; - if (i < 0) - return 0; - return (int) i; + public static void drawPlayerHead(EntityPlayer target, float x, float y, int w, int h) { + mc.getTextureManager().bindTexture(((AbstractClientPlayer) target).getLocationSkin()); + Gui.drawScaledCustomSizeModalRect((int) x, (int) y, 8, 8, 8, 8, w, h, 64, 64); } public static void drawRect(float x, float y, float width, float height, int color) { @@ -144,18 +174,6 @@ public static void drawRect(float x, float y, float width, float height, int col GlStateManager.disableBlend(); } - public static Color intToColor(Integer c) { - return new Color(c >> 16 & 255, c >> 8 & 255, c & 255, c >> 24 & 255); - } - - private static void glColor(int color) { - int red = color >> 16 & 255; - int green = color >> 8 & 255; - int blue = color & 255; - int alpha = color >> 24 & 255; - GL11.glColor4f(red / 255.0F, green / 255.0F, blue / 255.0F, alpha / 255.0F); - } - public static void drawModalRectWithCustomSizedTexture(float x, float y, float u, float v, float width, float height, float textureWidth, float textureHeight) { float f = 1.0F / textureWidth; float f1 = 1.0F / textureHeight; @@ -169,6 +187,34 @@ public static void drawModalRectWithCustomSizedTexture(float x, float y, float u tessellator.draw(); } + + // other + + public static Color reAlpha(Color color, int alpha) { + return new Color(color.getRed(), color.getGreen(), color.getBlue(), limit(alpha)); + } + + public static int limit(double i) { + if (i > 255) + return 255; + if (i < 0) + return 0; + return (int) i; + } + + + public static Color intToColor(Integer c) { + return new Color(c >> 16 & 255, c >> 8 & 255, c & 255, c >> 24 & 255); + } + + private static void glColor(int color) { + int red = color >> 16 & 255; + int green = color >> 8 & 255; + int blue = color & 255; + int alpha = color >> 24 & 255; + GL11.glColor4f(red / 255.0F, green / 255.0F, blue / 255.0F, alpha / 255.0F); + } + public static void doGlScissor(float x, float y, float width, float height, int scaleFactor) { if (mc.currentScreen != null) { width *= 1f / scaleFactor * 2; @@ -180,27 +226,14 @@ public static void doGlScissor(float x, float y, float width, float height, int } - public static void drawHue(float x, float y, int width, float height) { - float hue = 0; - float increment = 1.0F / height; - for (int i = 0; i < height; i++) { - drawRect(x, y + i, width, 1, Color.getHSBColor(hue, 1.0F, 1.0F).getRGB()); - hue += increment; - } - } - public static void drawPlayerHead(EntityPlayer target, float x, float y, int w, int h) { - mc.getTextureManager().bindTexture(((AbstractClientPlayer) target).getLocationSkin()); - Gui.drawScaledCustomSizeModalRect((int) x, (int) y, 8, 8, 8, 8, w, h, 64, 64); - } public static boolean isHovered(float x, float y, float width, float height, int mouseX, int mouseY) { return mouseX >= x && mouseX <= x + width && mouseY >= y && mouseY <= y + height; } - public static boolean isHoveredWithoutScale(float x, float y, float width, float height, int mouseX, int mouseY) { - ScaledResolution sr = new ScaledResolution(mc); - return mouseX >= x && mouseX <= x + width && mouseY >= y && mouseY <= y + height; + public static boolean isHovered(Bounding bounding, int mouseX, int mouseY) { + return isHovered(bounding.x, bounding.y, bounding.width, bounding.height, mouseX, mouseY); } public static int fixScale() { @@ -220,17 +253,6 @@ public static int getFixedScale() { return scaleFactor; } - public static void scaleStart(float x, float y, float scale) { - glPushMatrix(); - glTranslatef(x, y, 0); - glScalef(scale, scale, 1); - glTranslatef(-x, -y, 0); - } - - public static void scaleEnd() { - glPopMatrix(); - } - public static float[] getFixedBounds() { ScaledResolution sr = new ScaledResolution(mc); int scaleFactor; @@ -244,6 +266,19 @@ public static float[] getFixedBounds() { return new float[]{guiWidth, guiHeight}; } + public static void scaleStart(float x, float y, float scale) { + glPushMatrix(); + glTranslatef(x, y, 0); + glScalef(scale, scale, 1); + glTranslatef(-x, -y, 0); + } + + public static void scaleEnd() { + glPopMatrix(); + } + + + public static void beginBlend() { GlStateManager.enableBlend(); GlStateManager.blendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); @@ -265,6 +300,8 @@ public static void drawBlurArea(float x, float y, float width, float height, int StencilUtil.uninitStencilBuffer(); } + + // background(shader) public static float animation = 0f; static GLSLSandboxShader shader; static long initTime = System.currentTimeMillis(); @@ -315,29 +352,4 @@ public static void drawBackground(int guiWidth, int guiHeight, int mouseX, int m } } } - - static ArrayList downloadingImages = new ArrayList<>(); - static ArrayList downloadedImages = new ArrayList<>(); - - - public static void drawWebImage(String url, float x, float y, int width, int height) { - if (downloadingImages.contains(url)){ - drawRoundedRectImage(x, y, width, height, 5, new Color(194, 194, 194, 255)); - } else if (downloadedImages.contains(url)) { - drawImage(new ResourceLocation(url), x, y, width, height, -1); - }else{ - downloadingImages.add(url); - FPSMaster.async.runnable(()->{ - ResourceLocation textureLocation = new ResourceLocation(url); - ThreadDownloadImageData downloadImageData = new ThreadDownloadImageData(null, null, textureLocation, null); - try { - downloadImageData.setBufferedImage(HttpRequest.downloadImage(url)); - mc.getTextureManager().loadTexture(textureLocation, downloadImageData); - } catch (IOException ignored) { - } - downloadedImages.add(url); - downloadingImages.remove(url); - }); - } - } } diff --git a/shared/java/top/fpsmaster/utils/render/shader/KawaseBloom.java b/shared/java/top/fpsmaster/utils/render/shader/KawaseBloom.java index d6e9310a..4d4b16ab 100644 --- a/shared/java/top/fpsmaster/utils/render/shader/KawaseBloom.java +++ b/shared/java/top/fpsmaster/utils/render/shader/KawaseBloom.java @@ -98,7 +98,7 @@ public static void renderBlur(int framebufferTexture, int iterations, int offset ShaderUtil.drawQuads(); GlStateManager.bindTexture(0); setAlphaLimit(0); - Render2DUtils.beginBlend(); + Render2DUtils.endBlend(); } private static void renderFBO(Framebuffer framebuffer, int framebufferTexture, ShaderUtil shader, float offset) { From c1297b4d6ccbaf6b4c427a04463d3b0f157db639 Mon Sep 17 00:00:00 2001 From: SuperSkidder Date: Tue, 29 Jul 2025 14:00:14 +0800 Subject: [PATCH 193/193] optimize code --- .../modules/client/{ => thread}/ClientThreadPool.java | 4 +++- shared/java/top/fpsmaster/ui/mc/GuiMultiplayer.java | 5 ++--- 2 files changed, 5 insertions(+), 4 deletions(-) rename shared/java/top/fpsmaster/modules/client/{ => thread}/ClientThreadPool.java (68%) diff --git a/shared/java/top/fpsmaster/modules/client/ClientThreadPool.java b/shared/java/top/fpsmaster/modules/client/thread/ClientThreadPool.java similarity index 68% rename from shared/java/top/fpsmaster/modules/client/ClientThreadPool.java rename to shared/java/top/fpsmaster/modules/client/thread/ClientThreadPool.java index f713b939..53b5667e 100644 --- a/shared/java/top/fpsmaster/modules/client/ClientThreadPool.java +++ b/shared/java/top/fpsmaster/modules/client/thread/ClientThreadPool.java @@ -1,7 +1,9 @@ -package top.fpsmaster.modules.client; +package top.fpsmaster.modules.client.thread; import java.util.concurrent.*; +// 此工具只应用于只执行一次,或者执行时间可确定的任务,对于重复性或者不确定任务,应该各自处理其逻辑,包括重复线程任务以及超时时间等,而非直接再此处执行。 +// 此工具不保证新的任务可以立即执行,可能会因为其他线程延迟执行。 public class ClientThreadPool { private final ExecutorService executorService; diff --git a/shared/java/top/fpsmaster/ui/mc/GuiMultiplayer.java b/shared/java/top/fpsmaster/ui/mc/GuiMultiplayer.java index 05b4ab8f..9865b740 100644 --- a/shared/java/top/fpsmaster/ui/mc/GuiMultiplayer.java +++ b/shared/java/top/fpsmaster/ui/mc/GuiMultiplayer.java @@ -19,7 +19,7 @@ import org.lwjgl.opengl.GL11; import top.fpsmaster.FPSMaster; import top.fpsmaster.font.impl.UFontRenderer; -import top.fpsmaster.modules.client.ClientThreadPool; +import top.fpsmaster.modules.client.thread.ClientThreadPool; import top.fpsmaster.ui.click.component.ScrollContainer; import top.fpsmaster.ui.common.GuiButton; import top.fpsmaster.ui.screens.mainmenu.MainMenu; @@ -98,8 +98,7 @@ public void initGui() { serverListDisplay.clear(); serverListDisplay.addAll(serverListInternet); if (serverListRecommended.isEmpty()) { - ClientThreadPool clientThreadPool = new ClientThreadPool(100); - clientThreadPool.runnable(() -> { + FPSMaster.async.runnable(() -> { String s; try { s = HttpRequest.get("https://service.fpsmaster.top/api/client/servers").getBody();