├── .github ├── ISSUE_TEMPLATE │ ├── bug_report.yml │ ├── feature_request.yml │ └── todo.yml └── workflows │ └── build.yml ├── .gitignore ├── LICENSE ├── README.md ├── README_cn.md ├── build.gradle ├── docs └── pics │ ├── ender.png │ ├── inv.png │ ├── menu_en.png │ └── menu_zh.png ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── settings.gradle ├── settings.json ├── src └── main │ ├── java │ └── dev │ │ └── dubhe │ │ └── gugle │ │ └── carpet │ │ ├── GcaExtension.java │ │ ├── GcaSetting.java │ │ ├── GcaValidators.java │ │ ├── api │ │ ├── menu │ │ │ ├── CustomMenu.java │ │ │ └── control │ │ │ │ ├── AutoResetButton.java │ │ │ │ ├── Button.java │ │ │ │ ├── ButtonList.java │ │ │ │ ├── CheckList.java │ │ │ │ └── RadioList.java │ │ └── tools │ │ │ ├── package-info.java │ │ │ └── text │ │ │ ├── Color.java │ │ │ └── ComponentTranslate.java │ │ ├── commands │ │ ├── BlistCommand.java │ │ ├── BotCommand.java │ │ ├── HereCommand.java │ │ ├── LocCommand.java │ │ ├── SopCommand.java │ │ ├── TodoCommand.java │ │ ├── WhereisCommand.java │ │ └── WlistCommand.java │ │ ├── mixin │ │ ├── APAccessor.java │ │ ├── AbstractContainerMenuAccessor.java │ │ ├── AbstractContainerMenuMixin.java │ │ ├── ActionAccessor.java │ │ ├── AxeItemMixin.java │ │ ├── ChestMenuMixin.java │ │ ├── CommandsMixin.java │ │ ├── EntityInvoker.java │ │ ├── EntityTypeMixin.java │ │ ├── FenceGateBlockMixin.java │ │ ├── FishingHookMixin.java │ │ ├── ItemFrameMixin.java │ │ ├── ItemStackMixin.java │ │ ├── NaturalSpawnerMixin.java │ │ ├── Network.java │ │ ├── PlayerAccessor.java │ │ ├── PlayerCommandMixin.java │ │ ├── PlayerMixin.java │ │ ├── ServerGamePacketListenerImplMixin.java │ │ ├── ServerLevelMixin.java │ │ ├── ServerPlaceRecipeMixin.java │ │ ├── ServerPlayerMixin.java │ │ ├── SignBlockMixin.java │ │ ├── SlotMixin.java │ │ ├── TransferCommandMixin.java │ │ └── WanderingTraderMixin.java │ │ └── tools │ │ ├── ClientUtils.java │ │ ├── ComponentUtils.java │ │ ├── FastPingFriend.java │ │ ├── FilesUtil.java │ │ ├── IdGenerator.java │ │ ├── InventoryUtil.java │ │ ├── ModCommands.java │ │ ├── PosUtils.java │ │ ├── ResourceLocationSerializer.java │ │ ├── SettingUtils.java │ │ ├── SimpleInGameCalculator.java │ │ ├── TriConsumer.java │ │ ├── WelcomeMessage.java │ │ ├── player │ │ ├── FakePlayerAutoFish.java │ │ ├── FakePlayerAutoReplaceTool.java │ │ ├── FakePlayerAutoReplenishment.java │ │ ├── FakePlayerResident.java │ │ ├── FakePlayerSerializer.java │ │ ├── IClientMenuTick.java │ │ ├── IGcaPlayer.java │ │ ├── ISlotIcon.java │ │ ├── PlayerContainer.java │ │ ├── PlayerEnderChestContainer.java │ │ ├── PlayerInventoryContainer.java │ │ └── PlayerInventoryMenu.java │ │ └── serializer │ │ ├── ChatFormattingSerializer.java │ │ └── DimTypeSerializer.java │ └── resources │ ├── assets │ └── gca │ │ ├── icon.png │ │ └── lang │ │ ├── en_us.json │ │ ├── zh_cn.json │ │ └── zh_tw.json │ ├── fabric.mod.json │ └── gca.mixins.json └── versions ├── 1.20.1 ├── build.gradle ├── gca.accesswidener └── gradle.properties ├── 1.21.1 ├── gca.accesswidener └── gradle.properties ├── 1.21.2 ├── gca.accesswidener └── gradle.properties ├── 1.21.3 ├── gca.accesswidener └── gradle.properties ├── 1.21.4 ├── gca.accesswidener └── gradle.properties ├── 1.21.5 ├── gca.accesswidener └── gradle.properties └── mainProject /.github/ISSUE_TEMPLATE/bug_report.yml: -------------------------------------------------------------------------------- 1 | name: Bug Report - Bug反馈 2 | description: Create a report to help us improve. - 反馈问题,帮助我们改进 3 | title: "[Bug] " 4 | labels: 5 | - 🐛 bug 6 | 7 | body: 8 | - type: markdown 9 | attributes: 10 | value: | 11 | Before filling in this `issue`, please make sure that there are no similar or duplicate `issues` that have been opened. 12 | 填写此 `issue` 前,请先确认已经开启的 `issue` 没有类似或重复的 `issue`。 13 | 14 | - type: dropdown 15 | id: system 16 | attributes: 17 | label: OS Version - 操作系统 18 | options: 19 | - Linux 20 | - Windows 21 | - MacOS 22 | validations: 23 | required: true 24 | 25 | - type: input 26 | id: mc_version 27 | attributes: 28 | label: Minecraft Version Details - Minecraft 版本信息 29 | description: | 30 | What version of Minecraft do you use? 31 | 你使用的 Minecraft 版本是什么 32 | placeholder: Minecraft version 33 | validations: 34 | required: true 35 | 36 | - type: input 37 | id: version 38 | attributes: 39 | label: Version Details - 版本信息 40 | description: | 41 | What version of Mod do you use? 42 | 你使用的 Mod 版本是什么 43 | placeholder: Mod version 44 | validations: 45 | required: true 46 | 47 | - type: textarea 48 | id: exist 49 | attributes: 50 | label: Existing behavior - 现有行为 51 | description: | 52 | Please describe the problem you have encountered carefully. 53 | 请仔细描述你所遇到的问题。 54 | validations: 55 | required: true 56 | 57 | - type: textarea 58 | id: expect 59 | attributes: 60 | label: Expected behavior - 预期行为 61 | description: | 62 | Please describe in detail the results you wish to achieve. 63 | 请仔细描述你要得到的结果。 64 | validations: 65 | required: true 66 | 67 | - type: textarea 68 | id: reproduce 69 | attributes: 70 | label: To Reproduce - 复现问题 71 | description: | 72 | How do you trigger this bug? Please walk us through it step by step. 73 | 这个bug是怎么触发的?请详细告诉我们是怎样出现这个情况的。 74 | validations: 75 | required: false 76 | 77 | - type: checkboxes 78 | id: know 79 | attributes: 80 | label: This issue is unique - 这个issue是唯一的 81 | options: 82 | - label: I have searched the issue tracker and did not find an issue describing my bug. - 我已经搜索问题追踪器并且没有发现相同的 issue。 83 | required: true 84 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.yml: -------------------------------------------------------------------------------- 1 | name: Feature request - 功能请求 2 | description: Suggest an idea for this project - 为这个项目推荐一个新想法 3 | title: "[Feature] " 4 | labels: 5 | - 🪁 enhancement 6 | 7 | body: 8 | - type: markdown 9 | attributes: 10 | value: | 11 | Before filling in this `issue`, please make sure that there are no similar or duplicate `issues` that have been opened. 12 | 填写此 `issue` 前,请先确认已经开启的 `issue` 没有类似或重复的 `issue`。 13 | 14 | - type: textarea 15 | attributes: 16 | label: What new features do you want? - 你想要什么新功能? 17 | description: | 18 | What new feature or change you want? How it improves? Please tell us the requirements is with a clear and detailed description, put your screenshots if possible. 19 | 你想要什么新功能或者什么改变?这会带来什么提升?请清晰而详细地描述你的需求,如果可以的话最好附带截图。 20 | validations: 21 | required: true 22 | 23 | - type: checkboxes 24 | id: know 25 | attributes: 26 | label: This issue is unique - 这个issue是唯一的 27 | options: 28 | - label: I have searched the issue tracker and did not find an issue describing my bug. - 我已经搜索问题追踪器并且没有发现相同的 issue。 29 | required: true 30 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/todo.yml: -------------------------------------------------------------------------------- 1 | name: TODO 2 | description: Add a to-do list for a project - 添加一个项目的待做事项 3 | title: "[TODO] " 4 | labels: 5 | - 📋️ TODO 6 | 7 | body: 8 | - type: markdown 9 | attributes: 10 | value: | 11 | 这是一个项目内部使用的 `issue` 模板,请不要使用这个模板! 12 | This is an internal `issue` template for a project, please do not use this template! 13 | 14 | - type: input 15 | attributes: 16 | label: Matters to be added to TODO - 将要加入TODO的事项 17 | validations: 18 | required: true 19 | 20 | - type: textarea 21 | attributes: 22 | label: Describe what this TODO will do - 描述这个TODO要做的事情 23 | validations: 24 | required: false 25 | -------------------------------------------------------------------------------- /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | name: Mod Build 2 | 3 | on: 4 | workflow_dispatch: 5 | push: 6 | branches: 7 | - releases/** 8 | paths: 9 | - src/** 10 | - versions/** 11 | - build.gradle 12 | - gradle.properties 13 | - settings.gradle 14 | 15 | jobs: 16 | build: 17 | strategy: 18 | matrix: 19 | os: [ ubuntu-latest ] 20 | runs-on: ${{ matrix.os }} 21 | env: 22 | CI_BUILD: true 23 | PR_BUILD: false 24 | steps: 25 | - name: checkout 26 | uses: actions/checkout@v4 27 | 28 | - name: Setup Java 21 29 | uses: actions/setup-java@v3.6.0 30 | with: 31 | distribution: zulu 32 | java-version: 21 33 | 34 | - name: validate gradle wrapper 35 | uses: gradle/actions/wrapper-validation@v3 36 | 37 | - name: make gradle wrapper executable 38 | if: ${{ runner.os != 'Windows' }} 39 | run: chmod +x ./gradlew 40 | 41 | - name: Setup Gradle 42 | uses: gradle/actions/setup-gradle@v3 43 | 44 | - name: Build 45 | run: ./gradlew build 46 | 47 | - run: ./gradlew build publishMods 48 | env: 49 | CURSEFORGE_TOKEN: ${{ secrets.CURSEFORGE_TOKEN }} 50 | MODRINTH_TOKEN: ${{ secrets.MODRINTH_TOKEN }} 51 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # User-specific stuff 2 | .idea/ 3 | 4 | *.iml 5 | *.ipr 6 | *.iws 7 | 8 | # IntelliJ 9 | out/ 10 | # mpeltonen/sbt-idea plugin 11 | .idea_modules/ 12 | 13 | # JIRA plugin 14 | atlassian-ide-plugin.xml 15 | 16 | # Compiled class file 17 | *.class 18 | 19 | # Log file 20 | *.log 21 | 22 | # BlueJ files 23 | *.ctxt 24 | 25 | # Package Files # 26 | *.jar 27 | *.war 28 | *.nar 29 | *.ear 30 | *.zip 31 | *.tar.gz 32 | *.rar 33 | 34 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 35 | hs_err_pid* 36 | 37 | *~ 38 | 39 | # temporary files which can be created if a process still has a handle open of a deleted file 40 | .fuse_hidden* 41 | 42 | # KDE directory preferences 43 | .directory 44 | 45 | # Linux trash folder which might appear on any partition or disk 46 | .Trash-* 47 | 48 | # .nfs files are created when an open file is removed but is still being accessed 49 | .nfs* 50 | 51 | # General 52 | .DS_Store 53 | .AppleDouble 54 | .LSOverride 55 | 56 | # Icon must end with two \r 57 | Icon 58 | 59 | # Thumbnails 60 | ._* 61 | 62 | # Files that might appear in the root of a volume 63 | .DocumentRevisions-V100 64 | .fseventsd 65 | .Spotlight-V100 66 | .TemporaryItems 67 | .Trashes 68 | .VolumeIcon.icns 69 | .com.apple.timemachine.donotpresent 70 | 71 | # Directories potentially created on remote AFP share 72 | .AppleDB 73 | .AppleDesktop 74 | Network Trash Folder 75 | Temporary Items 76 | .apdisk 77 | 78 | # Windows thumbnail cache files 79 | Thumbs.db 80 | Thumbs.db:encryptable 81 | ehthumbs.db 82 | ehthumbs_vista.db 83 | 84 | # Dump file 85 | *.stackdump 86 | 87 | # Folder config file 88 | [Dd]esktop.ini 89 | 90 | # Recycle Bin used on file shares 91 | $RECYCLE.BIN/ 92 | 93 | # Windows Installer files 94 | *.cab 95 | *.msi 96 | *.msix 97 | *.msm 98 | *.msp 99 | 100 | # Windows shortcuts 101 | *.lnk 102 | 103 | .gradle 104 | build/ 105 | 106 | # Ignore Gradle GUI config 107 | gradle-app.setting 108 | 109 | # Cache of project 110 | .gradletasknamecache 111 | 112 | **/build/ 113 | 114 | # Common working directory 115 | run/ 116 | 117 | # Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored) 118 | !gradle-wrapper.jar 119 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2022 Gugle 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Gugle's Carpet Addition [ English | [中文](README_cn.md) ] 2 | 3 | [![Development Builds](https://github.com/Gu-ZT/gugle-carpet-addition/workflows/Build%20Mod/badge.svg)](https://github.com/Gu-ZT/gugle-carpet-addition/actions/workflows/ci.yml) 4 | [![CurseForge downloads](http://cf.way2muchnoise.eu/full_662867_downloads.svg)](https://www.curseforge.com/minecraft/mc-mods/guglecarpetaddition) 5 | [![Modrinth downloads](https://img.shields.io/modrinth/dt/gca?color=00AF5C&label=Modrinth%20downloads&logo=modrinth)](https://modrinth.com/mod/gca) 6 | [![GitHub downloads](https://img.shields.io/github/downloads/Gu-ZT/gugle-carpet-addition/total?label=Github%20downloads&logo=github)](https://github.com/Gu-ZT/gugle-carpet-addition/releases) 7 | 8 | ![menu](docs/pics/menu_en.png) 9 | 10 | ## GCA 11 | 12 | #### If you need GCA for Minecraft 1.13, [please click here](https://github.com/Gu-ZT/TISCarpet113WithGCA/releases/latest) 13 | 14 | ### openFakePlayerInventory 15 | 16 | * Use `/carpet openFakePlayerInventory true` Allow player to open the fake player's inventory 17 | 18 | ![menu](docs/pics/inv.png) 19 | 20 | ### openFakePlayerEnderChest 21 | 22 | * Use `/carpet openFakePlayerEnderChest true` Allow player to open the fake player's ender chest 23 | 24 | Sneak to open the fake player's ender chest 25 | 26 | ![menu](docs/pics/ender.png) 27 | 28 | ### fakePlayerResident 29 | 30 | * Use `/carpet fakePlayerResident true` to keep the fake player when exiting the level 31 | 32 | ### fakePlayerAutoReplenishment 33 | 34 | * Use `/carpet fakePlayerAutoReplenishment true` to make fake player to auto replenishment 35 | 36 | ### fakePlayerAutoFish 37 | 38 | * Use `/carpet fakePlayerAutoFish true` to make fake player to auto fish 39 | 40 | ### fakePlayerAutoReplaceTool 41 | 42 | * Use `/carpet fakePlayerAutoReplaceTool true` to make fake player to auto replace tool 43 | 44 | ### betterFenceGatePlacement 45 | 46 | * Use `/carpet betterFenceGatePlacement true` to make the placed fence gate have the same block status as the fence gate 47 | you clicked 48 | 49 | ### betterWoodStrip 50 | 51 | * Use `/carpet betterWoodStrip true` make only the axe with "Strip" in its name is allowed to peel logs 52 | 53 | ### betterSignInteraction 54 | 55 | * Use `/carpet betterSignInteraction true` to make the block attached to the sign interact when you right-click it 56 | 57 | ### betterSignEditing 58 | 59 | * Use `/carpet betterSignEditing true` to make it possible to use feather editing sign with "pen" in the name 60 | -------------------------------------------------------------------------------- /README_cn.md: -------------------------------------------------------------------------------- 1 | # Gugle的Carpet附加包 [ [English](README.md) | 中文 ] 2 | 3 | [![Development Builds](https://github.com/Gu-ZT/gugle-carpet-addition/workflows/Build%20Mod/badge.svg)](https://github.com/Gu-ZT/gugle-carpet-addition/actions/workflows/ci.yml) 4 | [![CurseForge downloads](http://cf.way2muchnoise.eu/full_662867_downloads.svg)](https://www.curseforge.com/minecraft/mc-mods/guglecarpetaddition) 5 | [![Modrinth downloads](https://img.shields.io/modrinth/dt/gca?color=00AF5C&label=Modrinth%20downloads&logo=modrinth)](https://modrinth.com/mod/gca) 6 | [![GitHub downloads](https://img.shields.io/github/downloads/Gu-ZT/gugle-carpet-addition/total?label=Github%20downloads&logo=github)](https://github.com/Gu-ZT/gugle-carpet-addition/releases) 7 | ![menu](docs/pics/menu_zh.png) 8 | 9 | ## GCA 10 | 11 | #### 如果你需要Minecraft 1.13版本的GCA, [请点击此处](https://github.com/Gu-ZT/TISCarpet113WithGCA/releases/latest) 12 | 13 | ### 假人背包 14 | 15 | * 使用 `/carpet openFakePlayerInventory true` 允许玩家打开假人背包 16 | 17 | ![menu](docs/pics/inv.png) 18 | 19 | ### 假人末影箱 20 | 21 | * 使用 `/carpet openFakePlayerEnderChest true` 允许玩家打开假人末影箱 22 | 23 | 潜行可以打开假人的末影箱 24 | 25 | ![menu](docs/pics/ender.png) 26 | 27 | ### 假人驻留 28 | 29 | * 使用 `/carpet fakePlayerResident true` 在退出存档时保留假人 30 | 31 | ### 假人补货 32 | 33 | * 使用 `/carpet fakePlayerAutoReplenishment true` 让假人自动补货 34 | 35 | ### 假人钓鱼 36 | 37 | * 使用 `/carpet fakePlayerAutoFish true` 让假人自动钓鱼 38 | 39 | ### 假人切换工具 40 | 41 | * 使用 `/carpet fakePlayerAutoReplaceTool true` 让假人自动切换快损坏的工具 42 | 43 | ### 更好的栅栏门放置 44 | 45 | * 使用 `/carpet betterFenceGatePlacement true` 让放置的栅栏门与你点击的栅栏门拥有相同的方块状态 46 | 47 | ### 更好的原木去皮 48 | 49 | * 使用 `/carpet betterWoodStrip true` 使得仅允许名称中包含“去皮”的斧头对原木去皮 50 | 51 | ### 更好的告示牌交互 52 | 53 | * 使用 `/carpet betterSignInteraction true` 使得右键告示牌时与之附着的方块产生交互 54 | 55 | ### 更好的告示牌编辑 56 | 57 | * 使用 `/carpet betterSignEditing true` 使得允许使用名称中包含“笔”的羽毛编辑告示牌 58 | -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id "fabric-loom" version "1.7-SNAPSHOT" apply false 3 | id "maven-publish" 4 | id "com.replaymod.preprocess" version "88169fcbc9" 5 | } 6 | 7 | preprocess { 8 | def mc1201 = createNode("1.20.1", 1_20_01, "official") 9 | def mc1211 = createNode("1.21.1", 1_21_01, "official") 10 | def mc1212 = createNode("1.21.2", 1_21_02, "official") 11 | def mc1213 = createNode("1.21.3", 1_21_03, "official") 12 | def mc1214 = createNode("1.21.4", 1_21_04, "official") 13 | def mc1215 = createNode("1.21.5", 1_21_05, "official") 14 | 15 | mc1201.link(mc1211, null) 16 | mc1212.link(mc1211, null) 17 | mc1213.link(mc1211, null) 18 | mc1214.link(mc1211, null) 19 | mc1215.link(mc1211, null) 20 | } -------------------------------------------------------------------------------- /docs/pics/ender.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Gu-ZT/gugle-carpet-addition/380966729d8f6698abe6d555ca405099d4a70b11/docs/pics/ender.png -------------------------------------------------------------------------------- /docs/pics/inv.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Gu-ZT/gugle-carpet-addition/380966729d8f6698abe6d555ca405099d4a70b11/docs/pics/inv.png -------------------------------------------------------------------------------- /docs/pics/menu_en.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Gu-ZT/gugle-carpet-addition/380966729d8f6698abe6d555ca405099d4a70b11/docs/pics/menu_en.png -------------------------------------------------------------------------------- /docs/pics/menu_zh.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Gu-ZT/gugle-carpet-addition/380966729d8f6698abe6d555ca405099d4a70b11/docs/pics/menu_zh.png -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | org.gradle.jvmargs=-Xmx6G 2 | org.gradle.parallel=true 3 | 4 | mod_id=gca 5 | mod_name=GugleCarpetAddition 6 | mod_version=2.10.0 7 | maven_group=dev.dubhe.gugle 8 | archives_base_name=gugle-carpet-addition 9 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Gu-ZT/gugle-carpet-addition/380966729d8f6698abe6d555ca405099d4a70b11/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.8-bin.zip 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @rem 2 | @rem Copyright 2015 the original author or authors. 3 | @rem 4 | @rem Licensed under the Apache License, Version 2.0 (the "License"); 5 | @rem you may not use this file except in compliance with the License. 6 | @rem You may obtain a copy of the License at 7 | @rem 8 | @rem https://www.apache.org/licenses/LICENSE-2.0 9 | @rem 10 | @rem Unless required by applicable law or agreed to in writing, software 11 | @rem distributed under the License is distributed on an "AS IS" BASIS, 12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | @rem See the License for the specific language governing permissions and 14 | @rem limitations under the License. 15 | @rem 16 | 17 | @if "%DEBUG%" == "" @echo off 18 | @rem ########################################################################## 19 | @rem 20 | @rem Gradle startup script for Windows 21 | @rem 22 | @rem ########################################################################## 23 | 24 | @rem Set local scope for the variables with windows NT shell 25 | if "%OS%"=="Windows_NT" setlocal 26 | 27 | set DIRNAME=%~dp0 28 | if "%DIRNAME%" == "" set DIRNAME=. 29 | set APP_BASE_NAME=%~n0 30 | set APP_HOME=%DIRNAME% 31 | 32 | @rem Resolve any "." and ".." in APP_HOME to make it shorter. 33 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi 34 | 35 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 36 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" 37 | 38 | @rem Find java.exe 39 | if defined JAVA_HOME goto findJavaFromJavaHome 40 | 41 | set JAVA_EXE=java.exe 42 | %JAVA_EXE% -version >NUL 2>&1 43 | if "%ERRORLEVEL%" == "0" goto execute 44 | 45 | echo. 46 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 47 | echo. 48 | echo Please set the JAVA_HOME variable in your environment to match the 49 | echo location of your Java installation. 50 | 51 | goto fail 52 | 53 | :findJavaFromJavaHome 54 | set JAVA_HOME=%JAVA_HOME:"=% 55 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 56 | 57 | if exist "%JAVA_EXE%" goto execute 58 | 59 | echo. 60 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 61 | echo. 62 | echo Please set the JAVA_HOME variable in your environment to match the 63 | echo location of your Java installation. 64 | 65 | goto fail 66 | 67 | :execute 68 | @rem Setup the command line 69 | 70 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 71 | 72 | 73 | @rem Execute Gradle 74 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* 75 | 76 | :end 77 | @rem End local scope for the variables with windows NT shell 78 | if "%ERRORLEVEL%"=="0" goto mainEnd 79 | 80 | :fail 81 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 82 | rem the _cmd.exe /c_ return code! 83 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 84 | exit /b 1 85 | 86 | :mainEnd 87 | if "%OS%"=="Windows_NT" endlocal 88 | 89 | :omega 90 | -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | import groovy.json.JsonSlurper 2 | 3 | pluginManagement { 4 | repositories { 5 | mavenLocal() 6 | mavenCentral() 7 | gradlePluginPortal() 8 | maven { 9 | name = 'Fabric' 10 | url = 'https://maven.fabricmc.net/' 11 | } 12 | maven { 13 | name = 'Jitpack' 14 | url = "https://jitpack.io" 15 | } 16 | resolutionStrategy { 17 | eachPlugin { 18 | switch (requested.id.id) { 19 | case "com.replaymod.preprocess": { 20 | useModule("com.github.Fallen-Breath:preprocessor:${requested.version}") 21 | break 22 | } 23 | } 24 | } 25 | } 26 | } 27 | } 28 | 29 | Map> settings = file("settings.json").withReader { 30 | new JsonSlurper().parse(it) as Map> 31 | } 32 | 33 | for (String version : settings.get("versions")) { 34 | include(":$version") 35 | ProjectDescriptor proj = project(":$version") 36 | proj.setProjectDir(file("versions/$version")) 37 | proj.setBuildFileName("../${settings.versions.get(0)}/build.gradle") 38 | } 39 | -------------------------------------------------------------------------------- /settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "versions": [ 3 | "1.20.1", 4 | "1.21.1", 5 | "1.21.2", 6 | "1.21.3", 7 | "1.21.4", 8 | "1.21.5" 9 | ] 10 | } -------------------------------------------------------------------------------- /src/main/java/dev/dubhe/gugle/carpet/GcaExtension.java: -------------------------------------------------------------------------------- 1 | package dev.dubhe.gugle.carpet; 2 | 3 | import carpet.CarpetExtension; 4 | import carpet.CarpetServer; 5 | import carpet.patches.EntityPlayerMPFake; 6 | import com.google.gson.Gson; 7 | import com.google.gson.GsonBuilder; 8 | import com.google.gson.JsonElement; 9 | import com.google.gson.JsonObject; 10 | import com.mojang.brigadier.CommandDispatcher; 11 | import dev.dubhe.gugle.carpet.api.tools.text.ComponentTranslate; 12 | import dev.dubhe.gugle.carpet.commands.BlistCommand; 13 | import dev.dubhe.gugle.carpet.commands.BotCommand; 14 | import dev.dubhe.gugle.carpet.commands.HereCommand; 15 | import dev.dubhe.gugle.carpet.commands.LocCommand; 16 | import dev.dubhe.gugle.carpet.commands.SopCommand; 17 | import dev.dubhe.gugle.carpet.commands.TodoCommand; 18 | import dev.dubhe.gugle.carpet.commands.WhereisCommand; 19 | import dev.dubhe.gugle.carpet.commands.WlistCommand; 20 | import dev.dubhe.gugle.carpet.tools.ResourceLocationSerializer; 21 | import dev.dubhe.gugle.carpet.tools.WelcomeMessage; 22 | import dev.dubhe.gugle.carpet.tools.player.FakePlayerResident; 23 | import dev.dubhe.gugle.carpet.tools.serializer.ChatFormattingSerializer; 24 | import dev.dubhe.gugle.carpet.tools.serializer.DimTypeSerializer; 25 | import net.fabricmc.api.ModInitializer; 26 | import net.minecraft.ChatFormatting; 27 | import net.minecraft.commands.CommandBuildContext; 28 | import net.minecraft.commands.CommandSourceStack; 29 | import net.minecraft.nbt.CompoundTag; 30 | import net.minecraft.resources.ResourceKey; 31 | import net.minecraft.resources.ResourceLocation; 32 | import net.minecraft.server.MinecraftServer; 33 | import net.minecraft.server.level.ServerPlayer; 34 | import net.minecraft.world.level.storage.LevelResource; 35 | import org.apache.logging.log4j.LogManager; 36 | import org.apache.logging.log4j.Logger; 37 | import org.jetbrains.annotations.NotNull; 38 | 39 | import java.io.BufferedReader; 40 | import java.io.BufferedWriter; 41 | import java.io.File; 42 | import java.io.IOException; 43 | import java.nio.charset.StandardCharsets; 44 | import java.nio.file.Files; 45 | import java.util.ArrayList; 46 | import java.util.HashMap; 47 | import java.util.HashSet; 48 | import java.util.List; 49 | import java.util.Map; 50 | import java.util.function.Consumer; 51 | 52 | public class GcaExtension implements CarpetExtension, ModInitializer { 53 | private static final HashSet RESIDENT_PLAYERS = new HashSet<>(); 54 | public static final Gson GSON = new GsonBuilder() 55 | .setPrettyPrinting() 56 | .registerTypeHierarchyAdapter(ResourceKey.class, new DimTypeSerializer()) 57 | .registerTypeHierarchyAdapter(ResourceLocation.class, new ResourceLocationSerializer()) 58 | .registerTypeHierarchyAdapter(ChatFormatting.class, new ChatFormattingSerializer()) 59 | .registerTypeHierarchyAdapter(WelcomeMessage.MessageData.class, new WelcomeMessage.MessageData.Serializer()) 60 | .create(); 61 | public static String MOD_ID = "gca"; 62 | public static final Logger LOGGER = LogManager.getLogger(MOD_ID); 63 | public static final HashMap> ON_PLAYER_LOGGED_IN = new HashMap<>(); 64 | public static final List> PLAN_FUNCTION = new ArrayList<>(); 65 | 66 | public static @NotNull ResourceLocation id(String path) { 67 | //#if MC>=12100 68 | return ResourceLocation.fromNamespaceAndPath(MOD_ID, path); 69 | //#else 70 | //$$ return new ResourceLocation(MOD_ID, path); 71 | //#endif 72 | } 73 | 74 | @Override 75 | public void onPlayerLoggedIn(@NotNull ServerPlayer player) { 76 | Consumer consumer = ON_PLAYER_LOGGED_IN.remove(player.getGameProfile().getName()); 77 | if (consumer != null) consumer.accept(player); 78 | if (GcaSetting.welcomePlayer) WelcomeMessage.onPlayerLoggedIn(player); 79 | if (player instanceof EntityPlayerMPFake fakePlayer) { 80 | RESIDENT_PLAYERS.add(fakePlayer); 81 | } 82 | } 83 | 84 | @Override 85 | public void onPlayerLoggedOut(ServerPlayer player) { 86 | if (player instanceof EntityPlayerMPFake) { 87 | RESIDENT_PLAYERS.remove(player); 88 | } 89 | } 90 | 91 | @Override 92 | public void onGameStarted() { 93 | CarpetServer.settingsManager.parseSettingsClass(GcaSetting.class); 94 | } 95 | 96 | @Override 97 | public void onServerLoaded(MinecraftServer server) { 98 | BlistCommand.PERMISSION.init(server); 99 | BotCommand.BOT_INFO.init(server); 100 | LocCommand.LOC_POINT.init(server); 101 | TodoCommand.TODO.init(server); 102 | WlistCommand.PERMISSION.init(server); 103 | WelcomeMessage.WELCOME_MESSAGE.init(server); 104 | } 105 | 106 | @Override 107 | public void onServerClosed(MinecraftServer server) { 108 | try { 109 | if (GcaSetting.fakePlayerResident) { 110 | JsonObject fakePlayerList = new JsonObject(); 111 | for (EntityPlayerMPFake player : RESIDENT_PLAYERS) { 112 | if (player.saveWithoutId(new CompoundTag()).contains("gca.NoResident")) { 113 | continue; 114 | } 115 | String username = player.getGameProfile().getName(); 116 | fakePlayerList.add(username, FakePlayerResident.save(player)); 117 | } 118 | File file = server.getWorldPath(LevelResource.ROOT).resolve("fake_player.gca.json").toFile(); 119 | // 文件不需要存在 120 | try (BufferedWriter bfw = Files.newBufferedWriter(file.toPath(), StandardCharsets.UTF_8)) { 121 | bfw.write(GSON.toJson(fakePlayerList)); 122 | } catch (Exception e) { 123 | GcaExtension.LOGGER.error(e.getMessage(), e); 124 | } 125 | } 126 | } finally { 127 | RESIDENT_PLAYERS.clear(); 128 | } 129 | } 130 | 131 | @Override 132 | public void onServerLoadedWorlds(MinecraftServer server) { 133 | if (GcaSetting.fakePlayerResident) { 134 | File file = server.getWorldPath(LevelResource.ROOT).resolve("fake_player.gca.json").toFile(); 135 | if (!file.isFile()) { 136 | return; 137 | } 138 | try (BufferedReader bfr = Files.newBufferedReader(file.toPath(), StandardCharsets.UTF_8)) { 139 | JsonObject fakePlayerList = GSON.fromJson(bfr, JsonObject.class); 140 | for (Map.Entry entry : fakePlayerList.entrySet()) { 141 | FakePlayerResident.load(entry, server); 142 | } 143 | } catch (IOException e) { 144 | GcaExtension.LOGGER.error(e.getMessage(), e); 145 | } 146 | //noinspection ResultOfMethodCallIgnored 147 | file.delete(); 148 | } 149 | } 150 | 151 | @Override 152 | public void registerCommands(CommandDispatcher dispatcher, CommandBuildContext commandBuildContext) { 153 | BotCommand.register(dispatcher); 154 | LocCommand.register(dispatcher); 155 | HereCommand.register(dispatcher); 156 | WhereisCommand.register(dispatcher); 157 | TodoCommand.register(dispatcher); 158 | WlistCommand.register(dispatcher); 159 | BlistCommand.register(dispatcher); 160 | SopCommand.register(dispatcher); 161 | } 162 | 163 | @Override 164 | public Map canHasTranslations(String lang) { 165 | return ComponentTranslate.getTranslations(lang); 166 | } 167 | 168 | @Override 169 | public void onInitialize() { 170 | CarpetServer.manageExtension(this); 171 | } 172 | 173 | public static @NotNull ResourceLocation parseLocation(String string) { 174 | //#if MC>=12100 175 | return ResourceLocation.parse(string); 176 | //#else 177 | //$$ return new ResourceLocation(string); 178 | //#endif 179 | } 180 | } 181 | -------------------------------------------------------------------------------- /src/main/java/dev/dubhe/gugle/carpet/GcaSetting.java: -------------------------------------------------------------------------------- 1 | package dev.dubhe.gugle.carpet; 2 | 3 | import carpet.api.settings.Rule; 4 | import carpet.api.settings.Validators; 5 | 6 | public class GcaSetting { 7 | 8 | public static final String GCA = "GCA"; 9 | public static final String EXPERIMENTAL = "experimental"; 10 | public static final String BOT = "BOT"; 11 | public static final String COMMAND = "command"; 12 | 13 | // 允许玩家打开假人背包 14 | @Rule( 15 | categories = {GCA, BOT} 16 | ) 17 | public static boolean openFakePlayerInventory = false; 18 | 19 | // 允许玩家打开真人背包 20 | @Rule( 21 | options = {"true", "false", "ops", "0", "1", "2", "3", "4"}, 22 | categories = {GCA, EXPERIMENTAL}, 23 | validators = Validators.CommandLevel.class 24 | ) 25 | public static String openRealPlayerInventory = "false"; 26 | 27 | // 允许玩家打开假人末影箱 28 | @Rule( 29 | categories = {GCA, BOT}, 30 | options = {"ender_chest", "true", "false"}, 31 | validators = GcaValidators.EnderChest.class 32 | ) 33 | public static String openFakePlayerEnderChest = "false"; 34 | 35 | // 退出存档时保留假人 36 | @Rule( 37 | categories = {GCA, BOT} 38 | ) 39 | public static boolean fakePlayerResident = false; 40 | 41 | // 退出存档时保留假人动作 42 | @Rule( 43 | categories = {GCA, BOT} 44 | ) 45 | public static boolean fakePlayerReloadAction = false; 46 | 47 | // 让假人自动补货 48 | @Rule( 49 | categories = {GCA, BOT} 50 | ) 51 | public static boolean fakePlayerAutoReplenishment = false; 52 | 53 | // 让假人自动从潜影盒补货 54 | @Rule( 55 | categories = {GCA, BOT} 56 | ) 57 | public static boolean fakePlayerAutoReplenishmentFormShulkerBox = false; 58 | 59 | // 让假人自动钓鱼 60 | @Rule( 61 | categories = {GCA, BOT} 62 | ) 63 | public static boolean fakePlayerAutoFish = false; 64 | 65 | // 让假人自动切换快损坏的工具 66 | @Rule( 67 | categories = {GCA, BOT} 68 | ) 69 | public static boolean fakePlayerAutoReplaceTool = false; 70 | 71 | public static final String fakePlayerNoneName = "#none"; 72 | 73 | // 假人名称前缀 74 | @Rule( 75 | options = {fakePlayerNoneName, "bot_"}, 76 | categories = {GCA, BOT} 77 | ) 78 | public static String fakePlayerPrefixName = fakePlayerNoneName; 79 | 80 | // 假人名称后缀 81 | @Rule( 82 | options = {fakePlayerNoneName, "_fake"}, 83 | categories = {GCA, BOT} 84 | ) 85 | public static String fakePlayerSuffixName = fakePlayerNoneName; 86 | 87 | // 方便快捷的假人管理菜单 88 | @Rule( 89 | categories = {GCA, BOT, COMMAND}, 90 | options = {"ops", "0", "1", "2", "3", "4", "true", "false"}, 91 | validators = Validators.CommandLevel.class 92 | ) 93 | public static String commandBot = "ops"; 94 | 95 | // 待办事项清单 96 | @Rule( 97 | categories = {GCA, COMMAND}, 98 | options = {"ops", "0", "1", "2", "3", "4", "true", "false"}, 99 | validators = Validators.CommandLevel.class 100 | ) 101 | public static String commandTodo = "ops"; 102 | 103 | // 快速发送坐标 104 | @Rule( 105 | categories = {GCA, COMMAND}, 106 | options = {"ops", "0", "1", "2", "3", "4", "true", "false"}, 107 | validators = Validators.CommandLevel.class, 108 | conditions = GcaValidators.CarpetAmsAdditionLoaded.class 109 | ) 110 | public static String commandHere = "ops"; 111 | 112 | // 快速定位玩家 113 | @Rule( 114 | categories = {GCA, COMMAND}, 115 | options = {"ops", "0", "1", "2", "3", "4", "true", "false"}, 116 | validators = Validators.CommandLevel.class 117 | ) 118 | public static String commandWhereis = "ops"; 119 | 120 | // 地标管理菜单 121 | @Rule( 122 | categories = {GCA, COMMAND}, 123 | options = {"ops", "0", "1", "2", "3", "4", "true", "false"}, 124 | validators = Validators.CommandLevel.class 125 | ) 126 | public static String commandLoc = "ops"; 127 | 128 | // 白名单管理 129 | @Rule( 130 | categories = {GCA, COMMAND} 131 | ) 132 | public static boolean commandWlist = false; 133 | 134 | // 封禁名单管理 135 | @Rule( 136 | categories = {GCA, COMMAND} 137 | ) 138 | public static boolean commandBlist = false; 139 | 140 | // 简单获取op 141 | @Rule( 142 | categories = {GCA, COMMAND} 143 | ) 144 | public static boolean commandSop = false; 145 | 146 | // 让放置的栅栏门与你点击的栅栏门拥有相同的方块状态 147 | @Rule( 148 | categories = {GCA} 149 | ) 150 | public static boolean betterFenceGatePlacement = false; 151 | 152 | // 仅允许名称中包含“去皮”的斧头对原木去皮 153 | @Rule( 154 | categories = {GCA} 155 | ) 156 | public static boolean betterWoodStrip = false; 157 | 158 | // 右键告示牌时与之附着的方块产生交互 159 | @Rule( 160 | categories = {GCA} 161 | ) 162 | public static boolean betterSignInteraction = false; 163 | 164 | // 右键包含物品的展示框时与之附着的方块产生交互 165 | @Rule( 166 | categories = {GCA} 167 | ) 168 | public static boolean betterItemFrameInteraction = false; 169 | 170 | // 快速合成时在物品栏保留一份物品 171 | @Rule( 172 | categories = {GCA, EXPERIMENTAL} 173 | ) 174 | public static boolean betterQuickCrafting = false; 175 | 176 | // 简单的游戏内计算器 177 | @Rule( 178 | categories = {GCA} 179 | ) 180 | public static boolean simpleInGameCalculator = false; 181 | 182 | // 快速ping好友 183 | @Rule( 184 | categories = {GCA} 185 | ) 186 | public static boolean fastPingFriend = false; 187 | 188 | // 设置LC值为多少高度时的值 189 | @Rule( 190 | categories = {GCA, EXPERIMENTAL} 191 | ) 192 | public static int qnmdLC = -1; 193 | 194 | // 修复末地水晶同步 195 | @Rule( 196 | categories = {GCA, EXPERIMENTAL} 197 | ) 198 | public static boolean fixedEndCrystalSync = false; 199 | 200 | // 欢迎玩家 201 | @Rule( 202 | categories = {GCA} 203 | ) 204 | public static boolean welcomePlayer = false; 205 | 206 | // 流浪商人生成失败提醒 207 | @Rule( 208 | categories = {GCA, EXPERIMENTAL} 209 | ) 210 | public static boolean wanderingTraderSpawnFailedWarning = false; 211 | 212 | // 流浪商人生成提醒 213 | @Rule( 214 | categories = {GCA, EXPERIMENTAL} 215 | ) 216 | public static boolean wanderingTraderSpawnRemind = false; 217 | 218 | //#if MC>=12100 219 | // 服务器玩家转移命令 220 | @Rule( 221 | categories = {GCA, COMMAND} 222 | ) 223 | //#else 224 | //#endif 225 | public static boolean commandTransfer = false; 226 | } 227 | -------------------------------------------------------------------------------- /src/main/java/dev/dubhe/gugle/carpet/GcaValidators.java: -------------------------------------------------------------------------------- 1 | package dev.dubhe.gugle.carpet; 2 | 3 | import carpet.api.settings.CarpetRule; 4 | import carpet.api.settings.Rule; 5 | import carpet.api.settings.Validator; 6 | import net.fabricmc.loader.api.FabricLoader; 7 | import net.minecraft.commands.CommandSourceStack; 8 | import org.jetbrains.annotations.Nullable; 9 | 10 | import java.util.List; 11 | 12 | public class GcaValidators { 13 | public static final boolean CARPET_AMS_ADDITION = FabricLoader.getInstance().isModLoaded("carpet-ams-addition"); 14 | 15 | public static class EnderChest extends Validator { 16 | public static final List OPTIONS = List.of("true", "false", "ender_chest"); 17 | 18 | @Override 19 | public String validate(@Nullable CommandSourceStack commandSourceStack, CarpetRule carpetRule, String newValue, String userString) { 20 | return !OPTIONS.contains(newValue) ? null : newValue; 21 | } 22 | 23 | public String description() { 24 | return "Can be limited to 'ender_chest' for use EnderChest open only, true/false for open directly/unable"; 25 | } 26 | } 27 | 28 | public static class CarpetAmsAdditionLoaded implements Rule.Condition { 29 | @Override 30 | public boolean shouldRegister() { 31 | return !CARPET_AMS_ADDITION; 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/dev/dubhe/gugle/carpet/api/menu/CustomMenu.java: -------------------------------------------------------------------------------- 1 | package dev.dubhe.gugle.carpet.api.menu; 2 | 3 | import dev.dubhe.gugle.carpet.api.menu.control.Button; 4 | import dev.dubhe.gugle.carpet.api.menu.control.ButtonList; 5 | import net.minecraft.world.Container; 6 | 7 | import java.util.ArrayList; 8 | import java.util.List; 9 | import java.util.Map; 10 | 11 | public abstract class CustomMenu implements Container { 12 | public final List> buttons = new ArrayList<>(); 13 | public final List buttonLists = new ArrayList<>(); 14 | 15 | public void tick() { 16 | this.checkButton(); 17 | } 18 | 19 | public void addButton(int slot, Button button) { 20 | if (getContainerSize() < (slot + 1)) { 21 | return; 22 | } 23 | buttons.add(Map.entry(slot, button)); 24 | } 25 | 26 | public void addButtonList(ButtonList buttonList) { 27 | this.buttonLists.add(buttonList); 28 | } 29 | 30 | private void checkButton() { 31 | for (Map.Entry button : buttons) { 32 | button.getValue().checkButton(this, button.getKey()); 33 | } 34 | } 35 | } 36 | 37 | -------------------------------------------------------------------------------- /src/main/java/dev/dubhe/gugle/carpet/api/menu/control/AutoResetButton.java: -------------------------------------------------------------------------------- 1 | package dev.dubhe.gugle.carpet.api.menu.control; 2 | 3 | import dev.dubhe.gugle.carpet.api.tools.text.Color; 4 | import dev.dubhe.gugle.carpet.api.tools.text.ComponentTranslate; 5 | import net.minecraft.network.chat.Style; 6 | import net.minecraft.world.item.Item; 7 | import net.minecraft.world.item.Items; 8 | 9 | public class AutoResetButton extends Button { 10 | public AutoResetButton(String key) { 11 | super(false, 12 | ComponentTranslate.trans(key, Color.WHITE, Style.EMPTY.withBold(true).withItalic(false)), 13 | ComponentTranslate.trans(key, Color.WHITE, Style.EMPTY.withBold(true).withItalic(false)) 14 | ); 15 | this.addTurnOnFunction(this::turnOffWithoutFunction); 16 | } 17 | 18 | public AutoResetButton(String key, Item item) { 19 | super(false, 20 | item, 21 | item, 22 | 1, 23 | ComponentTranslate.trans(key, Color.WHITE, Style.EMPTY.withBold(true).withItalic(false)), 24 | ComponentTranslate.trans(key, Color.WHITE, Style.EMPTY.withBold(true).withItalic(false)) 25 | ); 26 | this.addTurnOnFunction(this::turnOffWithoutFunction); 27 | } 28 | 29 | public static final AutoResetButton NONE = new AutoResetButton("gca.button.none", Items.RED_STAINED_GLASS_PANE); 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/dev/dubhe/gugle/carpet/api/menu/control/ButtonList.java: -------------------------------------------------------------------------------- 1 | package dev.dubhe.gugle.carpet.api.menu.control; 2 | 3 | import java.util.List; 4 | 5 | @SuppressWarnings("unused") 6 | public abstract class ButtonList { 7 | protected final List