diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml new file mode 100644 index 00000000..705dc0fe --- /dev/null +++ b/.github/workflows/nightly.yml @@ -0,0 +1,124 @@ +name: Java CI with Gradle - Nightly + +on: + schedule: + - cron: '0 17 * * *' + 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 89% rename from .github/workflows/gradle.yml rename to .github/workflows/publish.yml index 2d30f4c4..08f496ad 100644 --- a/.github/workflows/gradle.yml +++ b/.github/workflows/publish.yml @@ -1,10 +1,9 @@ name: Java CI with Gradle on: - push: - branches: [ "master", "v4" ] - pull_request: - branches: [ "master", "v4" ] +# push: +# branches: [ "master", "v4" ] + workflow_dispatch: jobs: build: @@ -42,8 +41,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 @@ -92,4 +93,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" diff --git a/README.md b/README.md index 5e71ef3d..83f2c4fc 100644 --- a/README.md +++ b/README.md @@ -10,61 +10,26 @@ 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: -- [x] 完全迁移到Java -- [ ] 优化代码结构 -- [x] 添加固定界面尺寸选项 -- [x] 组件尺寸自定义 -- [ ] 重构MusicPlayer界面 -- [ ] 支持播放无损/VIP音乐 -- [ ] 修复音乐可视化 -- [ ] 添加脚本插件系统 -- [ ] 添加界面自动对齐 -- [ ] 添加翻译功能 -- [ ] 迁移优化代码 -- [ ] 自动更新 -- [ ] 多语言界面 -- [ ] 重写IRC模块 -- [ ] 优化配置文件模块 -- [ ] FPSMaster Intelligence -- [ ] HitMarker -- [ ] Waypoint +### 开发 + - 查看我们的[代码规范](docs/code_standards.md)了解如何编写符合我们要求的代码。 + - 查看我们的[环境配置](docs/development_environment.md)了解如何配置开发环境。 + - 查看我们的[开发指南](docs/development_tutorial.md)了解如何使用我们的模块系统、配置系统等,并完成你的需求。 + - 查看我们的[任务列表](docs/tasks.md)了解当前的开发计划和进度。 ## 开源许可证 本项目采用 GPL-3.0 许可证。详情请参阅 [LICENSE](LICENSE) 文件。 -特别声明:由于疏忽,自`c6a5edaac43fdcca8ce487eee430e9fb059a2db1`前所有版本的代码均错误地使用了MIT协议开源,现已更正为GPL-3.0。 - ## 开发环境配置 -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/e686f6313e4406de4286bf27e0db4a2bf5a31b7f.svg "Repobeats analytics image") +![Alt](https://repobeats.axiom.co/api/embed/7d755c063aa9a34d74edb7045541e8bfe6e09b89.svg "Repobeats analytics image") ## 引用的开源项目: [eventbus](https://github.com/therealbush/eventbus) 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_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 new file mode 100644 index 00000000..62fedd7a --- /dev/null +++ b/docs/development_tutorial.md @@ -0,0 +1,357 @@ +# FPSMaster 开发教程 + +本教程将介绍如何为 FPSMaster 客户端添加新功能,包括基本功能、带界面组件的功能,以及如何使用 mixin 系统。此外,还将简要介绍客户端的命令系统和配置系统。 + +## 前提条件 + +在开始开发前,你需要配置好本项目的开发环境,具体可以参考:[配置开发环境](development_environment.md) + +## 目录 + +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 diff --git a/docs/tasks.md b/docs/tasks.md new file mode 100644 index 00000000..dc960ff6 --- /dev/null +++ b/docs/tasks.md @@ -0,0 +1,144 @@ +# FPSMaster 任务列表 + +本文档包含 FPSMaster 项目的任务和待办事项。 + +## 当前开发任务 + +以下是当前开发周期的紧急任务: + +- [x] 完全迁移到Java +- [x] 添加固定界面尺寸选项 +- [x] 组件尺寸自定义 +- [x] 修复音乐可视化 +- [x] 添加脚本插件系统 +- [x] 迁移优化代码 +- [x] HitMarker +- [ ] 优化代码结构 +- [ ] 重构MusicPlayer界面 +- [ ] 支持播放无损/VIP音乐 +- [ ] 添加界面自动对齐 +- [ ] 添加翻译功能 +- [ ] Waypoint +- [ ] 攻击音效 +- [ ] 更加自定义话的组件(大小调整、按键显示) +- [ ] 修改notification,添加更多样式和自定义 +- [ ] RawInput兼容和优化 +- [ ] FPS Hurt Cam +- [ ] World Color + + +## 长期改进任务 + +这是 FPSMaster 项目的综合改进任务列表。每个任务都按类别分类,并包含一个可在完成时标记的复选框。 + +## 架构改进 + +### 模块系统 +1. [ ] 创建使用注解而非硬编码列表的模块注册系统 +2. [ ] 重构模块类别以使用更灵活的分类法 +3. [ ] 实现更加高级的Values系统 + +### 事件系统 +1. [ ] 优化事件分发以提高性能 +2. [ ] 实现事件优先级 +3. [ ] 创建全面的事件文档 +4. [ ] 添加事件调试/监控工具 + +### 配置系统 +1. [x] 重构配置保存格式 +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. [x] 创建开发者设置指南 +2. [x] 添加贡献指南 +3. [ ] 创建API文档 + +## 安全改进 + +### 认证 +1. [ ] 实现安全令牌存储 +2. [ ] 改进会话管理 + +### 数据保护 +1. [ ] 加密敏感配置数据 + +## 国际化和可访问性 + +### 国际化 +1. [ ] 完成翻译系统 +2. [ ] 创建翻译贡献工具 +3. [ ] 添加语言自动检测 + +## 功能增强 + +### 用户体验 +1. [ ] 创建更直观的设置界面 +2. [ ] 为操作添加视觉反馈 +3. [ ] 实现撤销/重做功能 + +### 集成 +1. [ ] 添加对更多Minecraft版本的支持 +2. [ ] 添加与流行Minecraft服务器的集成 +3. [ ] 为其他模组创建兼容性层,如Optifine等 +4. [ ] 实现配置文件的云同步 +5. [ ] 添加AI相关功能的集成 diff --git a/shared/java/top/fpsmaster/FPSMaster.java b/shared/java/top/fpsmaster/FPSMaster.java index faeadf49..e21b9e9f 100644 --- a/shared/java/top/fpsmaster/FPSMaster.java +++ b/shared/java/top/fpsmaster/FPSMaster.java @@ -1,26 +1,27 @@ package top.fpsmaster; -import net.minecraftforge.fml.common.FMLCommonHandler; -import top.fpsmaster.features.GlobalSubmitter; +import top.fpsmaster.exception.ExceptionHandler; +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; -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; import top.fpsmaster.modules.logger.ClientLogger; import top.fpsmaster.modules.lua.LuaManager; 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.click.music.NewMusicPanel; import top.fpsmaster.ui.custom.ComponentsManager; 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; @@ -34,31 +35,29 @@ 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; - 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(); 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(); public static OOBEScreen oobeScreen = new OOBEScreen(); public static AccountManager accountManager = new AccountManager(); - public static GlobalSubmitter submitter = new GlobalSubmitter(); + public static ClientUsersManager clientUsersManager = new ClientUsersManager(); + public static GlobalListener submitter = new GlobalListener(); public static CommandManager commandManager = new CommandManager(); 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; @@ -68,17 +67,18 @@ private static void checkDevelopment() { try { Class.forName("net.fabricmc.devlaunchinjector.Main"); development = true; - } catch (Throwable e) { + } catch (Throwable ignored) { } } 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..."); @@ -88,22 +88,22 @@ private void initializeFonts() { fontManager.load(); } - private void initializeLang() { + 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() { + 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"); + NewMusicPanel.nickname = FileUtils.readTempValue("nickname"); accountManager.autoLogin(); } @@ -144,7 +144,7 @@ private void initializeModules() { submitter.init(); } - private void initializePlugins() { + private void initializePlugins() throws FileException { luaManager.init(); } @@ -157,45 +157,54 @@ 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) { - isLatest = false; - updateFailed = true; - return; - } - if (!s.isEmpty()) { - latest = s; - isLatest = CLIENT_VERSION.equals(s); + if (s == null || s.isEmpty()) { + s = UpdateChecker.getLatestVersion(); + if (s == null || s.isEmpty()) { + isLatest = false; + updateFailed = true; + ClientLogger.error("获取最新版本信息失败"); + return; + } } + s = s.trim(); + latest = s; + isLatest = GitInfo.getCommitId().equals(s); }); } public void initialize() { - initializeFonts(); - initializeLang(); - initializeMusic(); - initializeModules(); - initializeComponents(); - initializeConfigures(); - initializeCommands(); - initializePlugins(); - - if (phase == "release") { + try { + initializeFonts(); + initializeMusic(); + initializeModules(); + initializeComponents(); + initializeConfigures(); + initializeCommands(); + initializePlugins(); + initializeLang(); checkUpdate(); + checkOptifine(); + } catch (Exception e) { + ExceptionHandler.handle(e); } - if (phase == "alpha") { - autoUpdate(); - } - checkOptifine(); } - public void autoUpdate() { - File mods = FMLCommonHandler.instance().getMinecraftServerInstance().getFile("mods"); - } public void shutdown() { - configManager.saveConfig("default"); + try { + ClientLogger.info("Saving configs"); + configManager.saveConfig("default"); + if (wsClient != null && wsClient.isOpen()) { + wsClient.close(200, "Shutdown"); + } + } catch (FileException e) { + throw new RuntimeException(e); + } } } \ No newline at end of file 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/EventDispatcher.java b/shared/java/top/fpsmaster/event/EventDispatcher.java index 5e1b8a0c..c98fa13f 100644 --- a/shared/java/top/fpsmaster/event/EventDispatcher.java +++ b/shared/java/top/fpsmaster/event/EventDispatcher.java @@ -1,6 +1,10 @@ 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; import java.util.List; @@ -33,14 +37,40 @@ 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()); - e.printStackTrace(); + 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()); + e.printStackTrace(); + } } } + 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/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/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 new file mode 100644 index 00000000..03c5fad9 --- /dev/null +++ b/shared/java/top/fpsmaster/event/events/EventValueChange.java @@ -0,0 +1,15 @@ +package top.fpsmaster.event.events; + +import top.fpsmaster.event.CancelableEvent; +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/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..6d7b1049 --- /dev/null +++ b/shared/java/top/fpsmaster/exception/ExceptionHandler.java @@ -0,0 +1,102 @@ +package top.fpsmaster.exception; + +import top.fpsmaster.modules.logger.ClientLogger; + +/** + * 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()); + } + 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); +// } + } +} 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..dc3dc3cc --- /dev/null +++ b/shared/java/top/fpsmaster/exception/NetworkException.java @@ -0,0 +1,28 @@ +package top.fpsmaster.exception; + +/** + * 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(int code, String message) { + super(message); + this.code = code; + } + + /** + * Constructs a new NetworkException with the specified detail message and cause. + * + * @param message the detail message + * @param cause the 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/features/GlobalListener.java b/shared/java/top/fpsmaster/features/GlobalListener.java new file mode 100644 index 00000000..cb75ed39 --- /dev/null +++ b/shared/java/top/fpsmaster/features/GlobalListener.java @@ -0,0 +1,224 @@ +package top.fpsmaster.features; + +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; +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.account.AccountManager; +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; +import top.fpsmaster.utils.render.StencilUtil; +import top.fpsmaster.utils.render.shader.KawaseBlur; +import top.fpsmaster.websocket.client.WsClient; + +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; + +public class GlobalListener { + + MathTimer musicSwitchTimer = new MathTimer(); + + public void init() { + EventDispatcher.registerListener(this); + } + + @Subscribe + public void onChat(EventPacket e) { +// if (Translator.using) { +// if (ProviderManager.packetChat.isPacket(e.packet)) { +// ProviderManager.packetChat.appendTranslation(e.packet); +// } +// } + } + + @Subscribe + public void onChatSend(EventSendChatMessage e) { + String msg = e.msg; + } + + + PlayerInformation playerInformation = null; + + + Map playerInfos = new ConcurrentHashMap<>(); + Thread tickThread; + Thread accThread; + + @Subscribe + public void onTick(EventTick e) throws URISyntaxException { + 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 && (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(); + } + }); + 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; + if (mc.getNetHandler().getPlayerInfoMap() == null) + return; + + Set currentPlayers = mc.getNetHandler().getPlayerInfoMap().stream() + .map(info -> info.getGameProfile().getId()) + .collect(Collectors.toSet()); + + 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)) { + playerInfos.put(uuid, info); + FPSMaster.INSTANCE.wsClient.fetchPlayer(uuid.toString(), info.getGameProfile().getName()); + } + } + + 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()); + } 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()); + } + } + }); + accThread.start(); + } + } + + @Subscribe + public void onCape(EventCapeLoading e) { + 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; + cosmetic1.frameTime = System.currentTimeMillis(); + } + e.setCachedCape("ornaments/" + cosmetic + "_resource_" + cosmetic1.frame); + } else { + e.setCachedCape("ornaments/" + cosmetic + "_resource"); + } + } + } + + @Subscribe + public void onRender(EventRender2D e) { + ScaledResolution scaledResolution = new ScaledResolution(Minecraft.getMinecraft()); + float mouseX = (float) Mouse.getX() / scaledResolution.getScaleFactor(); + float mouseY = scaledResolution.getScaledHeight() - (float) Mouse.getY() / scaledResolution.getScaleFactor(); + + if (ClientSettings.blur.getValue()) { + StencilUtil.initStencilToWrite(); + EventDispatcher.dispatchEvent(new EventShader()); + FPSMaster.componentsManager.draw((int) mouseX, (int) mouseY); + StencilUtil.readStencilBuffer(1); + KawaseBlur.renderBlur(3, 3); + StencilUtil.uninitStencilBuffer(); + } + FPSMaster.componentsManager.draw((int) mouseX, (int) mouseY); + NotificationManager.drawNotifications(); + } + + static 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/GlobalSubmitter.java b/shared/java/top/fpsmaster/features/GlobalSubmitter.java deleted file mode 100644 index f60ba856..00000000 --- a/shared/java/top/fpsmaster/features/GlobalSubmitter.java +++ /dev/null @@ -1,66 +0,0 @@ -package top.fpsmaster.features; - -import net.minecraft.client.Minecraft; -import net.minecraft.client.gui.ScaledResolution; -import org.lwjgl.input.Mouse; -import top.fpsmaster.FPSMaster; -import top.fpsmaster.event.EventDispatcher; -import top.fpsmaster.event.Subscribe; -import top.fpsmaster.event.events.*; -import top.fpsmaster.features.impl.interfaces.ClientSettings; -import top.fpsmaster.modules.music.MusicPlayer; -import top.fpsmaster.ui.notification.NotificationManager; -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; - -public class GlobalSubmitter { - - MathTimer musicSwitchTimer = new MathTimer(); - - public void init() { - EventDispatcher.registerListener(this); - } - - @Subscribe - public void onChat(EventPacket e) { -// if (Translator.using) { -// if (ProviderManager.packetChat.isPacket(e.packet)) { -// ProviderManager.packetChat.appendTranslation(e.packet); -// } -// } - } - - @Subscribe - public void onChatSend(EventSendChatMessage e) { - String msg = e.msg; - } - - @Subscribe - public void onTick(EventTick e) { - if (musicSwitchTimer.delay(1000)) { - if (MusicPlayer.isPlaying && MusicPlayer.getPlayProgress() > 0.999) { - MusicPlayer.playList.next(); - } - } - } - - @Subscribe - public void onRender(EventRender2D e) { - ScaledResolution scaledResolution = new ScaledResolution(Minecraft.getMinecraft()); - float mouseX = (float) Mouse.getX() / scaledResolution.getScaleFactor(); - float mouseY = scaledResolution.getScaledHeight() - (float) Mouse.getY() / scaledResolution.getScaleFactor(); - - if (ClientSettings.blur.value) { - StencilUtil.initStencilToWrite(); - EventDispatcher.dispatchEvent(new EventShader()); - FPSMaster.componentsManager.draw((int) mouseX, (int) mouseY); - StencilUtil.readStencilBuffer(1); - KawaseBlur.renderBlur(3, 3); - StencilUtil.uninitStencilBuffer(); - } - FPSMaster.componentsManager.draw((int) mouseX, (int) mouseY); - NotificationManager.drawNotifications(); - } -} diff --git a/shared/java/top/fpsmaster/features/command/Command.java b/shared/java/top/fpsmaster/features/command/Command.java index 42c37f19..c1fbb31a 100644 --- a/shared/java/top/fpsmaster/features/command/Command.java +++ b/shared/java/top/fpsmaster/features/command/Command.java @@ -1,10 +1,11 @@ package top.fpsmaster.features.command; + 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 Exception; } diff --git a/shared/java/top/fpsmaster/features/command/CommandManager.java b/shared/java/top/fpsmaster/features/command/CommandManager.java index 3b79f91e..422ebf23 100644 --- a/shared/java/top/fpsmaster/features/command/CommandManager.java +++ b/shared/java/top/fpsmaster/features/command/CommandManager.java @@ -7,12 +7,14 @@ 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; import java.util.List; +import static top.fpsmaster.utils.Utility.mc; + public class CommandManager { private final List commands = new ArrayList<>(); @@ -26,18 +28,16 @@ public void init() { } @Subscribe - public void onChat(EventSendChatMessage e) { - if (ClientCommand.using && e.msg.startsWith(ClientCommand.prefix.getValue())) { + public void onChat(EventSendChatMessage e) throws Exception { + if (ClientSettings.clientCommand.getValue() && e.msg.startsWith(ClientSettings.prefix.getValue())) { e.cancel(); - try { - 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 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 7afb899d..adc4c095 100644 --- a/shared/java/top/fpsmaster/features/command/impl/AI.java +++ b/shared/java/top/fpsmaster/features/command/impl/AI.java @@ -1,22 +1,20 @@ 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; 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" + @@ -64,7 +62,7 @@ public AI() { } @Override - public void execute(String[] args) { + public void execute(String[] args) throws Exception { StringBuilder sb = new StringBuilder(); if (args.length > 0) { if (args[0].equals("lua")) { @@ -95,7 +93,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/features/command/impl/Dev.java b/shared/java/top/fpsmaster/features/command/impl/Dev.java index b76925de..71fa0645 100644 --- a/shared/java/top/fpsmaster/features/command/impl/Dev.java +++ b/shared/java/top/fpsmaster/features/command/impl/Dev.java @@ -1,9 +1,7 @@ package top.fpsmaster.features.command.impl; import net.minecraft.client.Minecraft; -import top.fpsmaster.FPSMaster; 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; @@ -16,7 +14,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")); @@ -35,8 +33,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/shared/java/top/fpsmaster/features/command/impl/IRCChat.java b/shared/java/top/fpsmaster/features/command/impl/IRCChat.java index 01badf5d..2f4f5d00 100644 --- a/shared/java/top/fpsmaster/features/command/impl/IRCChat.java +++ b/shared/java/top/fpsmaster/features/command/impl/IRCChat.java @@ -1,9 +1,15 @@ 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; +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,12 @@ 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, 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()); + } } else { for (String arg : args) { if (arg.equals(args[args.length - 1])) { diff --git a/shared/java/top/fpsmaster/features/impl/InterfaceModule.java b/shared/java/top/fpsmaster/features/impl/InterfaceModule.java index a4beab2b..4498dbad 100644 --- a/shared/java/top/fpsmaster/features/impl/InterfaceModule.java +++ b/shared/java/top/fpsmaster/features/impl/InterfaceModule.java @@ -6,16 +6,18 @@ 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 { 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); + public InterfaceModule(String name, Category category) { super(name, category); diff --git a/shared/java/top/fpsmaster/features/impl/interfaces/ArmorDisplay.java b/shared/java/top/fpsmaster/features/impl/interfaces/ArmorDisplay.java index 8aba6c1a..dcbbc73c 100644 --- a/shared/java/top/fpsmaster/features/impl/interfaces/ArmorDisplay.java +++ b/shared/java/top/fpsmaster/features/impl/interfaces/ArmorDisplay.java @@ -2,16 +2,13 @@ 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"); 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/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/features/impl/interfaces/CPSDisplay.java b/shared/java/top/fpsmaster/features/impl/interfaces/CPSDisplay.java index 39b984a1..f8b86cc4 100644 --- a/shared/java/top/fpsmaster/features/impl/interfaces/CPSDisplay.java +++ b/shared/java/top/fpsmaster/features/impl/interfaces/CPSDisplay.java @@ -7,12 +7,12 @@ 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 { - 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/ClientSettings.java b/shared/java/top/fpsmaster/features/impl/interfaces/ClientSettings.java index 6639028f..b3b67f12 100644 --- a/shared/java/top/fpsmaster/features/impl/interfaces/ClientSettings.java +++ b/shared/java/top/fpsmaster/features/impl/interfaces/ClientSettings.java @@ -1,19 +1,41 @@ 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.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", 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()); public ClientSettings() { - super("ClientSettings", Category.Interface); - addSettings(keyBind, fixedScale, blur); + super("ClientSettings", Category.Utility); + 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 @@ -21,4 +43,24 @@ public void onEnable() { super.onEnable(); this.set(false); } + + @Subscribe + 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")); + e.cancel(); + } else { + Utility.sendClientNotify(FPSMaster.i18n.get("blur.performance")); + } + } + } } 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/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/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/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/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/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/interfaces/Keystrokes.java b/shared/java/top/fpsmaster/features/impl/interfaces/Keystrokes.java index 14a0a3a0..2df23f42 100644 --- a/shared/java/top/fpsmaster/features/impl/interfaces/Keystrokes.java +++ b/shared/java/top/fpsmaster/features/impl/interfaces/Keystrokes.java @@ -3,13 +3,16 @@ 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)); + 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(rounded, backgroundColor, fontShadow, betterFont, pressedColor, bg, 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/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/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/ModsList.java b/shared/java/top/fpsmaster/features/impl/interfaces/ModsList.java index fbd6c2b0..43a29992 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; +import java.awt.*; 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, spacing, backgroundColor, bg); } } diff --git a/shared/java/top/fpsmaster/features/impl/interfaces/MusicOverlay.java b/shared/java/top/fpsmaster/features/impl/interfaces/MusicOverlay.java index 2092b73b..a9f91f1b 100644 --- a/shared/java/top/fpsmaster/features/impl/interfaces/MusicOverlay.java +++ b/shared/java/top/fpsmaster/features/impl/interfaces/MusicOverlay.java @@ -1,19 +1,38 @@ 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; 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; +import java.awt.*; 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, betterFont, fontShadow); } - 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)); + Thread updateThread = new Thread(JLayerHelper::updateLoudness); + + @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/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/PotionDisplay.java b/shared/java/top/fpsmaster/features/impl/interfaces/PotionDisplay.java index 6da8f8b7..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(rounded, backgroundColor, fontShadow, betterFont, bg, rounded, roundRadius); + addSettings(backgroundColor, fontShadow, betterFont, spacing, bg, rounded, roundRadius); } @Override diff --git a/shared/java/top/fpsmaster/features/impl/interfaces/ReachDisplay.java b/shared/java/top/fpsmaster/features/impl/interfaces/ReachDisplay.java index 25affbb7..5051435a 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; @@ -24,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); @@ -34,48 +34,9 @@ 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) { - d1 = rayTrace.hitVec.distanceTo(vec3d); - } - 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) + if (mc.objectMouseOver == null || mc.objectMouseOver.entityHit == 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); reach = Double.parseDouble(String.format("%.2f", distance)); - } } } diff --git a/shared/java/top/fpsmaster/features/impl/interfaces/TargetDisplay.java b/shared/java/top/fpsmaster/features/impl/interfaces/TargetDisplay.java index f3c1b829..758fe049 100644 --- a/shared/java/top/fpsmaster/features/impl/interfaces/TargetDisplay.java +++ b/shared/java/top/fpsmaster/features/impl/interfaces/TargetDisplay.java @@ -9,24 +9,24 @@ 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; -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"); - 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"); + 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", "fancy", "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 @@ -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 617077a3..32a7ba18 100644 --- a/shared/java/top/fpsmaster/features/impl/optimizes/OldAnimations.java +++ b/shared/java/top/fpsmaster/features/impl/optimizes/OldAnimations.java @@ -2,28 +2,38 @@ import net.minecraft.client.Minecraft; import net.minecraft.client.entity.EntityPlayerSP; +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; 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; + +import static top.fpsmaster.utils.Utility.mc; 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(), "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); 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 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); + public static NumberSetting scale = new NumberSetting("Scale", 1, 0, 3, 0.01); public static boolean using = false; @@ -34,7 +44,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, oldThirdPerson, blockSwing, oldDamage, oldUsing, oldBlock, animationMode, x, y, z); } @Override @@ -66,6 +76,9 @@ public void onTick(EventTick event) { delta *= 0.4f; eyeHeight = START_HEIGHT - delta; } + if (Minecraft.getMinecraft().gameSettings.keyBindAttack.isKeyDown() && thePlayer.isUsingItem() && blockSwing.getValue()) { + swingItem(); + } } public static float getClientEyeHeight(float partialTicks) { @@ -84,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/optimizes/Performance.java b/shared/java/top/fpsmaster/features/impl/optimizes/Performance.java index ede29ca0..a95c310a 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 { @@ -25,16 +21,16 @@ 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); 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); - 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/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/optimizes/WavyCape.java b/shared/java/top/fpsmaster/features/impl/optimizes/WavyCape.java new file mode 100644 index 00000000..578ee6a6 --- /dev/null +++ b/shared/java/top/fpsmaster/features/impl/optimizes/WavyCape.java @@ -0,0 +1,11 @@ +package top.fpsmaster.features.impl.optimizes; + +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.RENDER); + } +} diff --git a/shared/java/top/fpsmaster/features/impl/render/BlockOverlay.java b/shared/java/top/fpsmaster/features/impl/render/BlockOverlay.java index f10611ed..b9782ee4 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/Crosshair.java b/shared/java/top/fpsmaster/features/impl/render/Crosshair.java index a7fdcba0..3b8d970f 100644 --- a/shared/java/top/fpsmaster/features/impl/render/Crosshair.java +++ b/shared/java/top/fpsmaster/features/impl/render/Crosshair.java @@ -13,22 +13,22 @@ 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); + 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)); @@ -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 a7f8f3d0..d130f4ca 100644 --- a/shared/java/top/fpsmaster/features/impl/render/DamageIndicator.java +++ b/shared/java/top/fpsmaster/features/impl/render/DamageIndicator.java @@ -2,23 +2,24 @@ import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.GlStateManager; -import net.minecraft.entity.Entity; -import net.minecraft.entity.item.EntityTNTPrimed; +import net.minecraft.entity.EntityLivingBase; 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; 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; + public DamageIndicator() { super("DamageIndicator", Category.RENDER); } @@ -30,30 +31,50 @@ 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 (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(); + } + } @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) { Minecraft mc = Minecraft.getMinecraft(); DecimalFormat df = new DecimalFormat("0.00"); - String damage = df.format(indicator.damage); + 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); @@ -63,48 +84,52 @@ 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); 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(); - Color color = new Color(20, 255, 20); + 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(255, 20, 20); + color = new Color(224, 41, 41, alpha); } GL11.glEnable(3553); GL11.glDisable(3042); GL11.glDisable(2848); + GlStateManager.enableBlend(); ProviderManager.mcProvider.getFontRenderer().drawStringWithShadow(damage, -width + 5, indicator.animation * 10, color.getRGB()); GlStateManager.enableLighting(); - GlStateManager.enableBlend(); GlStateManager.enableDepth(); + GlStateManager.disableBlend(); 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); GL11.glPopMatrix(); + GL11.glPopAttrib(); } -} -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/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() { diff --git a/shared/java/top/fpsmaster/features/impl/render/FireModifier.java b/shared/java/top/fpsmaster/features/impl/render/FireModifier.java index f30ef102..b9343fd9 100644 --- a/shared/java/top/fpsmaster/features/impl/render/FireModifier.java +++ b/shared/java/top/fpsmaster/features/impl/render/FireModifier.java @@ -6,12 +6,12 @@ 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 { 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/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/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/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/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/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))); + } } } } diff --git a/shared/java/top/fpsmaster/features/impl/render/MotionBlur.java b/shared/java/top/fpsmaster/features/impl/render/MotionBlur.java index fc989fe5..f6fb2ce5 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 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); - 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/java/top/fpsmaster/features/impl/utility/AutoGG.java b/shared/java/top/fpsmaster/features/impl/utility/AutoGG.java new file mode 100644 index 00000000..25c6edfc --- /dev/null +++ b/shared/java/top/fpsmaster/features/impl/utility/AutoGG.java @@ -0,0 +1,88 @@ +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; +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.utils.Utility; +import top.fpsmaster.utils.math.MathTimer; + +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 TextSetting message = new TextSetting("Message", "gg"); + private final ModeSetting servers = new ModeSetting("Servers", 0, "hypixel", "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); + this.addSettings(autoPlay, delay, message, servers); + } + + @Subscribe + public void onPacket(EventPacket event) { + if (event.type == EventPacket.PacketType.RECEIVE && ProviderManager.packetChat.isPacket(event.packet)) { + IChatComponent componentValue = ProviderManager.packetChat.getChatComponent(event.packet); + String chatMessage = componentValue.getUnformattedText(); + switch (servers.getValue()) { + case 0: + 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 ")) { + if (delay.getValue().doubleValue() > 0) { + Utility.sendClientNotify("Sending you to the next game in " + delay.getValue().intValue() + " 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: + 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"); + } + } + } + } + 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 58ae5e4f..50eaa118 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; @@ -40,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); @@ -49,7 +46,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 +54,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 +71,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,17 +91,16 @@ 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(); } - if (ProviderManager.mcProvider.getPlayer() == null) return; - ProviderManager.mcProvider.getPlayer().sendChatMessage(s); + Utility.sendChatMessage(s); } }); } 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..281f1ee3 100644 --- a/shared/java/top/fpsmaster/features/impl/utility/IRC.java +++ b/shared/java/top/fpsmaster/features/impl/utility/IRC.java @@ -1,23 +1,12 @@ 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.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; public static final BooleanSetting showMates = new BooleanSetting("showMates", true); - private final MathTimer timer = new MathTimer(); public IRC() { super("IRC", Category.Utility); @@ -30,29 +19,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.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/LevelTag.java b/shared/java/top/fpsmaster/features/impl/utility/LevelTag.java index 244a3595..a04b6bab 100644 --- a/shared/java/top/fpsmaster/features/impl/utility/LevelTag.java +++ b/shared/java/top/fpsmaster/features/impl/utility/LevelTag.java @@ -1,18 +1,21 @@ 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; 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; 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 top.fpsmaster.modules.client.ClientUsersManager; +import top.fpsmaster.utils.render.Render2DUtils; import static top.fpsmaster.utils.Utility.mc; @@ -21,14 +24,19 @@ 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) { + if (!using) + return; + if(!str.contains(entityIn.getName()) || !(entityIn instanceof EntityPlayer)) + return; + if (str.contains("[NPC]")) + return; double d = entityIn.getDistanceSqToEntity(mc.getRenderManager().livingPlayer); if (d < 100) { float f = 1.6F; @@ -38,7 +46,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); @@ -59,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; @@ -86,19 +96,35 @@ else if (mc.gameSettings.thirdPersonView == 1) i = -10; } + boolean isMate = ((entityIn == mc.thePlayer) && str.contains(entityIn.getName())) || FPSMaster.clientUsersManager.getClientUser(entityIn) != null; + int j = fontRenderer.getStringWidth(str) / 2; + + if (isMate) { + j += 6; + } + 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); + 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/java/top/fpsmaster/features/impl/utility/SkinChanger.java b/shared/java/top/fpsmaster/features/impl/utility/SkinChanger.java index 870bb1d5..356fa3fc 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,9 +14,11 @@ import top.fpsmaster.interfaces.ProviderManager; import top.fpsmaster.modules.account.AccountManager; +import static top.fpsmaster.utils.Utility.mc; + 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(); @@ -24,6 +31,7 @@ public class SkinChanger extends Module { }); public static boolean using = false; + private WorldClient world; public SkinChanger() { super("SkinChanger", Category.Utility); @@ -42,12 +50,16 @@ 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()) && world == mc.theWorld) + return; + world = mc.theWorld; + AccountManager.skin = skinName.getValue(); FPSMaster.async.runnable(this::update); } - AccountManager.skin = skinName.getValue(); } public void update() { @@ -61,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/features/impl/utility/Sprint.java b/shared/java/top/fpsmaster/features/impl/utility/Sprint.java index 4a9261f5..1e4c4cf8 100644 --- a/shared/java/top/fpsmaster/features/impl/utility/Sprint.java +++ b/shared/java/top/fpsmaster/features/impl/utility/Sprint.java @@ -1,26 +1,54 @@ package top.fpsmaster.features.impl.utility; 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; -public class Sprint extends Module { +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); public Sprint() { super("Sprint", Category.Utility); + addSettings(toggleSprint, betterFont); + } + + + @Override + public void onEnable() { + super.onEnable(); + using = true; } @Subscribe public void onUpdate(EventUpdate e) { - ProviderManager.gameSettings.setKeyPress(Utility.mc.gameSettings.keyBindSprint, true); + if (!toggleSprint.getValue()) { + sprint = true; + } + } + + @Subscribe + public void onKey(EventKey e) { + if (toggleSprint.getValue() && e.key == mc.gameSettings.keyBindSprint.getKeyCode()) { + sprint = !sprint; + if (!sprint) + mc.thePlayer.setSprinting(false); + } } @Override public void onDisable() { super.onDisable(); - ProviderManager.gameSettings.setKeyPress(Utility.mc.gameSettings.keyBindSprint, false); + 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/features/impl/utility/TNTTimer.java b/shared/java/top/fpsmaster/features/impl/utility/TNTTimer.java index e2c063ac..e5f2f671 100644 --- a/shared/java/top/fpsmaster/features/impl/utility/TNTTimer.java +++ b/shared/java/top/fpsmaster/features/impl/utility/TNTTimer.java @@ -10,13 +10,13 @@ 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 { 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); @@ -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/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 769e6ffb..9288c0ec 100644 --- a/shared/java/top/fpsmaster/features/manager/Module.java +++ b/shared/java/top/fpsmaster/features/manager/Module.java @@ -4,13 +4,9 @@ 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.modules.logger.ClientLogger; import top.fpsmaster.ui.notification.NotificationManager; import java.util.LinkedList; @@ -41,17 +37,19 @@ 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); + } else if (setting instanceof MultipleItemSetting) { + this.settings.add(setting); } } } @@ -62,9 +60,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 +74,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( @@ -90,6 +89,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/features/manager/ModuleManager.java b/shared/java/top/fpsmaster/features/manager/ModuleManager.java index d9691b95..1c61d541 100644 --- a/shared/java/top/fpsmaster/features/manager/ModuleManager.java +++ b/shared/java/top/fpsmaster/features/manager/ModuleManager.java @@ -6,12 +6,13 @@ 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.dev.DevMode; +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; @@ -46,8 +47,10 @@ public void onKey(EventKey e) { module.toggle(); } } - - if (e.key == Keyboard.KEY_INSERT) { +// 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()); } } @@ -72,6 +75,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()); @@ -92,6 +96,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()); @@ -100,6 +105,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()); @@ -112,10 +118,11 @@ 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()); + 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 81d155d8..637bbaa5 100644 --- a/shared/java/top/fpsmaster/features/settings/Setting.java +++ b/shared/java/top/fpsmaster/features/settings/Setting.java @@ -1,5 +1,8 @@ package top.fpsmaster.features.settings; +import top.fpsmaster.event.EventDispatcher; +import top.fpsmaster.event.events.EventValueChange; + public class Setting { public String name; @@ -22,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() { @@ -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..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 { @@ -23,10 +24,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..dabc6838 100644 --- a/shared/java/top/fpsmaster/features/settings/impl/ModeSetting.java +++ b/shared/java/top/fpsmaster/features/settings/impl/ModeSetting.java @@ -2,9 +2,11 @@ import top.fpsmaster.features.settings.Setting; +import java.util.Objects; + public class ModeSetting extends Setting { - private String[] modes; + private final String[] modes; public ModeSetting(String name, int value, String... modes) { super(name, value); @@ -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/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/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/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/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/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/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 5fdb11ff..ae969fa3 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 @@ -382,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/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/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/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/modules/account/AccountManager.java b/shared/java/top/fpsmaster/modules/account/AccountManager.java index af9af4f7..0b298c01 100644 --- a/shared/java/top/fpsmaster/modules/account/AccountManager.java +++ b/shared/java/top/fpsmaster/modules/account/AccountManager.java @@ -1,65 +1,143 @@ package top.fpsmaster.modules.account; +import com.google.gson.JsonElement; 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; +import java.io.IOException; +import java.util.ArrayList; +import java.util.HashMap; + public class AccountManager { private String token = ""; private String username = ""; - private String[] itemsHeld = new String[0]; + 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() { - 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 { + doAutoLogin(); + } catch (FileException e) { + ExceptionHandler.handleFileException(e, "尝试自动登录失败"); + } catch (AccountException e) { + ExceptionHandler.handleAccountException(e, "尝试自动登录失败"); + } catch (NetworkException e) { + ExceptionHandler.handleNetworkException(e, "尝试自动登录失败"); + } catch (Exception e) { + ExceptionHandler.handle(e, "尝试自动登录失败"); + } + }); + } + + private void doAutoLogin() throws FileException, AccountException, NetworkException { + token = FileUtils.readTempValue("token").trim(); + username = FPSMaster.configManager.configure.getOrCreate("username", "").trim(); + if (!token.isEmpty() && !username.isEmpty()) { + if (attemptLogin(username, token)) { + ClientLogger.info("自动登录成功! " + username); + FPSMaster.INSTANCE.loggedIn = true; + } else { + ClientLogger.info(username); + ClientLogger.error("自动登录失败!"); + throw new AccountException("自动登录失败"); } - } catch (Exception e) { - e.printStackTrace(); - ClientLogger.error("尝试自动登录失败!" + e.getMessage()); } } - private boolean attemptLogin(String username, String token) { + private boolean attemptLogin(String username, String token) throws AccountException { 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 { + HashMap headers = new HashMap<>(); + 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 AccountException("Failed to login via token"); + } } - 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 static JsonObject login(String username, String password) throws AccountException { + JsonObject body = new JsonObject(); + body.addProperty("username", username); + body.addProperty("password", password); + HttpRequest.HttpResponseResult s; + try { + s = HttpRequest.post(FPSMaster.SERVICE_API + "/api/auth/login", body.toString()); + } catch (IOException e) { + throw new RuntimeException(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; } - public static JsonParser parser = new JsonParser(); - public static String cape = ""; - public static String skin = ""; + 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 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 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); + cosmetic.load(); + } + } catch (Exception e) { + throw new AccountException("Failed to login via token"); + } } // Getter and Setter methods @@ -78,12 +156,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/account/Cosmetic.java b/shared/java/top/fpsmaster/modules/account/Cosmetic.java new file mode 100644 index 00000000..e52858ab --- /dev/null +++ b/shared/java/top/fpsmaster/modules/account/Cosmetic.java @@ -0,0 +1,64 @@ +package top.fpsmaster.modules.account; + +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; + +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 Integer frame = 0; + public long frameTime = 0; + public List frames = new ArrayList<>(); + + public Cosmetic() { + } + + public void load() { + if (mc.theWorld == null) return; + FPSMaster.async.runnable(() -> { + if (resource.endsWith(".png")) { + ResourceLocation textureLocation = new ResourceLocation("ornaments/" + id + "_resource"); + ThreadDownloadImageData downloadImageData = new ThreadDownloadImageData(null, null, textureLocation, null); + try { + downloadImageData.setBufferedImage(HttpRequest.downloadImage(resource)); + mc.getTextureManager().loadTexture(textureLocation, downloadImageData); + } catch (IOException ignored) { + } + } 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, null, textureLocation, null); + downloadImageData.setBufferedImage(frame.image); + mc.getTextureManager().loadTexture(textureLocation, downloadImageData); + } + loaded = true; + } catch (IOException e) { + throw new RuntimeException(e); + } + } + }); + } +} 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..da19a86d --- /dev/null +++ b/shared/java/top/fpsmaster/modules/client/ClientUsersManager.java @@ -0,0 +1,39 @@ +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; + +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); + ClientUser rm = null; + for (ClientUser user : users) { + if (user.uid.equals(clientUser.uid)) + rm = user; + } + 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) { + for (ClientUser user : users) + if (user.gameId.equals(entityIn.getName()) && user.uuid.equals(entityIn.getUniqueID().toString())) + 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/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; } } diff --git a/shared/java/top/fpsmaster/modules/client/AsyncTask.java b/shared/java/top/fpsmaster/modules/client/thread/ClientThreadPool.java similarity index 61% rename from shared/java/top/fpsmaster/modules/client/AsyncTask.java rename to shared/java/top/fpsmaster/modules/client/thread/ClientThreadPool.java index ab8fa11b..53b5667e 100644 --- a/shared/java/top/fpsmaster/modules/client/AsyncTask.java +++ b/shared/java/top/fpsmaster/modules/client/thread/ClientThreadPool.java @@ -1,11 +1,13 @@ -package top.fpsmaster.modules.client; +package top.fpsmaster.modules.client.thread; 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/config/ConfigManager.java b/shared/java/top/fpsmaster/modules/config/ConfigManager.java index 15750ccb..fc39a788 100644 --- a/shared/java/top/fpsmaster/modules/config/ConfigManager.java +++ b/shared/java/top/fpsmaster/modules/config/ConfigManager.java @@ -1,25 +1,28 @@ package top.fpsmaster.modules.config; import com.google.gson.*; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; import top.fpsmaster.FPSMaster; -import top.fpsmaster.features.impl.InterfaceModule; +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; -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; 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; +import top.fpsmaster.utils.world.ItemsUtil; -import java.util.HashMap; +import java.util.*; public class ConfigManager { - private Gson gson = new GsonBuilder().setPrettyPrinting().create(); + private final Gson gson = new GsonBuilder().setPrettyPrinting().create(); public Configure configure = new Configure(); @@ -29,7 +32,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(); @@ -43,7 +46,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); @@ -65,22 +68,36 @@ 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); - 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(); moduleJson.addProperty("enabled", module.isEnabled()); moduleJson.addProperty("key", module.key); for (Setting setting : module.settings) { - String settingValue = setting.value.toString(); + 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; - 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); } @@ -90,66 +107,69 @@ 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(); - - 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(); - } + readComponents(); + jsonStr = FileUtils.readFile(name + ".json"); + JsonObject json = gson.fromJson(jsonStr, JsonObject.class); + + 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.setValue(settingValue.getAsBoolean()); + } else if (setting instanceof NumberSetting) { + NumberSetting numberSetting = (NumberSetting) setting; + numberSetting.setValue(settingValue.getAsDouble()); + } else if (setting instanceof ModeSetting) { + ModeSetting modeSetting = (ModeSetting) setting; + modeSetting.setValue(settingValue.getAsInt()); + } else if (setting instanceof TextSetting) { + TextSetting textSetting = (TextSetting) setting; + textSetting.setValue(settingValue.getAsString()); + } else if (setting instanceof ColorSetting) { + ColorSetting colorSetting = (ColorSetting) setting; + String[] colorParts = settingValue.getAsString().split("\\|"); + colorSetting.getValue().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.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)); } - } catch (Exception e) { - e.printStackTrace(); } } } } + } - configure.configures = gson.fromJson(json.get("clientConfigure").getAsString(), HashMap.class); - } catch (Exception e) { - e.printStackTrace(); + JsonObject clientConfigure = json.get("clientConfigure").getAsJsonObject(); + for (Map.Entry element : clientConfigure.entrySet()) { + configure.configures.put(element.getKey(), element.getValue().getAsString()); } } @@ -157,7 +177,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/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..17bc4c92 100644 --- a/shared/java/top/fpsmaster/modules/i18n/Language.java +++ b/shared/java/top/fpsmaster/modules/i18n/Language.java @@ -1,22 +1,20 @@ package top.fpsmaster.modules.i18n; +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; public class Language { - private Map prompts = new HashMap<>(); + private final Map prompts = new HashMap<>(); public Language() { FileUtils.release("en_us"); 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 +22,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/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 cc155dd1..932634d8 100644 --- a/shared/java/top/fpsmaster/modules/lua/LuaManager.java +++ b/shared/java/top/fpsmaster/modules/lua/LuaManager.java @@ -1,40 +1,43 @@ 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.exception.FileException; import top.fpsmaster.features.manager.Module; -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.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; +import top.skidder.parser.LuaParser; 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 { public static ArrayList scripts = new ArrayList<>(); - public void init() { - try { - reload(); - } catch (Exception e) { - e.printStackTrace(); - } + public void init() throws FileException { + reload(); } - 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')"); @@ -86,6 +89,38 @@ 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; + boolean onGround = ProviderManager.mcProvider.getPlayer().onGround; + + lua.push(posX); + lua.push(posY); + lua.push(posZ); + lua.push(onGround); + return 4; + }); + 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 +156,7 @@ public static LuaScript loadLua(RawLua rawLua) { // Module object lua.pushJavaObject(FPSMaster.moduleManager); lua.setGlobal("moduleManager"); + lua.pushJavaClass(LuaModule.class); lua.setGlobal("module"); @@ -167,7 +203,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) { @@ -183,20 +219,24 @@ public static void reload() { 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() { + 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/lua/LuaModule.java b/shared/java/top/fpsmaster/modules/lua/LuaModule.java index 86b00454..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; @@ -48,7 +47,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()); } } 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 85df408d..00000000 --- a/shared/java/top/fpsmaster/modules/lua/parser/Statement.java +++ /dev/null @@ -1,233 +0,0 @@ -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 { - 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/modules/music/IngameOverlay.java b/shared/java/top/fpsmaster/modules/music/IngameOverlay.java new file mode 100644 index 00000000..1407c315 --- /dev/null +++ b/shared/java/top/fpsmaster/modules/music/IngameOverlay.java @@ -0,0 +1,94 @@ +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.netease.Music; +import top.fpsmaster.utils.Utility; +import top.fpsmaster.utils.math.animation.AnimationUtils; +import top.fpsmaster.utils.render.Render2DUtils; + +import java.awt.*; + +public class IngameOverlay { + private static float songProgress = 0f; + private static double[] smoothCurve = new double[0]; + + public static void onRender() { + if (MusicPlayer.isPlaying) { + ScaledResolution sr = new ScaledResolution(Utility.mc); + double[] curve = MusicPlayer.getCurve(); + if (curve.length != 0) { + int numBars = 60; // 你希望显示的频谱柱条数 + if (smoothCurve.length != numBars) { + smoothCurve = new double[numBars]; + } + + float width = (float) sr.getScaledWidth() / numBars; + + float screenWidth = sr.getScaledWidth(); + float screenHeight = sr.getScaledHeight(); + + 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.getValue().floatValue()); + + Render2DUtils.drawRect( + xPos, + screenHeight - height, + width, + height, + MusicOverlay.color.getColor() + ); + } + } + } + } + + 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(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, + new Color(234, 234, 234).getRGB() + ); + + FPSMaster.fontManager.s16.drawString( + current.author, + x + 40, + y + 18, + new Color(162, 162, 162).getRGB() + ); + } +} diff --git a/shared/java/top/fpsmaster/modules/music/JLayerHelper.java b/shared/java/top/fpsmaster/modules/music/JLayerHelper.java index 78105295..d42b1cab 100644 --- a/shared/java/top/fpsmaster/modules/music/JLayerHelper.java +++ b/shared/java/top/fpsmaster/modules/music/JLayerHelper.java @@ -1,30 +1,43 @@ package top.fpsmaster.modules.music; +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; +import java.io.IOException; +import java.util.Arrays; -public class JLayerHelper { +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); + AudioInputStream aud = AudioSystem.getAudioInputStream(soundFile); + audIn = AudioSystem.getAudioInputStream(soundFile); + audioBytes = readAudioData(audIn); clip = AudioSystem.getClip(); - if (clip != null) { - clip.open(audioIn); - clip.start(); - } - } catch (Exception e) { + if (clip == null) return; + clip.open(aud); + clip.start(); + } catch (UnsupportedAudioFileException e) { + ClientLogger.error("Unsupported audio file: " + wavFile); e.printStackTrace(); } } @@ -35,16 +48,97 @@ public static void seek(float progress) { clip.setMicrosecondPosition(currentTime); } + public static void updateLoudness() { + if (clip == null || audIn == null || !clip.isActive()) return; + + AudioFormat format = audIn.getFormat(); + if (format.getEncoding() != AudioFormat.Encoding.PCM_SIGNED || format.getSampleSizeInBits() != 16) { + 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]; + System.arraycopy(audioData, 0, paddedData, 0, min(fftSize, audioData.length)); + + 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) { @@ -61,6 +155,8 @@ public static void convert(String sourcePath, String targetPath) { public static void stop() { if (clip != null) { clip.stop(); + clip.close(); + clip = null; } } @@ -73,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/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/modules/music/MusicPlayer.java b/shared/java/top/fpsmaster/modules/music/MusicPlayer.java index 865f2ffb..9c845d7f 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; @@ -13,28 +16,41 @@ public class MusicPlayer { public static float volume = 1f; public static float curPlayProgress = 0f; + 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 Math.min(curPlayProgress, 1f); + 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() { + return JLayerHelper.loudnessCurve; } public static void pause() { - isPlaying = false; if (JLayerHelper.clip == null) return; - JLayerHelper.stop(); + isPlaying = false; + pauseAt = getPlayProgress(); + JLayerHelper.pause(); } public static void stop() { - isPlaying = false; if (JLayerHelper.clip == null) return; + isPlaying = false; JLayerHelper.stop(); } @@ -46,12 +62,18 @@ 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")); - FPSMaster.async.runnable(() -> { - JLayerHelper.playWAV(filePath); + float v = Float.parseFloat(FPSMaster.configManager.configure.getOrCreate("volume", "1")); + if (playThread != null && playThread.isAlive()) + playThread.interrupt(); + playThread = new Thread(() -> { + try { + JLayerHelper.playWAV(path.replace(".mp3", ".wav")); + } catch (IOException | LineUnavailableException e) { + throw new RuntimeException(e); + } setVolume(v); }); + playThread.start(); } } @@ -65,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/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/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 891cd673..1661f571 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; @@ -20,7 +18,8 @@ public class Music extends AbstractMusic { String imgURL; String musicURL; public String id; - static Thread downloadThread; + public static Thread downloadThread; + public float downloadProgress; public Music(long id, String name, String artists, String picUrl) { this.name = name; @@ -34,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 +47,8 @@ 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()) { @@ -58,6 +58,7 @@ public void play() { } else { MusicPlayer.playFile(mp3.getAbsolutePath()); } + MusicPlayer.isPlaying = true; }).start(); } else { downloadThread = new Thread(this::download); @@ -73,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 24f2029a..c3558f00 100644 --- a/shared/java/top/fpsmaster/modules/music/netease/NeteaseApi.java +++ b/shared/java/top/fpsmaster/modules/music/netease/NeteaseApi.java @@ -1,66 +1,186 @@ 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; - 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); + } } + @Deprecated 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 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(); - 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); + } + } + + 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 4bf87fe0..f30a5f95 100644 --- a/shared/java/top/fpsmaster/modules/music/netease/deserialize/MusicWrapper.java +++ b/shared/java/top/fpsmaster/modules/music/netease/deserialize/MusicWrapper.java @@ -1,23 +1,20 @@ 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.io.IOException; import java.net.URLEncoder; +import java.util.ArrayList; import java.util.Iterator; +import java.util.List; 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); @@ -25,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) { @@ -50,9 +48,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 +70,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)); @@ -86,6 +82,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); @@ -143,7 +160,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(); @@ -182,16 +199,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(); } } @@ -204,4 +220,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/Compass.java b/shared/java/top/fpsmaster/ui/Compass.java index 3b3d56f7..a9085f04 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; @@ -59,109 +58,105 @@ 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); - 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(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) + : 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(); } @@ -174,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/CategoryComponent.java b/shared/java/top/fpsmaster/ui/click/CategoryComponent.java index 51575cdd..380041b2 100644 --- a/shared/java/top/fpsmaster/ui/click/CategoryComponent.java +++ b/shared/java/top/fpsmaster/ui/click/CategoryComponent.java @@ -7,22 +7,23 @@ import top.fpsmaster.utils.math.animation.Type; import top.fpsmaster.utils.render.Render2DUtils; +import java.awt.*; import java.util.Locale; 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) { 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) { 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 + 9, + y, 12f, 12f, animationName.getColor() 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..6fb5419d --- /dev/null +++ b/shared/java/top/fpsmaster/ui/click/CosmeticScreen.java @@ -0,0 +1,77 @@ +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; +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(guiWidth / 2f - 200, guiHeight / 2f - 130, 400, 260, 4, new Color(0, 0, 0, 100)); + GL11.glEnable(GL11.GL_SCISSOR_TEST); + 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()) + continue; + Cosmetic cosmetic = AccountManager.cosmetics.get(Integer.parseInt(id)); + if (!cosmetic.loaded) { + cosmetic.load(); + } + 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); + }); + GL11.glDisable(GL11.GL_SCISSOR_TEST); + + + } + + @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 + public void onClick(int mouseX, int mouseY, int 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 (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 = ""; + } 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 ffbe66bd..b34bd9b9 100644 --- a/shared/java/top/fpsmaster/ui/click/MainPanel.java +++ b/shared/java/top/fpsmaster/ui/click/MainPanel.java @@ -1,32 +1,25 @@ package top.fpsmaster.ui.click; -import net.minecraft.client.gui.GuiScreen; -import net.minecraft.client.gui.ScaledResolution; +import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.GlStateManager; import net.minecraft.util.ResourceLocation; 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; 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.themes.DarkTheme; -import top.fpsmaster.ui.click.themes.LightTheme; +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.ColorAnimation; 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.awt.*; import java.io.IOException; import java.util.LinkedList; @@ -36,21 +29,15 @@ public class MainPanel extends ScaledGuiScreen { float dragY = 0f; Category curType = Category.OPTIMIZE; LinkedList categories = new LinkedList<>(); - final float leftWidth = 110f; 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(FPSMaster.theme.getBackground()); - ColorAnimation modeColor = new ColorAnimation(FPSMaster.theme.getTypeSelectionBackground()); - ColorAnimation logoColor = new ColorAnimation(FPSMaster.theme.getLogo()); + + float categoryAnimation = 30; boolean close = false; @@ -62,8 +49,9 @@ public class MainPanel extends ScaledGuiScreen { static int x = -1; static int y = -1; - static float width = 0f; - static float height = 0f; + static float width = 430f; + static float height = 245.5f; + public static final float leftWidth = 50f; public static String bindLock = ""; public static Module curModule = null; public static String dragLock = "null"; @@ -76,12 +64,11 @@ 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"; drag = false; - sizeDrag = false; } if (drag) { @@ -90,22 +77,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(); @@ -118,104 +94,122 @@ 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()); - Render2DUtils.drawOptimizedRoundedRect( - x, - y, - width, - height, - backgroundColor.getColor() + Render2DUtils.drawImage(new ResourceLocation("client/gui/settings/window/panel.png"), + x + leftWidth - 8, + y - 2, + width - leftWidth + 16, + height + 12, + -1 ); - 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() - ); + moduleListAlpha = (float) AnimationUtils.base(moduleListAlpha, 255.0, 0.1f); - if (drag || sizeDrag) { - sizeDragBorder.start(sizeDragBorder.getColor(), new Color(255, 255, 255), 0.15f, Type.EASE_IN_OUT_QUAD); + if (curType == Category.Music) { + NewMusicPanel.draw(x + leftWidth, y, width - leftWidth, height, mouseX, mouseY, scaleFactor); } else { - sizeDragBorder.start(sizeDragBorder.getColor(), new Color(255, 255, 255, 0), 0.2f, Type.EASE_IN_OUT_QUAD); + 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; + 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 + 10, + moduleY, + containerWidth - 10, + 40f, + mouseX, + finalMouseY, + curModule == m.mod + ); + } + modsY += 45 + m.height; + modHeight += 45 + m.height; + } + } + modsContainer.setHeight(modHeight); + }); + GL11.glEnable(GL11.GL_BLEND); + GL11.glDisable(GL11.GL_SCISSOR_TEST); } - 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, - FPSMaster.theme.getDragHovered() - ); + + + if (Render2DUtils.isHovered(x, (int) (y + height / 2 - 70), categoryAnimation, 140, mouseX, mouseY)) { + categoryAnimation = (float) AnimationUtils.base(categoryAnimation, 100f, 0.15f); } else { - Render2DUtils.drawImage( - new ResourceLocation("client/gui/settings/drag.png"), - x + width - 5, - y + height - 5, - 5f, - 5f, - FPSMaster.theme.getDrag() - ); + categoryAnimation = (float) AnimationUtils.base(categoryAnimation, 30f, 0.15f); } - float my = (y + 60); - for (CategoryComponent m : categories) { - Render2DUtils.drawOptimizedRoundedRect( - x + 5, - my - 6, - leftWidth - 10, - 20f, - m.categorySelectionColor.getColor() - ); - my += 24f; - } + Render2DUtils.drawRoundedRectImage( + x + categoryAnimation / 50f, + y + height / 2 - 74, + categoryAnimation, + 140, + 20, + new Color(0, 0, 0, 200) + ); - my = (y + 60); - Render2DUtils.drawOptimizedRoundedRect( + 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.drawRoundedRectImage( + x + 4 + categoryAnimation / 50f, selection - 6, - leftWidth - 10, - 20f, - FPSMaster.theme.getPrimary() + categoryAnimation - 8, + 22f, + 20, + new Color(255, 255, 255) + ); + + + 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(FPSMaster.theme.getTypeSelectionBackground()); + 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(FPSMaster.theme.getTypeSelectionBackground(), 0)); + m.categorySelectionColor.base(Render2DUtils.reAlpha(new Color(70, 70, 70), 0)); } if (m.category == curType) { - selection = (sizeDrag || drag) + selection = drag ? my : (float) AnimationUtils.base(selection, my, 0.2); } m.render( - x + 5, + x + categoryAnimation / 50f, my, leftWidth - 10, 20f, @@ -223,128 +217,31 @@ public void render(int mouseX, int mouseY, float partialTicks) { mouseY, curType == m.category ); - my += 24f; + my += 27f; } - - 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()); - } - - GL11.glEnable(GL11.GL_SCISSOR_TEST); - Render2DUtils.doGlScissor( - x, y, width, - (height - 4), - 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); - } else { - modHeight = 20f; - float containerWidth = width - leftWidth - 2; - int finalMouseY = mouseY; - modsContainer.draw(x + leftWidth, y + 10f, containerWidth, height - 20f, mouseX, mouseY, () -> { - float modsY = y + 10f; - - 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, - moduleY, - containerWidth, - 40f, - mouseX, - finalMouseY, - curModule == m.mod - ); - } - modsY += 40 + m.height; - modHeight += 40 + m.height; - } - } - modsContainer.setHeight(modHeight); - }); - } - - 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); } @Override public void updateScreen() { super.updateScreen(); + x = (int) ((guiWidth - width) / 2); + y = (int) ((guiHeight - height) / 2); } @Override 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_OUT_BACK); +// aiChatPanel.init(); + NewMusicPanel.init(); + scaleAnimation.fstart(0.8, 1.0, 0.2f, Type.EASE_IN_OUT_QUAD); 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); - y = (int) ((scaledHeight - height) / 2); - } categories.clear(); for (Category c : Category.values()) { @@ -354,20 +251,29 @@ public void initGui() { selection = y + 70f; } + @Override + public void onResize(Minecraft mcIn, int w, int h) { + super.onResize(mcIn, w, h); + } + @Override public void onGuiClosed() { super.onGuiClosed(); - FPSMaster.configManager.saveConfig("default"); + try { + FPSMaster.configManager.saveConfig("default"); + } catch (FileException e) { + throw new RuntimeException(e); + } } @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) { 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; } @@ -378,47 +284,44 @@ public void keyTyped(char typedChar, int keyCode) throws IOException { } } - MusicPanel.keyTyped(typedChar, keyCode); + NewMusicPanel.keyTyped(typedChar, keyCode); super.keyTyped(typedChar, keyCode); } @Override 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(); +// 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 (mouseButton == 0 && Render2DUtils.isHoveredWithoutScale( - x, y, leftWidth, 34f, 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 (!Render2DUtils.isHovered(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 + 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 (!dragLock.equals("null")) + 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) { @@ -426,13 +329,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); + NewMusicPanel.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 +347,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/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 deb87127..9fefac9f 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; @@ -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, @@ -58,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 { @@ -74,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((double) wheel, (double) 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) { diff --git a/shared/java/top/fpsmaster/ui/click/modules/ModuleRenderer.java b/shared/java/top/fpsmaster/ui/click/modules/ModuleRenderer.java index 324913ea..f373f634 100644 --- a/shared/java/top/fpsmaster/ui/click/modules/ModuleRenderer.java +++ b/shared/java/top/fpsmaster/ui/click/modules/ModuleRenderer.java @@ -1,23 +1,22 @@ 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; 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; 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; import top.fpsmaster.utils.render.Render2DUtils; +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<>(); @@ -26,26 +25,27 @@ 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; - content = new ColorAnimation(mod.isEnabled() ? FPSMaster.theme.getModuleEnabled() : FPSMaster.theme.getModuleDisabled()); - 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)); - } + 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(module, (BooleanSetting) setting)); + } else if (setting instanceof ModeSetting) { + settingsRenderers.add(new ModeSettingRender(module, (ModeSetting) setting)); + } else if (setting instanceof TextSetting) { + settingsRenderers.add(new TextSettingRender(module, (TextSetting) setting)); + } else if (setting instanceof NumberSetting) { + settingsRenderers.add(new NumberSettingRender(module, (NumberSetting) setting)); + } else if (setting instanceof ColorSetting) { + settingsRenderers.add(new ColorSettingRender(module, (ColorSetting) setting)); + } else if (setting instanceof BindSetting) { + settingsRenderers.add(new BindSettingRender(module, (BindSetting) setting)); + } else if(setting instanceof MultipleItemSetting) { + settingsRenderers.add(new MultipleItemSettingRender(module,(MultipleItemSetting)setting)); } }); } @@ -57,34 +57,61 @@ 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(), FPSMaster.theme.getModuleEnabled(), 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); - background.start(background.getColor(), FPSMaster.theme.getModuleDisabled(), 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); } - Render2DUtils.drawOptimizedRoundedRect( - x + 4.5f, - y - 0.5f, - width - 9, - settingHeight + 38f, - FPSMaster.theme.getModuleEnabled() + Render2DUtils.drawImage( + new ResourceLocation("client/gui/settings/window/module.png"), + x + 5, + y, + width - 10, + 40, + -1 ); + GlStateManager.disableBlend(); + Render2DUtils.drawOptimizedRoundedRect( x + 5, - y, + y + 40, width - 10, - settingHeight + 37f, - FPSMaster.theme.getModuleDisabled().getRGB() + settingHeight, + 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) +// ); + + Render2DUtils.drawImage( + new ResourceLocation("client/gui/settings/window/option.png"), + x + width - 40, + y + 16, + 21, + 10, + option.getColor() ); - Render2DUtils.drawOptimizedRoundedBorderRect( - x + 5, y, width - 10, 37f, 0.5f, background.getColor(), Render2DUtils.reAlpha( - FPSMaster.theme.getModuleBorder(), (int) border) + + 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"), @@ -124,7 +151,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 e1c4791a..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,10 +7,10 @@ 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; +import java.awt.*; import java.util.Locale; public class BindSettingRender extends SettingRender { @@ -25,9 +25,9 @@ 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.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)) { @@ -36,15 +36,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()); + s16b.drawString(keyName, x + 18 + fw, y + 2, new Color(234, 234, 234).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; } @@ -54,10 +54,10 @@ 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 + 12 + fw, + x + 25 + fw, y, 10f + s16b.getStringWidth(keyName), 12f, @@ -73,7 +73,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/click/modules/impl/BooleanSettingRender.java b/shared/java/top/fpsmaster/ui/click/modules/impl/BooleanSettingRender.java index 2946cada..94d0b9cc 100644 --- a/shared/java/top/fpsmaster/ui/click/modules/impl/BooleanSettingRender.java +++ b/shared/java/top/fpsmaster/ui/click/modules/impl/BooleanSettingRender.java @@ -4,17 +4,16 @@ 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 { // 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); @@ -25,14 +24,14 @@ 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( 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 a13b1d2b..35ff07f7 100644 --- a/shared/java/top/fpsmaster/ui/click/modules/impl/ColorSettingRender.java +++ b/shared/java/top/fpsmaster/ui/click/modules/impl/ColorSettingRender.java @@ -9,10 +9,11 @@ import top.fpsmaster.ui.click.MainPanel; import top.fpsmaster.ui.click.modules.SettingRender; import top.fpsmaster.utils.math.animation.AnimationUtils; -import top.fpsmaster.utils.render.shader.GradientUtils; +import top.fpsmaster.utils.os.OSUtil; 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; @@ -34,32 +35,41 @@ 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) { - // 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) + ) + ); + }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; float brightness = customColor.brightness; @@ -110,9 +120,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"), @@ -151,7 +163,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/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/click/modules/impl/NumberSettingRender.java b/shared/java/top/fpsmaster/ui/click/modules/impl/NumberSettingRender.java index def1029f..b4c485e6 100644 --- a/shared/java/top/fpsmaster/ui/click/modules/impl/NumberSettingRender.java +++ b/shared/java/top/fpsmaster/ui/click/modules/impl/NumberSettingRender.java @@ -9,12 +9,12 @@ 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 { // animation private float aWidth = 0f; - private boolean dragging = false; public NumberSettingRender(Module mod, NumberSetting setting) { super(setting); @@ -25,17 +25,17 @@ 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, 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, 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)) { @@ -53,12 +53,11 @@ 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")) { MainPanel.dragLock = mod.name + setting.name + 4; - dragging = true; } } } 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..a3bd7b9e 100644 --- a/shared/java/top/fpsmaster/ui/click/modules/impl/TextSettingRender.java +++ b/shared/java/top/fpsmaster/ui/click/modules/impl/TextSettingRender.java @@ -3,15 +3,15 @@ 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 { - private TextField inputBox; + private final TextField inputBox; public TextSettingRender(Module mod, TextSetting setting) { super(setting); @@ -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 8f3fc779..d021e1a0 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; @@ -15,13 +17,13 @@ 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; -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 { @@ -32,17 +34,21 @@ 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 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 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"; @@ -50,6 +56,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); @@ -59,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); } } @@ -76,10 +82,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(); } } } @@ -91,15 +100,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); @@ -117,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(); @@ -143,12 +156,12 @@ 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) { 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; } @@ -174,7 +187,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; @@ -182,19 +195,19 @@ 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(); } 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); 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, () -> { @@ -203,34 +216,29 @@ 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()); - } 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()); - } - dY.updateAndGet(v -> new Float((float) (v + 40f))); - musicHeight.updateAndGet(v -> new Float((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()); }); } 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); // 搜索 - inputBox.render(x + 5, y + 6, 80f, 16f, mouseX, mouseY); + inputBox.drawTextBox(x + 5, y + 8, 80f, 16f); // 分页 int xOffset = 0; @@ -238,14 +246,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 + 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, 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 + 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, FPSMaster.theme.getTextColorDescription().getRGB()); + FPSMaster.fontManager.s16.drawString(FPSMaster.i18n.get(page), x + 95 + xOffset, y + 12, -1); } xOffset += stringWidth + 10; } @@ -257,18 +265,18 @@ 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); - 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; @@ -280,18 +288,18 @@ 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, 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, 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.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.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, 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, 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); @@ -300,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(); @@ -308,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"); @@ -327,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) { @@ -354,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) { @@ -363,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) { @@ -385,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, "无法保存二维码图片"); + } }); } @@ -397,12 +417,12 @@ 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(); searchThread = null; } } -} \ No newline at end of file +} 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..78aa8c62 --- /dev/null +++ b/shared/java/top/fpsmaster/ui/click/music/NewMusicPanel.java @@ -0,0 +1,456 @@ +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.input.Mouse; +import org.lwjgl.opengl.GL11; +import top.fpsmaster.FPSMaster; +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.math.animation.Animation; +import top.fpsmaster.utils.math.animation.Type; +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 { + + // 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; + 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; + + 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(() -> { + 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); + } + }); + 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); + 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")); + 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(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 { + 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(() -> { + 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; + } + songsContainer.setHeight(sY); + }); + } + 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) { + int opacity; + opacityAnimation.start(0,255,0.2f,Type.EASE_IN_QUAD); + if(!opacityAnimation.isFinished()){ + opacityAnimation.update(); + opacity = (int) opacityAnimation.value; + } else { + opacity = 255; + } + + 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)); + } + + // 操作按钮 + 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)); + + // 音量键 + 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) + 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; + } + + 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; + } + + + 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); + isWaitingLogin = false; + profile = MusicWrapper.getProfile(); + return; + } catch (FileException e) { + ExceptionHandler.handleFileException(e, "无法保存cookies"); + } + } + Thread.sleep(1000); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + } + }); + FPSMaster.async.runnable(() -> { + key = MusicWrapper.getQRKey(); + System.out.println(key); + 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/SearchBox.java b/shared/java/top/fpsmaster/ui/click/music/SearchBox.java deleted file mode 100644 index d776ff55..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.MathUtils; -import top.fpsmaster.utils.math.animation.ColorAnimation; -import top.fpsmaster.utils.render.Render2DUtils; -import java.awt.Color; - -public class SearchBox extends Gui { - private UFontRenderer font; - - private float width; - private float height; - private float xPosition; - private float yPosition; - - private String text = ""; - private int maxStringLength = 1000; - private int cursorCounter; - private boolean enableBackgroundDrawing = true; - private boolean canLoseFocus = true; - private boolean isFocused; - private boolean isEnabled = true; - private int lineScrollOffset = 0; - private int cursorPosition = 0; - private int selectionEnd = 0; - private Color enabledColor; - private Color disabledColor; - - private Predicate validator = Predicates.alwaysTrue(); - private String placeholder = ""; - private 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 = FPSMaster.theme.getTextboxEnabled(); - this.disabledColor = FPSMaster.theme.getTextboxDisabled(); - } - - public SearchBox(String placeholder) { - this.font = FPSMaster.fontManager.s18; - this.placeholder = placeholder; - this.enabledColor = FPSMaster.theme.getTextboxEnabled(); - this.disabledColor = FPSMaster.theme.getTextboxDisabled(); - } - - 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(); - } - - 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(FPSMaster.theme.getTextboxFocus()); - } else { - btnColor.base(FPSMaster.theme.getTextboxHover()); - } - } else { - btnColor.base(enabledColor); - } - 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/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..2d97f34b 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 { @@ -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) { @@ -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/common/TextField.java b/shared/java/top/fpsmaster/ui/common/TextField.java index 3b13f997..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; /** @@ -67,8 +68,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; @@ -105,7 +112,7 @@ public void setText(String text) { this.text = text; } - this.setCursorPositionEnd(); + this.setCursorPositionZero(); } } @@ -138,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); @@ -384,7 +391,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) { @@ -431,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/Component.java b/shared/java/top/fpsmaster/ui/custom/Component.java index 53d545c3..af3bcacb 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; @@ -88,56 +88,60 @@ 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)); - - if (!Mouse.isButtonDown(0)) { - FPSMaster.componentsManager.dragLock = ""; - } - if (Render2DUtils.isHovered(rX, rY, scaledWidth, scaledHeight, mouseX, mouseY) || drag) { - 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, -1); - - if (!Mouse.isButtonDown(0)) return; - - if (!drag && FPSMaster.componentsManager.dragLock.isEmpty()) { - dragX = mouseX - rX; - dragY = mouseY - rY; - FPSMaster.componentsManager.dragLock = mod.name; + 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 = ""; } - - 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); } } 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) { 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; @@ -185,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; } @@ -195,7 +206,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); } @@ -217,9 +228,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(); } } @@ -228,4 +242,9 @@ 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/ComponentsManager.java b/shared/java/top/fpsmaster/ui/custom/ComponentsManager.java index e5f3a013..51aaed75 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 @@ -37,6 +36,8 @@ public void init() { components.add(new CoordsDisplayComponent()); components.add(new ModsListComponent()); components.add(new MiniMapComponent()); + components.add(new SprintComponent()); + components.add(new ItemCountDisplayComponent()); } // Get a component by its class type @@ -52,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 4c867d45..cfc13a46 100644 --- a/shared/java/top/fpsmaster/ui/custom/impl/ArmorDisplayComponent.java +++ b/shared/java/top/fpsmaster/ui/custom/impl/ArmorDisplayComponent.java @@ -3,20 +3,18 @@ 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; import static top.fpsmaster.utils.Utility.mc; public class ArmorDisplayComponent extends Component { - + public ArmorDisplayComponent() { super(ArmorDisplay.class); } @@ -25,13 +23,13 @@ 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); + int x1 = (int) (x + i * (mod.spacing.getValue().intValue() + 18)) - mod.spacing.getValue().intValue(); int y1 = (int) y; - switch (ArmorDisplay.mode.value) { + switch (ArmorDisplay.mode.getValue()) { case 0: itemStack = armorInventory.get(armorInventory.size() - 1 - i); break; @@ -39,58 +37,65 @@ 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; } 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) { + if (ArmorDisplay.mode.getValue() == 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); } } - switch (ArmorDisplay.mode.value) { + 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/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 23184bc9..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 { @@ -18,12 +17,12 @@ 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); - if (((CoordsDisplay) mod).limitDisplay.value) { + if (((CoordsDisplay) mod).limitDisplay.getValue()) { String yStr = getString(); s = String.format("X:%d Y:%d(%s) Z:%d", @@ -41,8 +40,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.getValue().intValue() - (int) ProviderManager.mcProvider.getPlayer().posY; + String yStr; // color if (restHeight < 5) { 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 f98e4425..099e5757 100644 --- a/shared/java/top/fpsmaster/ui/custom/impl/InventoryDisplayComponent.java +++ b/shared/java/top/fpsmaster/ui/custom/impl/InventoryDisplayComponent.java @@ -4,10 +4,10 @@ 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.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; @@ -15,6 +15,7 @@ public class InventoryDisplayComponent extends Component { public InventoryDisplayComponent() { super(InventoryDisplay.class); + allowScale = true; } @Override @@ -25,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++; @@ -35,9 +39,12 @@ 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); mc.getRenderItem().renderItemOverlays(ProviderManager.mcProvider.getFontRenderer(), itemStack, x1, y1); @@ -56,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/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/KeystrokesComponent.java b/shared/java/top/fpsmaster/ui/custom/impl/KeystrokesComponent.java index 5d9523de..c3b836c7 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 { @@ -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) { @@ -57,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/java/top/fpsmaster/ui/custom/impl/LyricsComponent.java b/shared/java/top/fpsmaster/ui/custom/impl/LyricsComponent.java index c2086530..a15d4ef5 100644 --- a/shared/java/top/fpsmaster/ui/custom/impl/LyricsComponent.java +++ b/shared/java/top/fpsmaster/ui/custom/impl/LyricsComponent.java @@ -1,27 +1,31 @@ package top.fpsmaster.ui.custom.impl; -import org.jetbrains.annotations.Nullable; -import top.fpsmaster.FPSMaster; -import top.fpsmaster.font.impl.UFontRenderer; +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; import top.fpsmaster.utils.math.animation.AnimationUtils; +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 { private long duration = 0; - public LyricsComponent() { super(LyricsDisplay.class); x = 0.5f; y = 0.2f; + height = 70f; position = Position.CT; + allowScale = true; } private long fromTimeTick(String timeTick) { @@ -36,16 +40,20 @@ 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()); - y += 10; - AbstractMusic current = MusicPlayer.playList.current(); + if (((LyricsDisplay) mod).scale.getValue()) { + y += 10; + }else{ + y += 5; + } + y += (scale - 1) * 23; + AbstractMusic current = NewMusicPanel.playing; if (current != null && current.lyrics != null) { int curLine = -1; 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()); } @@ -62,26 +70,34 @@ 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 - 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; - if (i == curLine) { - line.animation = (float) AnimationUtils.base(line.animation, 0.0, 0.1f); - line.alpha = (float) AnimationUtils.base(line.alpha, 1.0, 0.1f); + float stringWidth = getStringWidth(20, content); + float xOffset = x + (width - stringWidth) / 2 * scale ; + width = 200f; + + if (this.width < stringWidth + 10 ) { + this.width = stringWidth + 10 ; + } + if (j == curLine) { + 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, i - curLine, 0.1f); - line.alpha = (float) (Math.abs(i - curLine) == 1 ? - AnimationUtils.base(line.alpha, 1.0, 0.1f) : - AnimationUtils.base(line.alpha, 0.0, 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.05f) : + AnimationUtils.base(line.alpha, 0.0, 0.05f)); } - 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 * scale)+ 20, 20,j == curLine); } } } @@ -89,26 +105,49 @@ 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(current) { + line.scaleAnimation.start(1.0,1.3,0.3f,Type.LINEAR); + }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((int) (20 * scale), 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(); + } } + 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()); - 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 0; + 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/ui/custom/impl/MiniMapComponent.java b/shared/java/top/fpsmaster/ui/custom/impl/MiniMapComponent.java index b0fbcf44..df16b69f 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; @@ -17,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/ModsListComponent.java b/shared/java/top/fpsmaster/ui/custom/impl/ModsListComponent.java index f6b2ea0f..19a435c2 100644 --- a/shared/java/top/fpsmaster/ui/custom/impl/ModsListComponent.java +++ b/shared/java/top/fpsmaster/ui/custom/impl/ModsListComponent.java @@ -5,20 +5,20 @@ import top.fpsmaster.features.manager.Category; import top.fpsmaster.features.manager.Module; 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; 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; @@ -31,31 +31,32 @@ 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()) { + 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, new Color(113, 127, 254).getRGB()); 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) -> { - 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()); - 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 ); @@ -64,34 +65,40 @@ 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 textWidth = mod.betterFont.getValue() ? font.getStringWidth(name) : ProviderManager.mcProvider.getFontRenderer().getStringWidth(name); - if (width2 < width) { - width2 = width + 5; + if (maxWidth < textWidth) { + maxWidth = textWidth + 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) { - color = col; + if(modlist.bg.getValue()) { + Render2DUtils.drawRect(x - textWidth - 4, y + modY, textWidth + 4, MODULE_HEIGHT + modlist.spacing.getValue().intValue() , modlist.backgroundColor.getColor()); } - - if (mod.betterFont.value) { - font.drawStringWithShadow(name, x - width - 2, y + modY + 2, color.getRGB()); + Color color = modlist.color.getColor(); + if (modlist.rainbow.getValue()) { + color = textColor; + } + //text y position centered offset + int yOffset; + if (mod.betterFont.getValue()) { + 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/MusicComponent.java b/shared/java/top/fpsmaster/ui/custom/impl/MusicComponent.java index 65b3100b..28415fd3 100644 --- a/shared/java/top/fpsmaster/ui/custom/impl/MusicComponent.java +++ b/shared/java/top/fpsmaster/ui/custom/impl/MusicComponent.java @@ -1,17 +1,17 @@ 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; 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; import top.fpsmaster.utils.render.Render2DUtils; -import java.awt.Color; +import java.awt.*; public class MusicComponent extends Component { @@ -25,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; } @@ -33,25 +33,27 @@ 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 - ); - - drawString(18, current.name, x + 40, y + 6, FPSMaster.theme.getTextColorTitle().getRGB()); - drawString(16, current.author, x + 40, y + 18, FPSMaster.theme.getTextColorDescription().getRGB()); + 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()); } @Override 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/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..29223f2e 100644 --- a/shared/java/top/fpsmaster/ui/custom/impl/PotionDisplayComponent.java +++ b/shared/java/top/fpsmaster/ui/custom/impl/PotionDisplayComponent.java @@ -3,36 +3,38 @@ 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.FPSMaster; +import org.lwjgl.opengl.GL11; 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 { public PotionDisplayComponent() { super(PotionDisplay.class); + allowScale = true; } + 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; 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,22 +44,27 @@ 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), - (potion % 8 * 18), - (198 + potion / 8 * 18), + 0, + 0, + (potion % 8 * 18) + 1, + (198 + (float)(potion / 8) * 18) + 1, 16, 16, 256f, 256f ); + GL11.glScalef(1 / scale, 1 / scale, 0); + GL11.glTranslatef(-(int) (x + 8), -(int) (dY + 8), 0); - dY += 36f; + 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 87d75bf6..db9ff037 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; @@ -8,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/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/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..31b12410 --- /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.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); + allowScale = true; + } + + @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/java/top/fpsmaster/ui/custom/impl/TargetHUDComponent.java b/shared/java/top/fpsmaster/ui/custom/impl/TargetHUDComponent.java index 7896c8d4..079c2c2f 100644 --- a/shared/java/top/fpsmaster/ui/custom/impl/TargetHUDComponent.java +++ b/shared/java/top/fpsmaster/ui/custom/impl/TargetHUDComponent.java @@ -1,23 +1,22 @@ 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; +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 { private float animation = 0f; - private float healthWidth = 0f; - private ColorAnimation colorAnimation = new ColorAnimation(); + private float healthPer = 0f; + private final ColorAnimation colorAnimation = new ColorAnimation(); public TargetHUDComponent() { super(TargetDisplay.class); @@ -26,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 @@ -35,42 +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 = ((Entity) target1).getDisplayName().getFormattedText(); - if (name.length() > 12) { - name = name.substring(0, 10) + ".."; + String name = target1.getDisplayName().getFormattedText(); + 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 = ((EntityPlayer) target1).getHealth(); - float maxHealth = ((EntityPlayer) target1).getMaxHealth(); - healthWidth = (float) AnimationUtils.base(healthWidth, (health / maxHealth), 0.1); + float health = target1.getHealth(); + float maxHealth = target1.getMaxHealth(); - // 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/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/DevSpace.java b/shared/java/top/fpsmaster/ui/devspace/DevSpace.java index 266e3933..473904c1 100644 --- a/shared/java/top/fpsmaster/ui/devspace/DevSpace.java +++ b/shared/java/top/fpsmaster/ui/devspace/DevSpace.java @@ -8,10 +8,9 @@ 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; -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.*; @@ -19,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; @@ -165,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); } @@ -258,7 +257,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())); } @@ -280,11 +279,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 +336,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; @@ -432,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/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 11df1291..2ca62754 100644 --- a/shared/java/top/fpsmaster/ui/devspace/map/expressions/FunctionCallExpressionComponent.java +++ b/shared/java/top/fpsmaster/ui/devspace/map/expressions/FunctionCallExpressionComponent.java @@ -1,12 +1,11 @@ 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.ArrayList; import java.util.List; public class FunctionCallExpressionComponent extends ExpressionComponent { @@ -39,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/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 e8c6747f..9865b740 100644 --- a/shared/java/top/fpsmaster/ui/mc/GuiMultiplayer.java +++ b/shared/java/top/fpsmaster/ui/mc/GuiMultiplayer.java @@ -1,10 +1,13 @@ package top.fpsmaster.ui.mc; import com.google.common.collect.Lists; -import net.minecraft.client.gui.*; +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.google.gson.JsonObject; +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; @@ -16,16 +19,18 @@ 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.thread.ClientThreadPool; 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; -import top.fpsmaster.wrapper.ChatFormattingProvider; import java.awt.*; import java.io.File; +import java.io.IOException; import java.util.List; public class GuiMultiplayer extends ScaledGuiScreen { @@ -33,23 +38,29 @@ 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 final List serverListRecommended = Lists.newArrayList(); public final OldServerPinger oldServerPinger = new OldServerPinger(); + private final Gson gson = new GsonBuilder().setPrettyPrinting().create(); + String action = ""; + MathTimer timer = new MathTimer(); + GuiButton join = new GuiButton("加入服务器", () -> { if (selectedServer == null) return; 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) @@ -63,30 +74,41 @@ 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); } }, 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 public void initGui() { super.initGui(); + tab = 0; loadServerList(); serverListInternet.clear(); for (ServerData server : servers) { this.serverListInternet.add(new ServerListEntry(this, server)); } + serverListDisplay.clear(); + serverListDisplay.addAll(serverListInternet); + if (serverListRecommended.isEmpty()) { + FPSMaster.async.runnable(() -> { + 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)))); + }); + } } @Override @@ -135,6 +157,8 @@ public void saveServerList() { } ScrollContainer scrollContainer = new ScrollContainer(); + int tab = 0; + @Override public void render(int mouseX, int mouseY, float partialTicks) { @@ -143,53 +167,48 @@ 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); - - 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); + title.drawCenteredString("多人游戏", guiWidth / 2f, 16, -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()); - int index = 0; - for (ServerListEntry server : serverListInternet) { + 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 && servers.indexOf(selectedServer) == index) { - Render2DUtils.drawOptimizedRoundedRect((width - 340) / 2f, y, 340, 54, new Color(255, 255, 255, 50)); + + if (selectedServer != null && selectedServer == server.getServerData()) { + 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); - index++; + server.drawEntry(0, (int) ((guiWidth - 340) / 2), (int) y, 340, 54, mouseX, mouseY, false); y += 58; } - scrollContainer.setHeight(y - 70 - scrollContainer.getScroll()); + scrollContainer.setHeight(y - 50 - scrollContainer.getScroll()); }); GL11.glDisable(GL11.GL_SCISSOR_TEST); 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); } @@ -219,24 +238,43 @@ public void onClick(int mouseX, int mouseY, int mouseButton) { back.mouseClick(mouseX, mouseY, mouseButton); - int y = 80; + 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((guiWidth - 180) / 2f, 30, 90, 24, mouseX, mouseY)) { + tab = 0; + serverListDisplay.clear(); + serverListDisplay.addAll(serverListInternet); + } else if (Render2DUtils.isHovered((guiWidth) / 2f, 30, 90, 24, mouseX, mouseY)) { + tab = 1; + serverListDisplay.clear(); + serverListDisplay.addAll(serverListRecommended); + } + + float y = 70 + scrollContainer.getScroll(); - int index = 0; - for (ServerListEntry server : serverListInternet) { + 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 (Render2DUtils.isHovered((guiWidth - 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); + } } } - index++; - y += 54; + y += 58; } + } diff --git a/shared/java/top/fpsmaster/ui/mc/ServerListEntry.java b/shared/java/top/fpsmaster/ui/mc/ServerListEntry.java index 111b93bc..d36bbbe7 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(); @@ -100,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; @@ -113,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; @@ -133,11 +129,10 @@ 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; - l = (int) (Minecraft.getSystemTime() / 100L + (long) (slotIndex * 2) & 7L); + l = (int) (Minecraft.getSystemTime() / 100L + (slotIndex * 2L) & 7L); if (l > 4) { l = 8 - l; } @@ -171,6 +166,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); @@ -228,12 +227,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); + logger.error("Invalid icon for server {} ({})", this.server.serverName, this.server.serverIP, throwable); + this.server.setBase64EncodedIconData(null); } finally { bytebuf.release(); bytebuf1.release(); 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..e97ac219 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; @@ -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/account/GuiWaiting.java b/shared/java/top/fpsmaster/ui/screens/account/GuiWaiting.java index 7c296702..fee60173 100644 --- a/shared/java/top/fpsmaster/ui/screens/account/GuiWaiting.java +++ b/shared/java/top/fpsmaster/ui/screens/account/GuiWaiting.java @@ -5,20 +5,23 @@ 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; public class GuiWaiting extends GuiScreen { + public static boolean loggedIn = false; - private boolean isLogged = false; + Thread loginThread = new Thread(MicrosoftLogin::loginViaBrowser); @Override public void initGui() { super.initGui(); - MicrosoftLogin.login(); + if (!loginThread.isAlive()){ + loginThread.start(); + } } @Override @@ -36,22 +39,22 @@ 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() + 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 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 +66,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/ui/screens/mainmenu/MainMenu.java b/shared/java/top/fpsmaster/ui/screens/mainmenu/MainMenu.java index eb68a2c7..ab3b58fc 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,16 +10,13 @@ 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; 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 { @@ -32,40 +28,38 @@ 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 Animation startAnimation = new Animation(); + private static final Animation startAnimation = new Animation(); + private static final Animation backgroundAnimation = new Animation(); 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()); } @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 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 @@ -81,6 +75,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; @@ -94,7 +94,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.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 @@ -104,7 +104,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; } } @@ -114,8 +114,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); } @@ -130,13 +130,21 @@ 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()); } 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/ui/screens/mainmenu/MenuButton.java b/shared/java/top/fpsmaster/ui/screens/mainmenu/MenuButton.java index bc981e57..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; @@ -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/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/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 f6be9e5b..2d939ef8 100644 --- a/shared/java/top/fpsmaster/ui/screens/oobe/impls/Login.java +++ b/shared/java/top/fpsmaster/ui/screens/oobe/impls/Login.java @@ -4,18 +4,21 @@ 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; 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 { @@ -36,28 +39,29 @@ 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()); - if (login.get("code").getAsInt() == 200) { + if (FPSMaster.accountManager != null) { + FPSMaster.accountManager.setUsername(username.getText()); + FPSMaster.accountManager.setToken(login.get("data").getAsJsonObject().get("token").getAsString()); + } + try { if (FPSMaster.accountManager != null) { - FPSMaster.accountManager.setUsername(username.getText()); - FPSMaster.accountManager.setToken(login.get("msg").getAsString()); - } - FileUtils.saveTempValue("token", FPSMaster.accountManager.getToken()); - FPSMaster.INSTANCE.loggedIn = true; - if (isOOBE) { - FPSMaster.oobeScreen.nextScene(); - } else { - Minecraft.getMinecraft().displayGuiScreen(new MainMenu()); + 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 (Exception e) { - e.printStackTrace(); + } catch (AccountException e) { + ExceptionHandler.handle(e, "登录失败"); msg = "未知错误: " + e.getMessage(); msgbox = true; } @@ -69,6 +73,7 @@ public Login(boolean isOOBE) { } else { Minecraft.getMinecraft().displayGuiScreen(new MainMenu()); } + FPSMaster.INSTANCE.loggedIn = false; FPSMaster.configManager.configure.set("username", ""); }); } @@ -77,12 +82,12 @@ 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()); - 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); @@ -120,7 +125,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/Utility.java b/shared/java/top/fpsmaster/utils/Utility.java index f6b7cec4..bd2fa991 100644 --- a/shared/java/top/fpsmaster/utils/Utility.java +++ b/shared/java/top/fpsmaster/utils/Utility.java @@ -4,27 +4,68 @@ import top.fpsmaster.interfaces.ProviderManager; import top.fpsmaster.modules.dev.DevMode; +import java.util.ArrayList; +import java.util.function.BiConsumer; +import java.util.function.Consumer; + public class Utility { public static Minecraft mc = Minecraft.getMinecraft(); + 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)); + } 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) { - if (ProviderManager.mcProvider.getWorld() != null) { - ProviderManager.mcProvider.printChatMessage(ProviderManager.utilityProvider.makeChatComponent("§9[FPSMaster]§r " + msg)); + sendClientNotify(msg); + } + } + + public static void flush() { + for (String message : messages) { + ProviderManager.mcProvider.printChatMessage(ProviderManager.utilityProvider.makeChatComponent(message)); + } + 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/awt/AWTUtils.java b/shared/java/top/fpsmaster/utils/awt/AWTUtils.java index 03eae52c..bec060a2 100644 --- a/shared/java/top/fpsmaster/utils/awt/AWTUtils.java +++ b/shared/java/top/fpsmaster/utils/awt/AWTUtils.java @@ -3,65 +3,63 @@ 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; import java.awt.image.BufferedImage; -import java.io.File; 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); - 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"); } + 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 { + 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()); - width *= 2; - 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); - - location = Minecraft.getMinecraft().getTextureManager() - .getDynamicTextureLocation(radius + "_full", new DynamicTexture(bufferedImage)); - - 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, radius * 2, radius * 2); + graphics2D.fill(roundRectangle); - // 返回生成的纹理 - return generatedFull.get(radius); + Minecraft mc = Minecraft.getMinecraft(); + if (mc == null || mc.getTextureManager() == null) { + return null; + } + + 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; + } finally { + graphics2D.dispose(); + } + }); } public static ResourceLocation[] generateRound(int radius) { if (generated.get(radius) != null) { return generated.get(radius); } + int radius2 = radius * 2; - if (radius <= 0) - radius = 1; + 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/shared/java/top/fpsmaster/utils/awt/GifUtil.java b/shared/java/top/fpsmaster/utils/awt/GifUtil.java index fcbc8391..a4eb6b83 100644 --- a/shared/java/top/fpsmaster/utils/awt/GifUtil.java +++ b/shared/java/top/fpsmaster/utils/awt/GifUtil.java @@ -4,13 +4,17 @@ 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.io.InputStream; +import java.util.ArrayList; import java.util.List; public class GifUtil { @@ -24,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/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/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(); } } diff --git a/shared/java/top/fpsmaster/utils/math/animation/Animation.java b/shared/java/top/fpsmaster/utils/math/animation/Animation.java index 20dd7971..9dbacce9 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; } @@ -80,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; + } } diff --git a/shared/java/top/fpsmaster/utils/math/animation/AnimationUtils.java b/shared/java/top/fpsmaster/utils/math/animation/AnimationUtils.java index 56f9fe4b..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() { @@ -115,4 +113,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/ColorAnimation.java b/shared/java/top/fpsmaster/utils/math/animation/ColorAnimation.java index 4a1e5d9e..b5794e02 100644 --- a/shared/java/top/fpsmaster/utils/math/animation/ColorAnimation.java +++ b/shared/java/top/fpsmaster/utils/math/animation/ColorAnimation.java @@ -1,13 +1,14 @@ 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(); - 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; @@ -24,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() { @@ -69,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/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 } diff --git a/shared/java/top/fpsmaster/utils/os/CryptUtils.java b/shared/java/top/fpsmaster/utils/os/CryptUtils.java index 6b752a3b..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 javax.crypto.Cipher; -import javax.crypto.spec.SecretKeySpec; +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/os/FileUtils.java b/shared/java/top/fpsmaster/utils/os/FileUtils.java index 5cd7a797..01fb3fac 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,16 @@ 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) { + ClientLogger.error("An error occurred while releasing language file: " + file + ".lang"); e.printStackTrace(); } } @@ -139,17 +151,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 +172,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(); } diff --git a/shared/java/top/fpsmaster/utils/os/HttpRequest.java b/shared/java/top/fpsmaster/utils/os/HttpRequest.java index ed99a6b2..327e18eb 100644 --- a/shared/java/top/fpsmaster/utils/os/HttpRequest.java +++ b/shared/java/top/fpsmaster/utils/os/HttpRequest.java @@ -1,115 +1,257 @@ package top.fpsmaster.utils.os; -import org.apache.http.client.HttpClient; +import com.google.gson.Gson; +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.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.HttpClients; +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.message.BasicNameValuePair; +import org.apache.http.util.EntityUtils; import top.fpsmaster.modules.logger.ClientLogger; -import java.io.*; +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; -public class HttpRequest { - private static final HttpClient client = HttpClients.createDefault(); - private static final int TIMEOUT = 15000; +public final class HttpRequest { + // Shared thread-safe HTTP client + private static final CloseableHttpClient HTTP_CLIENT = HttpClients.createDefault(); + // Default timeout settings (15 seconds) + private static final int DEFAULT_TIMEOUT = 15000; - public static String get(String url) { - return getWithCookie(url, ""); - } + // 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 static String getWithCookie(String url, String cookie) { - if (url == null || url.isEmpty()) { - throw new IllegalArgumentException("URL cannot be null or empty"); + public boolean isSuccess() { + return statusCode >= 200 && statusCode < 300; } + } + + private HttpRequest() { + } // Prevent instantiation + public static Gson gson() { + return new GsonBuilder().setPrettyPrinting().disableHtmlEscaping().create(); + } + + // ================== GET Requests ================== // + public static HttpResponseResult get(String url) throws IOException { + return executeRequest(new HttpGet(url), null); + } + + public static HttpResponseResult getWithCookie(String url, String cookie) throws IOException { 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"); + request.setHeader("Cookie", cookie.replace("\n", "")); + return executeRequest(request, null); + } + + public static HttpResponseResult get(String url, Map headers) throws IOException { + return executeRequest(new HttpGet(url), headers); + } - if (!cookie.isEmpty()) { - request.setHeader("Cookie", cookie.replace("\n", "")); + // ================== POST Requests ================== // + public static HttpResponseResult post(String url, String body) throws IOException { + return post(url, body, "application/json"); + } + + public static HttpResponseResult postJson(String url, JsonObject json) throws IOException { + return post(url, json.toString(), "application/json"); + } + + public static HttpResponseResult postJson(String url, JsonObject json, Map headers) throws IOException { + return post(url, json.toString(), "application/json", headers); + } + + public static HttpResponseResult postForm(String url, Map params) throws IOException { + 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); + } - 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()); + 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); + } + + 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); + } + if (body != null) { + StringEntity entity = new StringEntity(body, StandardCharsets.UTF_8); + entity.setContentType(contentType); + request.setEntity(entity); } - return ""; + 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(); + // ================== File Download ================== // + public static boolean downloadFile(String url, String filepath) { + try (InputStream is = HTTP_CLIENT.execute(new HttpGet(url)).getEntity().getContent(); + FileOutputStream fos = new FileOutputStream(filepath)) { + + byte[] buffer = new byte[8192]; + int bytesRead; + while ((bytesRead = is.read(buffer)) != -1) { + fos.write(buffer, 0, bytesRead); } + return true; } catch (Exception e) { - ClientLogger.error("Failed to download file from " + url + ": " + e.getMessage()); - e.printStackTrace(); + ClientLogger.error("Download failed: " + e.getMessage()); + return false; } } - 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()); - } + 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(); - // Add body - StringEntity entity = new StringEntity(body, StandardCharsets.UTF_8); - request.setEntity(entity); + try (InputStream is = entity.getContent(); + FileOutputStream fos = new FileOutputStream(filepath)) { - try (AutoCloseableHttpResponse httpResponse = new AutoCloseableHttpResponse(client.execute(request)); - BufferedReader reader = new BufferedReader(new InputStreamReader( - httpResponse.getHttpResponse().getEntity().getContent(), StandardCharsets.UTF_8))) { + byte[] buffer = new byte[8192]; + int bytesRead; + long downloadedSize = 0; - // Get the response code - response[0] = String.valueOf(httpResponse.getHttpResponse().getStatusLine().getStatusCode()); + while ((bytesRead = is.read(buffer)) != -1) { + fos.write(buffer, 0, bytesRead); + downloadedSize += bytesRead; - StringBuilder content = new StringBuilder(); - String inputLine; - while ((inputLine = reader.readLine()) != null) { - content.append(inputLine); + // Invoke progress callback if provided + if (callback != null) { + callback.onProgress(downloadedSize, totalSize); + } + } + return true; } - response[1] = content.toString(); + } 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 { + return HTTP_CLIENT.execute(new HttpGet(url)).getEntity().getContent(); + } catch (Exception e) { + ClientLogger.error("Download failed: " + e.getMessage()); + return null; } - return response; } public static void downloadAsync(String url, String filepath, Runnable callback) { new Thread(() -> { - try { - downloadFile(url, filepath); + boolean success = downloadFile(url, filepath); + if (success && callback != null) { callback.run(); - } catch (Exception e) { - e.printStackTrace(); } }).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 + request.setConfig(buildRequestConfig()); + addDefaultHeaders(request); + + // 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) + .setConnectionRequestTimeout(DEFAULT_TIMEOUT) + .setSocketTimeout(DEFAULT_TIMEOUT) + .build(); + } + + 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"); + } + + private static HttpResponseResult handleResponse(HttpResponse response, String url) throws IOException { + int statusCode = response.getStatusLine().getStatusCode(); + HttpEntity entity = response.getEntity(); + + 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/os/OSUtil.java b/shared/java/top/fpsmaster/utils/os/OSUtil.java new file mode 100644 index 00000000..c2213431 --- /dev/null +++ b/shared/java/top/fpsmaster/utils/os/OSUtil.java @@ -0,0 +1,30 @@ +package top.fpsmaster.utils.os; + +public class OSUtil { + + public static boolean supportShader = true; + + 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 supportShader; + } +} 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/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/java/top/fpsmaster/utils/render/Render2DUtils.java b/shared/java/top/fpsmaster/utils/render/Render2DUtils.java index 9af3d786..2745d4c7 100644 --- a/shared/java/top/fpsmaster/utils/render/Render2DUtils.java +++ b/shared/java/top/fpsmaster/utils/render/Render2DUtils.java @@ -14,14 +14,16 @@ 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.features.impl.render.MotionBlur; import top.fpsmaster.interfaces.ProviderManager; import top.fpsmaster.ui.screens.mainmenu.MainMenu; import top.fpsmaster.utils.Utility; 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; import top.fpsmaster.utils.render.shader.RoundedUtil; @@ -30,10 +32,12 @@ import java.awt.*; import java.io.File; import java.io.IOException; +import java.util.ArrayList; 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()); } @@ -53,11 +57,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; @@ -71,9 +75,39 @@ 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); + } + 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); } @@ -100,31 +134,32 @@ 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 drawRect(float x, float y, float width, float height, Color color) { - drawRect(x, y, width, height, color.getRGB()); + 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 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) { - GlStateManager.disableBlend(); - - glEnable(GL_BLEND); - glDisable(GL_TEXTURE_2D); + GlStateManager.enableBlend(); + GlStateManager.disableTexture2D(); + GlStateManager.enableAlpha(); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glEnable(GL_LINE_SMOOTH); glColor(color); @@ -134,23 +169,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(); - - } - - 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); + GlStateManager.enableTexture2D(); + GlStateManager.disableBlend(); } public static void drawModalRectWithCustomSizedTexture(float x, float y, float u, float v, float width, float height, float textureWidth, float textureHeight) { @@ -166,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; @@ -177,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() { @@ -209,7 +245,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; @@ -220,7 +256,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; @@ -230,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); @@ -240,6 +289,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); @@ -247,6 +300,8 @@ public static void drawBlurArea(int x, int y, int width, int height, int radius, StencilUtil.uninitStencilBuffer(); } + + // background(shader) public static float animation = 0f; static GLSLSandboxShader shader; static long initTime = System.currentTimeMillis(); @@ -254,47 +309,47 @@ 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; } } 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 { - if (mc.currentScreen instanceof MainMenu) { - animation = (float) AnimationUtils.base(animation, 1.0f, 0.05f); + 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 { + 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)); } } } diff --git a/shared/java/top/fpsmaster/utils/render/ScaledGuiScreen.java b/shared/java/top/fpsmaster/utils/render/ScaledGuiScreen.java index 37eb3bb5..0830a054 100644 --- a/shared/java/top/fpsmaster/utils/render/ScaledGuiScreen.java +++ b/shared/java/top/fpsmaster/utils/render/ScaledGuiScreen.java @@ -1,11 +1,10 @@ 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; -import top.fpsmaster.features.impl.interfaces.ClientSettings; -import java.awt.*; import java.io.IOException; public class ScaledGuiScreen extends GuiScreen { @@ -16,24 +15,34 @@ 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 - protected void mouseClicked(int mouseX, int mouseY, int mouseButton) throws IOException { - super.mouseClicked(mouseX, mouseY, mouseButton); - ScaledResolution sr = new ScaledResolution(mc); + 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 + public void mouseClicked(int mouseX, int mouseY, int mouseButton) throws IOException { + super.mouseClicked(mouseX, mouseY, mouseButton); int realMouseX = mouseX * scaleFactor / 2; int realMouseY = mouseY * scaleFactor / 2; onClick(realMouseX, realMouseY, mouseButton); 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/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)); 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/java/top/fpsmaster/utils/render/shader/KawaseBloom.java b/shared/java/top/fpsmaster/utils/render/shader/KawaseBloom.java index 8a99818a..4d4b16ab 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 { @@ -99,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) { 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..4d722c36 100644 --- a/shared/java/top/fpsmaster/utils/render/shader/RoundedUtil.java +++ b/shared/java/top/fpsmaster/utils/render/shader/RoundedUtil.java @@ -6,14 +6,14 @@ 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; 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) { 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; } diff --git a/shared/java/top/fpsmaster/utils/thirdparty/github/UpdateChecker.java b/shared/java/top/fpsmaster/utils/thirdparty/github/UpdateChecker.java index 56c55d3c..7ab78870 100644 --- a/shared/java/top/fpsmaster/utils/thirdparty/github/UpdateChecker.java +++ b/shared/java/top/fpsmaster/utils/thirdparty/github/UpdateChecker.java @@ -1,15 +1,16 @@ 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() { - 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(); + 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 f1967fa6..318bbab7 100644 --- a/shared/java/top/fpsmaster/utils/thirdparty/microsoft/MicrosoftLogin.java +++ b/shared/java/top/fpsmaster/utils/thirdparty/microsoft/MicrosoftLogin.java @@ -1,218 +1,382 @@ package top.fpsmaster.utils.thirdparty.microsoft; -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; -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.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.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("https://login.live.com/oauth20_token.srf", 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 = new JsonObject().getAsJsonObject("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 = get("https://api.minecraftservices.com/minecraft/profile", 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; + 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.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"); + 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 = buildUrl("https://login.live.com/oauth20_authorize.srf", 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(String url, Map param) { - try (CloseableHttpClient httpClient = HttpClients.createDefault()) { - HttpPost httpPost = new HttpPost(url); - 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).getBody(); + 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).getBody(); + 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).getBody(); + 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).getBody(); + 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 get(String url, Map headers) { - try (CloseableHttpClient httpClient = HttpClients.createDefault()) { - HttpGet httpGet = new HttpGet(url); - 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 buildUrl(String url, Map map) { - StringBuilder sb = new StringBuilder(url); - 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/java/top/fpsmaster/utils/thirdparty/openai/OpenAI.java b/shared/java/top/fpsmaster/utils/thirdparty/openai/OpenAI.java index 8c6e269a..6f14c6c0 100644 --- a/shared/java/top/fpsmaster/utils/thirdparty/openai/OpenAI.java +++ b/shared/java/top/fpsmaster/utils/thirdparty/openai/OpenAI.java @@ -1,9 +1,9 @@ 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; +import org.jetbrains.annotations.NotNull; import top.fpsmaster.FPSMaster; import top.fpsmaster.modules.logger.ClientLogger; import top.fpsmaster.utils.os.HttpRequest; @@ -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).getBody(); } catch (Exception e) { throw new RuntimeException(e); } @@ -54,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); @@ -69,44 +86,24 @@ 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; - try { - text = HttpRequest.sendPostRequest(baseUrl + "/chat/completions", json, hashMap); - } catch (Exception e) { - ClientLogger.error("Translator", e.toString()); - return ""; - } - - return getString(text); + return body; } - 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 +111,7 @@ public static String[] requestClientAI(String prompt, String model, JsonArray me put("model", model); put("prompt", prompt); }} - )[1]; + ).getBody(); if (!sendPostRequest.isEmpty()) { JsonObject json = new JsonParser().parse(sendPostRequest).getAsJsonObject(); diff --git a/shared/java/top/fpsmaster/utils/thirdparty/openai/OpenAIClient.java b/shared/java/top/fpsmaster/utils/thirdparty/openai/OpenAIClient.java index 6b77f8bc..43da1004 100644 --- a/shared/java/top/fpsmaster/utils/thirdparty/openai/OpenAIClient.java +++ b/shared/java/top/fpsmaster/utils/thirdparty/openai/OpenAIClient.java @@ -1,15 +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; @@ -59,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); @@ -72,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; } @@ -144,7 +143,7 @@ public interface ResponseCallback { void onError(Exception e); // 当发生错误时调用 - void onFinish(String string); + void onFinish(String string) throws FileException; } public static class Message { diff --git a/shared/java/top/fpsmaster/utils/thirdparty/rawinput/RawInputMod.java b/shared/java/top/fpsmaster/utils/thirdparty/rawinput/RawInputMod.java index bf98a006..c4c10b95 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; public void start() { try { Minecraft.getMinecraft().mouseHelper = new RawMouseHelper(); - controllers = ControllerEnvironment.getDefaultEnvironment().getControllers(); + String environment; + 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; + } + } } 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(); + } +} 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/java/top/fpsmaster/websocket/client/WsClient.java b/shared/java/top/fpsmaster/websocket/client/WsClient.java index 4fade73d..3dbd6cd0 100644 --- a/shared/java/top/fpsmaster/websocket/client/WsClient.java +++ b/shared/java/top/fpsmaster/websocket/client/WsClient.java @@ -1,16 +1,15 @@ 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.dev.DevMode; 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; @@ -24,9 +23,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")); + 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()); @@ -36,12 +35,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()); } @@ -59,13 +54,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); } } @@ -77,7 +71,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 { @@ -85,4 +79,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/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/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; + } +} 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 00000000..e5e86faa Binary files /dev/null and b/shared/resources/assets/minecraft/client/gui/music.png differ 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 00000000..70c56869 Binary files /dev/null and b/shared/resources/assets/minecraft/client/gui/screen/theme.png differ 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 00000000..960611d9 Binary files /dev/null and b/shared/resources/assets/minecraft/client/gui/settings/window/left.png differ 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 00000000..018921f2 Binary files /dev/null and b/shared/resources/assets/minecraft/client/gui/settings/window/module.png differ 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 00000000..1cc0e52a Binary files /dev/null and b/shared/resources/assets/minecraft/client/gui/settings/window/option.png differ diff --git a/shared/resources/assets/minecraft/client/gui/settings/window/option_circle.png b/shared/resources/assets/minecraft/client/gui/settings/window/option_circle.png new file mode 100644 index 00000000..bbd4bd8f Binary files /dev/null and b/shared/resources/assets/minecraft/client/gui/settings/window/option_circle.png differ 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 00000000..385ee5aa Binary files /dev/null and b/shared/resources/assets/minecraft/client/gui/settings/window/panel.png differ diff --git a/shared/resources/assets/minecraft/client/gui/settings/window/selection.png b/shared/resources/assets/minecraft/client/gui/settings/window/selection.png new file mode 100644 index 00000000..63ef3fef Binary files /dev/null and b/shared/resources/assets/minecraft/client/gui/settings/window/selection.png differ diff --git a/shared/resources/assets/minecraft/client/lang/en_us.lang b/shared/resources/assets/minecraft/client/lang/en_us.lang index 15dba463..05bd34ae 100644 --- a/shared/resources/assets/minecraft/client/lang/en_us.lang +++ b/shared/resources/assets/minecraft/client/lang/en_us.lang @@ -1,163 +1,304 @@ -# 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 +armordisplay.spacing=Spacing + +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 +betterchat.foldmessage=Fold Message + +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 +keystrokes.spacing=Spacing +keystrokes.fontcolor=FontColor +keystrokes.pressedfontcolor=PressedFontColor + +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 +potiondisplay.spacing=Spacing + +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 + +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 + +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 +musicdisplay.fontshadow=Font Shadow + + 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.oldthirdperson=Old Third Person Animation 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 +lyricsdisplay.scale=Play Text Scale +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 +307,248 @@ 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.targethud.fancy=Fancy 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 + +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 + 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 -# Category -category.optimize=Optimization +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 +modslist.spacing=Spacing + +betterscreen=Enhanced UI +betterscreen.desc=Improves vanilla UI visuals +betterscreen.background=Enable Background +betterscreen.backgroundanimation=Background Animation +betterscreen.noflickering=No Flickering + +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 +clientsettings.language=Language +clientsettings.language.chinese=Simplified Chinese +clientsettings.language.english=English + +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 + +customtitles=Custom Titles +customtitles.desc=Change the position of the title +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 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. +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 848f78d1..088dbbad 100644 --- a/shared/resources/assets/minecraft/client/lang/zh_cn.lang +++ b/shared/resources/assets/minecraft/client/lang/zh_cn.lang @@ -1,17 +1,15 @@ # 界面 mainmenu.single=单人游戏 mainmenu.multi=多人游戏 -mainmenu.proxy=网易代理 mainmenu.settings=设置 mainmenu.notlogin=您未登录,点此登录 mainmenu.welcome=欢迎您,%s mainmenu.latest=您使用的是最新版本! mainmenu.failed=获取更新失败! -mainmenu.notlatest=检测到新版本!最新版本:%s,点此更新 +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=下一步 @@ -47,11 +43,10 @@ oobe.done.desc=欢迎使用 oobe.done.start=开始 microsoft.login.title=正在登录微软账号 -microsoft.login.desc=请前往浏览器继续操作 # 功能 armordisplay=护甲显示 -armordisplay.desc=显示护甲信息 +armordisplay.desc=显示玩家的护甲信息 armordisplay.round=背景圆角 armordisplay.backgroundcolor=背景颜色 armordisplay.fontshadow=字体阴影 @@ -62,15 +57,17 @@ armordisplay.mode.simplevertical=垂直简单 armordisplay.mode.vertical=垂直详细 armordisplay.roundradius=圆角半径 armordisplay.background=背景 +armordisplay.spacing=间距 betterchat=聊天框 -betterchat.desc=更好的聊天框 +betterchat.desc=修改聊天框的背景、字体,以及添加动画等 betterchat.color=颜色 betterchat.backgroundcolor=背景颜色 betterchat.fontshadow=字体阴影 betterchat.betterfont=更好的字体 betterchat.roundradius=圆角半径 betterchat.background=背景 +betterchat.foldmessage=折叠消息 combodisplay=连击显示 combodisplay.desc=显示连击数 @@ -83,7 +80,7 @@ combodisplay.roundradius=圆角半径 combodisplay.background=背景 cpsdisplay=点击速度显示 -cpsdisplay.desc=显示点击速度 +cpsdisplay.desc=显示点击速度(CPS) cpsdisplay.textcolor=文字颜色 cpsdisplay.round=背景圆角 cpsdisplay.backgroundcolor=背景颜色 @@ -93,7 +90,7 @@ cpsdisplay.roundradius=圆角半径 cpsdisplay.background=背景 fpsdisplay=帧数显示 -fpsdisplay.desc=显示帧数 +fpsdisplay.desc=显示帧数(FPS) fpsdisplay.textcolor=文字颜色 fpsdisplay.roundradius=圆角半径 fpsdisplay.background=背景 @@ -103,12 +100,13 @@ fpsdisplay.fontshadow=字体阴影 fpsdisplay.betterfont=更好的字体 minimap=小地图 -minimap.desc=显示小地图 +minimap.desc=小地图组件 hotbar=物品栏 hotbar.desc=更好的物品栏 + keystrokes=按键显示 -keystrokes.desc=显示按键 +keystrokes.desc=在屏幕上显示按键情况 keystrokes.textcolor=文字颜色 keystrokes.pressedcolor=按下颜色 keystrokes.round=背景圆角 @@ -117,9 +115,12 @@ keystrokes.fontshadow=字体阴影 keystrokes.betterfont=更好的字体 keystrokes.roundradius=圆角半径 keystrokes.background=背景 +keystrokes.spacing=间距 +keystrokes.fontcolor=字体颜色 +keystrokes.pressedfontcolor=按下字体颜色 potiondisplay=药水显示 -potiondisplay.desc=显示当前的药水效果 +potiondisplay.desc=显示玩家的药水效果 potiondisplay.textcolor=文字颜色 potiondisplay.round=背景圆角 potiondisplay.backgroundcolor=背景颜色 @@ -127,9 +128,10 @@ potiondisplay.fontshadow=字体阴影 potiondisplay.betterfont=更好的字体 potiondisplay.roundradius=圆角半径 potiondisplay.background=背景 +potiondisplay.spacing=间距 pingdisplay=延迟显示 -pingdisplay.desc=显示自己的延迟 +pingdisplay.desc=显示玩家到服务器的延迟(Ping) pingdisplay.textcolor=文字颜色 pingdisplay.round=背景圆角 pingdisplay.backgroundcolor=背景颜色 @@ -139,7 +141,7 @@ pingdisplay.roundradius=圆角半径 pingdisplay.background=背景 reachdisplay=攻击距离显示 -reachdisplay.desc=显示攻击的距离 +reachdisplay.desc=在每次攻击时显示攻击的距离 reachdisplay.round=背景圆角 reachdisplay.backgroundcolor=背景颜色 reachdisplay.fontshadow=字体阴影 @@ -148,9 +150,8 @@ reachdisplay.roundradius=圆角半径 reachdisplay.textcolor=文字颜色 reachdisplay.background=背景 - scoreboard=计分板 -scoreboard.desc=更好的计分板 +scoreboard.desc=自定义计分板的样式 scoreboard.textcolor=文字颜色 scoreboard.score=红字 scoreboard.round=背景圆角 @@ -160,14 +161,13 @@ scoreboard.betterfont=更好的字体 scoreboard.roundradius=圆角半径 scoreboard.background=背景 - performance=性能 performance.desc=优化MC帧数 performance.entitiesoptimize=实体渲染优化 performance.fastcloud=云渲染优化 performance.fastrender=使用快速渲染 -performance.fastload=快速加载 -performance.fpslimit=失焦FPS限制 +performance.fastload=快速加载世界 +performance.fpslimit=限制客户端失去焦点时的帧数 performance.entitylimit=实体限制 performance.ignorestands=忽略盔甲架 performance.particleslimit=粒子限制 @@ -175,9 +175,15 @@ performance.screenshot=截图方式 performance.screenshot.fast=快速 performance.screenshot.vanilla=原版 performance.blur=界面高斯模糊 +performance.fontoptimize=字体优化 +performance.staticparticlecolor=静态粒子颜色 +performance.limitchunks=限制区块加载 +performance.chunkupdatelimit=区块更新限制 +performance.batchmodelrendering=渲染批处理 +performance.lowanimationtick=低动画帧率 fullbright=保持亮度 -fullbright.desc=保持亮度 +fullbright.desc=保持视野明亮 itemphysics=物品物理 itemphysics.desc=给掉落物添加物理效果 @@ -201,14 +207,25 @@ moreparticles.killeffect=击杀效果 motionblur=运动模糊 motionblur.desc=运动模糊 -motionblur.multiplier=运动模糊倍数 +motionblur.strength=运动模糊倍数 motionblur.mode=运动模糊模式 -motionblur.mode.classic=经典 +motionblur.mode.old=经典 motionblur.mode.new=新的 motionblur.fastrender=注意!动态模糊功能与快速渲染并不兼容,我们已为您自动关闭了快速渲染。 sprint=强制疾跑 sprint.desc=保持疾跑 +sprint.togglesprint=保持疾跑 +sprint.betterfont=更好的字体 + +autogg=自动GG +autogg.desc=游戏结束后自动地在发送你自定义的消息 +autogg.servers=服务器列表 +autogg.servers.hypxiel=Hypxiel +autogg.servers.kkcraft=KKCraft +autogg.message=自定义消息 +autogg.autoplay=自动重开 +autogg.delaytoplay=自动重开延迟 musicdisplay=音乐显示 musicdisplay.desc=显示你正在播放的音乐 @@ -218,7 +235,9 @@ musicdisplay.visual=音频可视化颜色 musicdisplay.amplitude=可视化幅度 musicdisplay.roundradius=圆角半径 musicdisplay.round=圆角 +musicdisplay.betterfont=更好的字体 musicdisplay.background=背景 +musicdisplay.fontshadow=字体阴影 oldanimations=旧动画 oldanimations.desc=旧动画 @@ -226,21 +245,36 @@ oldanimations.noshield=不显示盾牌 oldanimations.oldrod=旧鱼竿 oldanimations.oldbow=旧弓 oldanimations.oldswing=旧挥动 +oldanimations.blockswing=格挡挥动 oldanimations.oldblock=旧格挡 oldanimations.olddamage=旧伤害动画 oldanimations.oldusing=旧使用动画 oldanimations.blockhit=格挡挥手 +oldanimations.oldthirdperson=旧第三人称动画 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.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=客户端聊天 irc.desc=与相同客户端的用户聊天 -irc.enable=IRC功能已启用,输入#irc <消息>发送消息 +irc.enable=IRC功能已启用,输入%sirc <消息>发送消息 irc.showmates=显示同客户端用户 hitcolor=击中颜色 @@ -260,29 +294,30 @@ lyricsdisplay.fontshadow=字体阴影 lyricsdisplay.betterfont=更好的字体 lyricsdisplay.roundradius=圆角半径 lyricsdisplay.background=背景 +lyricsdisplay.scale=播放文字缩放 -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=方块高亮 @@ -295,18 +330,19 @@ blockoverlay.throughblock=穿透方块 blockoverlay.width=描边宽度 timechanger=时间修改 -timechanger.desc=修改时间 +timechanger.desc=修改世界时间 timechanger.time=时间 tnttimer=TNT时间显示 tnttimer.desc=显示TNT爆炸的时间 +tnttimer.duration=TNT爆炸时间 hitboxes=碰撞箱 hitboxes.desc=显示碰撞箱 hitboxes.color=颜色 -customfov=视场角 -customfov.desc=自定义视场角 +customfov=自定义视场角 +customfov.desc=修改各个情况下的视场角(FOV) customfov.nospeedfov=没有速度视角变化 customfov.noflyfov=没有飞行视角变化 customfov.nobowfov=没有弓箭视角变化 @@ -315,33 +351,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=字体阴影 @@ -357,9 +380,30 @@ targetdisplay.targetesp.none=不显示 targetdisplay.targethud=目标显示 targetdisplay.targethud.none=不显示 targetdisplay.targethud.simple=简单 +targetdisplay.targethud.fancy=华丽 targetdisplay.espcolor=ESP颜色 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=停止全局的摇晃 @@ -371,11 +415,6 @@ smoothzoom.speed=速度 smoothzoom.zoombind=快捷键 smoothzoom.smoothmouse=鼠标平滑 -protocol=协议 -protocol.desc=花雨庭通信协议 -protocol.bypass=绕过开端检测 -protocol.chestfix=箱子修复 - skinchanger=皮肤修改器 skinchanger.skin=皮肤名称 skinchanger.desc=皮肤修改器 @@ -430,7 +469,8 @@ coordsdisplay.background=背景 modslist=功能列表 modslist.desc=显示开启的功能 -modslist.showlogo=显示客户端标志 +modslist.showtext=显示自定义文本 +modslist.text=自定义文本 modslist.english=显示英文功能名 modslist.color=功能列表颜色 modslist.rainbow=功能列表彩色 @@ -438,6 +478,7 @@ modslist.backgroundcolor=功能列表背景颜色 modslist.betterfont=更好的字体 modslist.roundradius=圆角半径 modslist.background=背景 +modslist.spacing=间距 betterscreen=更好的界面 betterscreen.desc=让原版的部分界面看起来更好 @@ -447,7 +488,6 @@ betterscreen.noflickering=防止闪烁 clientcommand=客户端命令 clientcommand.desc=使用命令执行客户端功能 -clientcommand.prefix=命令前缀 cheatersdetector=作弊者检测 cheatersdetector.desc=检测作弊者并特殊标记 @@ -460,6 +500,11 @@ clientsettings.desc=调整客户端各类设置 clientsettings.clickguikey=设置界面快捷键 clientsettings.fixedscale=固定界面缩放比例 clientsettings.blur=界面组件模糊 +clientsettings.command=客户端命令 +clientsettings.prefix=命令前缀 +clientsettings.language=客户端语言 +clientsettings.language.chinese=简体中文 +clientsettings.language.english=英语 dragonwings=龙翅膀 dragonwings.desc=在自己身上龙翅膀 @@ -473,6 +518,15 @@ directiondisplay.desc=显示一个指南针 damageindicator=伤害指示器 damageindicator.desc=在生物受到伤害时显示伤害数字 +customtitles=自定义标题 +customtitles.desc=修改屏幕中间的标题文字的位置 +customtitles.x=横坐标偏移 +customtitles.y=纵坐标偏移 +customtitles.scale=缩放 + +wavycape=披风飘动 +wavycape.desc=使你的披风随着移动飘动 + # 类别 category.optimize=优化 category.render=视觉 @@ -495,7 +549,9 @@ irc.not_login=§c[IRC] §r§c您未连接到IRC,请报告本问题或检查网 irc.disconnect=§c[IRC] §r§c您已断开连接,请重新连接。 special.under_dev=正在开发中,请等待版本更新 translate.hover=点此翻译 -command.notfound=未找到命令,如果客户端命令影响了您的消息,请关闭实用->客户端命令 功能。 - -# 插件 -plugin_manager.title=插件市场 \ No newline at end of file +command.notfound=未找到命令,如果客户端命令影响了您的消息,请在客户端设置中关闭客户端命令功能。 +blur.fast_render=组件模糊与快速渲染不兼容,如要使用模糊效果,请先在设置中关闭快速渲染。 +blur.performance=组件模糊会极大影响性能,若您的配置较低则不建议开启! +motionblur.fast_render=快速渲染与运动模糊不兼容,已为您自动关闭快速渲染。 +chat.irc=客户端 +chat.mc=原版 \ No newline at end of file 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.); -} 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 00000000..7118b2c8 Binary files /dev/null and b/shared/resources/assets/minecraft/client/textures/mate.png differ 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 00000000..8c65b6ac Binary files /dev/null and b/shared/resources/assets/minecraft/client/textures/modules/autogg.png differ 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 00000000..bf3c0547 Binary files /dev/null and b/shared/resources/assets/minecraft/client/textures/modules/clientsettings.png differ 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 00000000..fe91986a Binary files /dev/null and b/shared/resources/assets/minecraft/client/textures/modules/wavycape.png differ 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/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()); -// } -// } -//} 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 4e7c6748..6273f558 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" @@ -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,8 +113,17 @@ 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") + 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: 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 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") 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) { 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/AbstractResourcePackMixin_DownscaleImages.java b/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/AbstractResourcePackMixin_DownscaleImages.java index 301e09c8..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 @@ -21,24 +21,30 @@ 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; } + // 如果图片尺寸已经小于等于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); } } 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/MixinAbstractClientPlayer.java b/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinAbstractClientPlayer.java index 488723b6..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 @@ -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,21 +7,17 @@ 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 { - private ResourceLocation fpsmasterCape; @Inject(method = "getFovModifier", at = @At("HEAD"), cancellable = true) public void customFov(CallbackInfoReturnable cir) { @@ -43,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); } @@ -65,23 +62,12 @@ 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; + if (event.cape != null) { + cir.setReturnValue(event.cape); } - - - NetworkPlayerInfo networkplayerinfo = this.getPlayerInfo(); - return networkplayerinfo == null ? null : networkplayerinfo.getLocationCape(); - } } 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..04155ad8 --- /dev/null +++ b/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinClientBrandRetriever.java @@ -0,0 +1,20 @@ +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 { + + //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(); +// } +} 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); - } - } 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..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 @@ -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; @@ -7,9 +9,11 @@ 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; +import net.minecraft.entity.item.EntityItemFrame; import net.minecraft.entity.passive.EntityAnimal; import net.minecraft.util.*; import net.minecraftforge.client.ForgeHooksClient; @@ -26,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; @@ -33,21 +38,23 @@ 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) 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) { 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) @@ -77,27 +84,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 +200,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; @@ -262,4 +301,93 @@ 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 = 0; + 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)); + } + + 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(); + } + } + } 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/MixinGuiChat.java b/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinGuiChat.java new file mode 100644 index 00000000..78fae781 --- /dev/null +++ b/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinGuiChat.java @@ -0,0 +1,64 @@ +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.java_websocket.enums.ReadyState; +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.Utility; +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) { + 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 + 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; + } + } + } + } + + + @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) { + if (message.toLowerCase().startsWith("/")) { + Utility.sendClientMessage("\247cIRC不允许命令输入!"); + } else { + FPSMaster.INSTANCE.wsClient.sendMessage(message); + } + } else { + instance.sendChatMessage(message); + } + } +} 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/MixinGuiIngame.java b/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinGuiIngame.java index 5aec71f6..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 @@ -8,18 +8,11 @@ import org.spongepowered.asm.mixin.injection.Inject; 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.Scoreboard; import top.fpsmaster.features.impl.render.Crosshair; @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 cce12bf8..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,12 +1,17 @@ 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; 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.event.events.EventRender2D; +import top.fpsmaster.features.impl.interfaces.CustomTitles; @Mixin(GuiIngameForge.class) public class MixinGuiIngameForge { @@ -14,4 +19,20 @@ public class MixinGuiIngameForge { 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); + } + + @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); + } } 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..2034ea5e --- /dev/null +++ b/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinGuiMultiplayer.java @@ -0,0 +1,24 @@ +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; +import top.fpsmaster.ui.screens.mainmenu.MainMenu; + +@Mixin(GuiMultiplayer.class) +public class MixinGuiMultiplayer { + @Inject(method = "initGui", at = @At("HEAD"), cancellable = true) + public void initGui(CallbackInfo ci) { + // 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(); + } + } +} 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..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()) { @@ -185,14 +188,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()); } } @@ -219,22 +217,20 @@ 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); 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)); @@ -268,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; + } } 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..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 @@ -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 = 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/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 8c88c13b..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 @@ -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; @@ -79,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(); @@ -89,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(); @@ -119,6 +114,115 @@ 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("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); + 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, swingProgress); + this.doBlockTransformations(); + GlStateManager.translate(-0.5, 0.2, 0.0); + } else if (OldAnimations.animationMode.isMode("Luna")) { + this.transformFirstPersonItem(equippedProgress, 0.0F); + this.doBlockTransformations(); + 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(equippedProgress, swingProgress); + this.doBlockTransformations(); + } else if (OldAnimations.animationMode.isMode("Swang")) { + this.transformFirstPersonItem(equippedProgress / 2.0F, swingProgress); + float var15; + 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(equippedProgress / 2.0F, swingProgress); + float var15; + 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(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, swingProgress); + 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(equippedProgress, 0.0F); + this.doBlockTransformations(); + 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(equippedProgress - 0.3F, swingProgress); + this.doBlockTransformations(); + } + } + + /** * @author SuperSkidder * @reason animation @@ -126,13 +230,13 @@ public void renderFireInFirstPerson(CallbackInfo ci) { @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) { @@ -173,13 +277,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; 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); + } } 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..5a7251c8 --- /dev/null +++ b/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinLayerCape.java @@ -0,0 +1,293 @@ +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; +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; + + @Unique + private static final int SEGMENTS = 18; + @Unique + private static final float CAPE_WIDTH = 0.6F; + @Unique + private static final float CAPE_LENGTH = 1.08F; + @Unique + private static final float CAPE_DEPTH = 0.06F; + + @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; + + 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 + 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 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 - 1) * segmentLength; + float yOffsetBottom = (segment) * segmentLength; + + + if (prevMatrix != null) { + renderCapeSegment(buffer, prevMatrix, currentMatrix, yOffsetTop, yOffsetBottom, segment); + } + if (segment == 0) { + renderTopSegment(buffer, currentMatrix); + } + prevMatrix = currentMatrix; + poseStack.popPose(); + } + + poseStack.popPose(); + tessellator.draw(); + } + + @Unique + private void applySegmentTransform(PoseStack poseStack, AbstractClientPlayer player, float partialTicks, int segment) { + poseStack.translate(0.0, 0.0, 0.175); + + // 计算玩家运动差值 + 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); + } + + // 应用风摆效果 + 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 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 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 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 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 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 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 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 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 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 + }; + } + + @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(); + } + + @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 float easeOutSine(float progress) { + return (float) Math.sin((progress * Math.PI) / 2); + } + + @Unique + 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 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/java/top/fpsmaster/forge/mixin/MixinMinecraft.java b/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinMinecraft.java index 7972f9e0..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 @@ -34,7 +34,6 @@ import javax.annotation.Nullable; import java.awt.*; -import java.util.Iterator; import static top.fpsmaster.FPSMaster.getClientTitle; @@ -68,6 +67,10 @@ public abstract class MixinMinecraft implements IMinecraft { @Shadow public PlayerControllerMP playerController; + + @Shadow + boolean running; + @Shadow public abstract void displayGuiScreen(@Nullable GuiScreen guiScreenIn); @@ -160,6 +163,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); @@ -220,14 +246,21 @@ 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 = "runTick", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/Minecraft;dispatchKeypresses()V", shift = At.Shift.AFTER)) public void keyEvent(CallbackInfo ci) { - EventKey key = new EventKey(Keyboard.getEventKey() == 0 ? Keyboard.getEventCharacter() + 256 : Keyboard.getEventKey()); - EventDispatcher.dispatchEvent(key); + if (Keyboard.getEventKeyState() && currentScreen == null){ + EventKey key = new EventKey(Keyboard.getEventKey() == 0 ? Keyboard.getEventCharacter() + 256 : Keyboard.getEventKey()); + EventDispatcher.dispatchEvent(key); + } } @Inject(method = "createDisplay", at = @At(value = "RETURN")) 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/forge/mixin/MixinRender.java b/v1.8.9/src/main/java/top/fpsmaster/forge/mixin/MixinRender.java index b3d15f89..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() { @@ -35,14 +37,12 @@ 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()) { + if (LevelTag.health.getValue()) LevelTag.renderHealth(entityIn, str, x, y, z, maxDistance); - LevelTag.renderName(entityIn, str, x, y, z, maxDistance); - ci.cancel(); - } + LevelTag.renderName(entityIn, str, x, y, z, maxDistance); + ci.cancel(); } @Inject(method = "renderName", at = @At("HEAD"), cancellable = true) 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..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; 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 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..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 @@ -20,17 +20,17 @@ 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.forge.api.IMinecraft; 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 +42,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 +108,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 +136,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 +150,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 +170,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 +178,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 +194,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 +239,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 +261,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 +272,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 +282,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 +297,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 +349,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 +367,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 +381,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 +409,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 +426,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 +434,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 +446,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 +466,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 +543,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 +588,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 +604,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 +633,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 +655,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 +668,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 +679,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 +690,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 +712,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 +724,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 +741,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 +761,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 +792,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) { + while (((IMinecraft) mc).arch$getRunning()) { + 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 +867,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 +884,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 +912,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 +942,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 1d190050..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 @@ -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; + 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")) { 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..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 @@ -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,12 +24,13 @@ 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); + GlStateManager.pushAttrib(); GlStateManager.depthMask(false); GlStateManager.disableTexture2D(); - GlStateManager.disableLighting(); +// GlStateManager.disableLighting(); GlStateManager.disableCull(); - GlStateManager.disableBlend(); - + 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(); @@ -41,9 +43,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); + GlStateManager.popAttrib(); + } } 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..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 @@ -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; @@ -25,9 +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()); @@ -41,7 +36,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)); @@ -49,63 +44,61 @@ 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 = 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)); - } + String s = filterHypixelIllegalCharacters(ScorePlayerTeam.formatPlayerName(scoreteam, score.getPlayerName()) + ": " + TextFormattingProvider.getRed() + score.getScorePoints()); + i = (int) Math.max(i, scoreboardComponent.getStringWidth(16, s)); } i += 6; - int height1 = 10; - float l1 = x; + int height1 = (int) scoreboardComponent.getStringHeight(16) + 2; 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()); - if (mod.betterFont.getValue()) { - scoreboardComponent.drawString(16, s3, (int) (l1 + 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); - } - } - if (mod.betterFont.getValue()) { - scoreboardComponent.drawString(16, s1, ((int) l1) + 2, (int) (y + h - k), -1); - } else { - ProviderManager.mcProvider.getFontRenderer().drawStringWithShadow(s1, ((int) l1) + 2, (int) (y + h - k), -1); + 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) * scoreboardComponent.scale), 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, l1 + 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); - } + scoreboardComponent.drawString(16, s2, x + (i - 2 - scoreboardComponent.getStringWidth(16, s2)) * scoreboardComponent.scale, y + k * scoreboardComponent.scale, -1); } } return new float[]{i, h}; } 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(); + } } diff --git a/v1.8.9/src/main/java/top/fpsmaster/wrapper/packets/SPacketChatProvider.java b/v1.8.9/src/main/java/top/fpsmaster/wrapper/packets/SPacketChatProvider.java index 15689360..f63dc01d 100644 --- a/v1.8.9/src/main/java/top/fpsmaster/wrapper/packets/SPacketChatProvider.java +++ b/v1.8.9/src/main/java/top/fpsmaster/wrapper/packets/SPacketChatProvider.java @@ -2,10 +2,10 @@ import net.minecraft.event.ClickEvent; import net.minecraft.event.HoverEvent; -import net.minecraft.network.Packet; import net.minecraft.network.play.server.S02PacketChat; import net.minecraft.util.ChatComponentText; import net.minecraft.util.ChatStyle; +import net.minecraft.util.IChatComponent; import org.jetbrains.annotations.NotNull; import top.fpsmaster.FPSMaster; import top.fpsmaster.interfaces.packets.IPacketChat; @@ -18,14 +18,20 @@ public boolean isPacket(@NotNull Object p) { } @NotNull + @Override public String getUnformattedText(@NotNull Object p){ - return ((S02PacketChat) p).getChatComponent().getUnformattedText(); + return getChatComponent(p).getUnformattedText(); } - + @NotNull + @Override + public IChatComponent getChatComponent(@NotNull Object p){ + return ((S02PacketChat) p).getChatComponent(); + } + @Override public int getType(@NotNull Object p){ return ((S02PacketChat) p).getType(); } - + @Override public void appendTranslation(@NotNull Object p){ String unformattedText = getUnformattedText(p); if (!unformattedText.endsWith(" [T]") && unformattedText.length() > 5) { 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; } 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 00000000..673ac21e Binary files /dev/null and b/v1.8.9/src/main/resources/assets/fpsmaster/textures/icon.png differ diff --git a/v1.8.9/src/main/resources/mcmod.info b/v1.8.9/src/main/resources/mcmod.info index 377e90b7..26b10473 100644 --- a/v1.8.9/src/main/resources/mcmod.info +++ b/v1.8.9/src/main/resources/mcmod.info @@ -11,7 +11,7 @@ "SuperSkidder" ], "credits": "", - "logoFile": "", + "logoFile": "assets/fpsmaster/textures/icon.png", "screenshots": [], "dependencies": [] } diff --git a/v1.8.9/src/main/resources/mixins.fpsmaster.json b/v1.8.9/src/main/resources/mixins.fpsmaster.json index 07bdac2b..29860d84 100644 --- a/v1.8.9/src/main/resources/mixins.fpsmaster.json +++ b/v1.8.9/src/main/resources/mixins.fpsmaster.json @@ -22,9 +22,11 @@ "MixinEntityPlayerSP", "MixinEntityRenderer", "MixinFontRender", + "MixinGuiChat", "MixinGuiContainer", "MixinGuiIngame", "MixinGuiIngameForge", + "MixinGuiMultiplayer", "MixinGuiNewChat", "MixinGuiPlayerOverlay", "MixinGuiScreen", @@ -32,6 +34,8 @@ "MixinItemRenderer", "MixinKeybinding", "MixinLayerArmorBase", + "MixinLayerCape", + "MixinLayerHeldItem", "MixinMainMenu", "MixinMinecraft", "MixinNetworkPlayerInfo", @@ -41,6 +45,7 @@ "MixinRenderManager", "MixinRenderTNTPrimed", "MixinServerSelectionList", + "MixinShaderGroup", "WorldClientMixin_AnimationTick", "accessor.FontRendererAccessor", "accessor.GlStateManagerAccessor",