├── amecs-api ├── src │ ├── main │ │ ├── resources │ │ │ ├── assets │ │ │ │ └── amecsapi │ │ │ │ │ ├── lang │ │ │ │ │ ├── et_ee.json │ │ │ │ │ ├── ko_kr.json │ │ │ │ │ ├── ru_ru.json │ │ │ │ │ ├── tr_tr.json │ │ │ │ │ ├── zh_hans.json │ │ │ │ │ ├── de_de.json │ │ │ │ │ ├── fi_fi.json │ │ │ │ │ ├── pt_br.json │ │ │ │ │ ├── pt_pt.json │ │ │ │ │ ├── it_it.json │ │ │ │ │ └── en_us.json │ │ │ │ │ └── icon.png │ │ │ ├── META-INF │ │ │ │ ├── coremods.json │ │ │ │ ├── mods.toml │ │ │ │ └── asm │ │ │ │ │ └── mouseScrollHook.js │ │ │ ├── pack.mcmeta │ │ │ ├── amecsapi.accesswidener │ │ │ └── amecsapi.mixins.json │ │ └── java │ │ │ └── de │ │ │ └── siphalor │ │ │ └── amecs │ │ │ ├── impl │ │ │ ├── AmecsAPIMod.java │ │ │ ├── AmecsAPI.java │ │ │ ├── mixin │ │ │ │ ├── KeyMappingLookupAccessor.java │ │ │ │ ├── MixinMinecraftClient.java │ │ │ │ ├── MixinKeyboard.java │ │ │ │ ├── MixinInputUtilType.java │ │ │ │ ├── MixinKeyBinding.java │ │ │ │ └── MixinMouse.java │ │ │ └── KeyBindingManager.java │ │ │ └── api │ │ │ ├── input │ │ │ ├── InputEventHandler.java │ │ │ └── InputHandlerManager.java │ │ │ ├── PriorityKeyBinding.java │ │ │ ├── KeyModifier.java │ │ │ └── AmecsKeyBinding.java │ ├── lombok.config │ └── testmod │ │ ├── resources │ │ ├── pack.mcmeta │ │ ├── assets │ │ │ └── amecsapi-testmod │ │ │ │ └── lang │ │ │ │ └── en_us.json │ │ └── META-INF │ │ │ └── mods.toml │ │ └── java │ │ └── de │ │ └── siphalor │ │ └── amecs │ │ └── testmod │ │ ├── ClientInit.java │ │ └── TestPriorityKeybinding.java ├── gradle │ └── wrapper │ │ ├── gradle-wrapper.jar │ │ └── gradle-wrapper.properties ├── .gitignore ├── .giup ├── gradle.properties ├── LICENSE_HEADER ├── .github │ └── workflows │ │ └── push-main.yaml ├── gradlew.bat ├── README.md └── build.gradle ├── intermediary-deobf ├── gradle.properties └── build.gradle.kts ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── forgeconfigapiport ├── src │ └── main │ │ ├── resources │ │ ├── mod_logo.png │ │ ├── pack.mcmeta │ │ └── META-INF │ │ │ └── mods.toml │ │ └── java │ │ ├── dev │ │ └── su5ed │ │ │ └── sinytra │ │ │ └── connectorextras │ │ │ └── forgeconfigapiport │ │ │ ├── ForgeConfigPathsImpl.java │ │ │ ├── ForgeConfigApiPortImpl.java │ │ │ └── ForgeConfigRegistryImpl.java │ │ └── fuzs │ │ └── forgeconfigapiport │ │ └── api │ │ └── config │ │ └── v2 │ │ ├── ForgeConfigRegistry.java │ │ └── ForgeConfigPaths.java └── build.gradle.kts ├── reach-entity-attributes ├── src │ └── main │ │ ├── resources │ │ ├── pack.mcmeta │ │ ├── META-INF │ │ │ ├── coremods.json │ │ │ ├── mods.toml │ │ │ └── asm │ │ │ │ ├── vehicleInventoryAttackRangeHook.js │ │ │ │ └── inventoryValidationHook.js │ │ ├── assets │ │ │ └── reach-entity-attributes │ │ │ │ └── lang │ │ │ │ └── en_us.json │ │ └── mixins.reach-entity-attributes.json │ │ └── java │ │ └── com │ │ └── jamieswhiteshirt │ │ └── reachentityattributes │ │ ├── DynamicEntityAttributeModifier.java │ │ └── mixin │ │ ├── EntityAttributeInstanceAccessor.java │ │ ├── ScreenHandlerMixin.java │ │ ├── ForgingScreenHandlerMixin.java │ │ ├── client │ │ └── GameRendererMixin.java │ │ ├── PlayerEntityInteractionHandlerMixin.java │ │ └── ChestStateManagerMixin.java ├── gradle.properties ├── LICENSE.md ├── README.md └── build.gradle ├── modmenu-bridge ├── src │ └── main │ │ ├── java │ │ ├── com │ │ │ └── terraformersmc │ │ │ │ └── modmenu │ │ │ │ ├── config │ │ │ │ └── option │ │ │ │ │ ├── OptionConvertable.java │ │ │ │ │ ├── StringSetConfigOption.java │ │ │ │ │ ├── ConfigOptionStorage.java │ │ │ │ │ ├── BooleanConfigOption.java │ │ │ │ │ └── EnumConfigOption.java │ │ │ │ └── api │ │ │ │ ├── ConfigScreenFactory.java │ │ │ │ └── ModMenuApi.java │ │ └── dev │ │ │ └── su5ed │ │ │ └── sinytra │ │ │ └── connectorextras │ │ │ └── modmenu │ │ │ ├── ModMenuDummy.java │ │ │ ├── ModMenuCompat.java │ │ │ ├── mixin │ │ │ └── MinecraftMixin.java │ │ │ └── ModMenuCompatSetup.java │ │ └── resources │ │ ├── mixins.connectorextras_modmenu_bridge.json │ │ └── META-INF │ │ └── neoforge.mods.toml └── build.gradle.kts ├── jei-bridge ├── src │ └── main │ │ ├── java │ │ ├── dev │ │ │ └── su5ed │ │ │ │ └── sinytra │ │ │ │ └── connectorextras │ │ │ │ └── jeibridge │ │ │ │ ├── JEIBridge.java │ │ │ │ ├── mixin │ │ │ │ └── ForgePluginFinderMixin.java │ │ │ │ └── JEIBridgeMixinPlugin.java │ │ └── mezz │ │ │ └── jei │ │ │ └── api │ │ │ └── fabric │ │ │ ├── ingredients │ │ │ └── fluids │ │ │ │ ├── JeiFluidIngredient.java │ │ │ │ └── IJeiFluidIngredient.java │ │ │ └── constants │ │ │ └── FabricTypes.java │ │ └── resources │ │ ├── mixins.jeibridge.json │ │ └── META-INF │ │ └── neoforge.mods.toml └── build.gradle.kts ├── .gitignore ├── rei-bridge ├── src │ └── main │ │ ├── java │ │ ├── dev │ │ │ └── su5ed │ │ │ │ └── sinytra │ │ │ │ └── connectorextras │ │ │ │ └── reibridge │ │ │ │ ├── REIBridge.java │ │ │ │ ├── REIBridgeSetup.java │ │ │ │ ├── mixin │ │ │ │ ├── RoughlyEnoughItemsCoreMixin.java │ │ │ │ └── client │ │ │ │ │ └── RoughlyEnoughItemsCoreClientMixin.java │ │ │ │ └── REIBridgeMixinPlugin.java │ │ └── me │ │ │ └── shedaniel │ │ │ └── rei │ │ │ ├── fabric │ │ │ └── ClientPluginDetector.java │ │ │ └── impl │ │ │ └── common │ │ │ └── compat │ │ │ └── FabricFluidAPISupportPlugin.java │ │ └── resources │ │ ├── mixins.reibridge.json │ │ └── META-INF │ │ └── neoforge.mods.toml └── build.gradle.kts ├── pehkui-bridge ├── src │ └── main │ │ ├── java │ │ └── dev │ │ │ └── su5ed │ │ │ └── sinytra │ │ │ └── connectorextras │ │ │ └── pehkuibridge │ │ │ ├── PehkuiBridge.java │ │ │ ├── PehkuiBridgeMixinPlugin.java │ │ │ └── mixin │ │ │ └── ScaleTypeMixin.java │ │ └── resources │ │ ├── mixins.pehkuibridge.json │ │ └── META-INF │ │ └── neoforge.mods.toml └── build.gradle.kts ├── extras-utils ├── build.gradle.kts └── src │ └── main │ └── java │ └── dev │ └── su5ed │ └── sinytra │ └── connectorextras │ └── util │ └── HackyModuleInjector.java ├── .github ├── ISSUE_TEMPLATE │ ├── config.yml │ └── bug_report.yml └── workflows │ ├── build.yml │ └── release.yml ├── emi-bridge ├── src │ └── main │ │ ├── resources │ │ ├── mixins.emibridge.json │ │ └── META-INF │ │ │ └── neoforge.mods.toml │ │ └── java │ │ └── dev │ │ ├── su5ed │ │ └── sinytra │ │ │ └── connectorextras │ │ │ └── emibridge │ │ │ ├── EMIBridge.java │ │ │ ├── mixin │ │ │ ├── MainEntrypointMixin.java │ │ │ └── EmiAgnosForgeMixin.java │ │ │ └── EMIBridgeMixinPlugin.java │ │ └── emi │ │ └── emi │ │ └── api │ │ └── FabricEmiStack.java └── build.gradle.kts ├── kubejs-bridge ├── src │ └── main │ │ ├── resources │ │ ├── mixins.connectorextras_kubejs_bridge.json │ │ └── META-INF │ │ │ └── neoforge.mods.toml │ │ └── java │ │ └── dev │ │ └── su5ed │ │ └── sinytra │ │ └── connectorextras │ │ └── kubejs │ │ ├── KubeJSCompat.java │ │ ├── mixin │ │ ├── ServerMainMixin.java │ │ ├── MinecraftMixin.java │ │ └── KubeJSMixin.java │ │ ├── KubeJSCompatMixinPlugin.java │ │ └── KubeJSCompatSetup.java └── build.gradle.kts ├── src └── main │ ├── java │ └── dev │ │ └── su5ed │ │ └── sinytra │ │ └── connectorextras │ │ ├── ConnectorExtras.java │ │ └── misc │ │ └── MCPitanLibBridge.java │ └── resources │ └── META-INF │ └── neoforge.mods.toml ├── terrablender-bridge ├── src │ └── main │ │ ├── java │ │ ├── dev │ │ │ └── su5ed │ │ │ │ └── sinytra │ │ │ │ └── connectorextras │ │ │ │ └── terrablenderbridge │ │ │ │ ├── TerraBlenderBridgeSetup.java │ │ │ │ └── TerraBlenderBridge.java │ │ └── terrablender │ │ │ └── api │ │ │ └── TerraBlenderApi.java │ │ └── resources │ │ └── META-INF │ │ └── neoforge.mods.toml └── build.gradle.kts ├── gradle.properties ├── energy-bridge ├── build.gradle.kts └── src │ └── main │ ├── resources │ └── META-INF │ │ └── neoforge.mods.toml │ └── java │ └── dev │ └── su5ed │ └── sinytra │ └── connectorextras │ └── energybridge │ ├── EnergyBridgeConfig.java │ ├── FabricEnergySlotHandler.java │ ├── EnergyBridge.java │ ├── FabricEnergyStorageHandler.java │ ├── ForgeEnergyStorageHandler.java │ └── EnergyBridgeSetup.java ├── settings.gradle.kts ├── .gitattributes ├── LICENSE └── gradlew.bat /amecs-api/src/main/resources/assets/amecsapi/lang/et_ee.json: -------------------------------------------------------------------------------- 1 | {} 2 | -------------------------------------------------------------------------------- /amecs-api/src/main/resources/assets/amecsapi/lang/ko_kr.json: -------------------------------------------------------------------------------- 1 | {} 2 | -------------------------------------------------------------------------------- /amecs-api/src/main/resources/assets/amecsapi/lang/ru_ru.json: -------------------------------------------------------------------------------- 1 | {} 2 | -------------------------------------------------------------------------------- /amecs-api/src/main/resources/assets/amecsapi/lang/tr_tr.json: -------------------------------------------------------------------------------- 1 | {} 2 | -------------------------------------------------------------------------------- /amecs-api/src/main/resources/assets/amecsapi/lang/zh_hans.json: -------------------------------------------------------------------------------- 1 | {} 2 | -------------------------------------------------------------------------------- /intermediary-deobf/gradle.properties: -------------------------------------------------------------------------------- 1 | loom.platform=fabric 2 | 3 | versionTechRebornEnergy=4.1.0 -------------------------------------------------------------------------------- /amecs-api/src/main/resources/META-INF/coremods.json: -------------------------------------------------------------------------------- 1 | { 2 | "mouseScrollHook": "META-INF/asm/mouseScrollHook.js" 3 | } -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Sinytra/ConnectorExtras/HEAD/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /amecs-api/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Sinytra/ConnectorExtras/HEAD/amecs-api/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /amecs-api/src/lombok.config: -------------------------------------------------------------------------------- 1 | lombok.log.custom.declaration = org.apache.logging.log4j.Logger org.apache.logging.log4j.LogManager.getLogger(TYPE) 2 | -------------------------------------------------------------------------------- /amecs-api/src/main/resources/pack.mcmeta: -------------------------------------------------------------------------------- 1 | { 2 | "pack": { 3 | "description": "The default data for amecsapi", 4 | "pack_format": 15 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /forgeconfigapiport/src/main/resources/mod_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Sinytra/ConnectorExtras/HEAD/forgeconfigapiport/src/main/resources/mod_logo.png -------------------------------------------------------------------------------- /amecs-api/src/main/resources/assets/amecsapi/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Sinytra/ConnectorExtras/HEAD/amecs-api/src/main/resources/assets/amecsapi/icon.png -------------------------------------------------------------------------------- /amecs-api/src/testmod/resources/pack.mcmeta: -------------------------------------------------------------------------------- 1 | { 2 | "pack": { 3 | "description": "The default data for amecsapi_testmod", 4 | "pack_format": 15 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /forgeconfigapiport/src/main/resources/pack.mcmeta: -------------------------------------------------------------------------------- 1 | { 2 | "pack": { 3 | "description": "The default data for forgeconfigapiport", 4 | "pack_format": 15 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /reach-entity-attributes/src/main/resources/pack.mcmeta: -------------------------------------------------------------------------------- 1 | { 2 | "pack": { 3 | "description": "The default data for reach-entity-attributes", 4 | "pack_format": 15 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /reach-entity-attributes/src/main/resources/META-INF/coremods.json: -------------------------------------------------------------------------------- 1 | { 2 | "inventoryValidationHook": "META-INF/asm/inventoryValidationHook.js", 3 | "vehicleInventoryAttackRangeHook": "META-INF/asm/vehicleInventoryAttackRangeHook.js" 4 | } -------------------------------------------------------------------------------- /amecs-api/.gitignore: -------------------------------------------------------------------------------- 1 | #Gradle 2 | .gradle/ 3 | build/ 4 | out/ 5 | classes/ 6 | 7 | #IDEA 8 | .idea/ 9 | *.iml 10 | *.ipr 11 | *.iws 12 | 13 | #vscode 14 | .settings/ 15 | .vscode/ 16 | bin/ 17 | .classpath 18 | .project 19 | 20 | #fabric 21 | run/ -------------------------------------------------------------------------------- /reach-entity-attributes/src/main/resources/assets/reach-entity-attributes/lang/en_us.json: -------------------------------------------------------------------------------- 1 | { 2 | "attribute.name.generic.reach-entity-attributes.reach": "Reach", 3 | "attribute.name.generic.reach-entity-attributes.attack_range": "Attack Range" 4 | } 5 | -------------------------------------------------------------------------------- /amecs-api/src/testmod/resources/assets/amecsapi-testmod/lang/en_us.json: -------------------------------------------------------------------------------- 1 | { 2 | "key.amecsapi-testmod.priority": "Priority Keybinding", 3 | "key.amecsapi-testmod.priority.amecsapi.description": "A Keybinding that tests the priority execution using Amecs API.\nSupports line breaks." 4 | } 5 | -------------------------------------------------------------------------------- /modmenu-bridge/src/main/java/com/terraformersmc/modmenu/config/option/OptionConvertable.java: -------------------------------------------------------------------------------- 1 | package com.terraformersmc.modmenu.config.option; 2 | 3 | import net.minecraft.client.option.SimpleOption; 4 | 5 | public interface OptionConvertable { 6 | SimpleOption asOption(); 7 | } 8 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Wed Jun 14 17:05:22 CEST 2023 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.8-bin.zip 5 | zipStoreBase=GRADLE_USER_HOME 6 | zipStorePath=wrapper/dists 7 | -------------------------------------------------------------------------------- /amecs-api/src/main/resources/amecsapi.accesswidener: -------------------------------------------------------------------------------- 1 | accessWidener v1 named 2 | accessible method net/minecraft/client/util/InputUtil$Type mapKey (Lnet/minecraft/client/util/InputUtil$Type;Ljava/lang/String;I)V 3 | 4 | accessible field net/minecraft/client/util/InputUtil$Key KEYS Ljava/util/Map; 5 | -------------------------------------------------------------------------------- /modmenu-bridge/src/main/resources/mixins.connectorextras_modmenu_bridge.json: -------------------------------------------------------------------------------- 1 | { 2 | "minVersion": "0.8", 3 | "compatibilityLevel": "JAVA_16", 4 | "required": true, 5 | "package": "dev.su5ed.sinytra.connectorextras.modmenu.mixin", 6 | "client": [ 7 | "MinecraftMixin" 8 | ] 9 | } 10 | -------------------------------------------------------------------------------- /jei-bridge/src/main/java/dev/su5ed/sinytra/connectorextras/jeibridge/JEIBridge.java: -------------------------------------------------------------------------------- 1 | package dev.su5ed.sinytra.connectorextras.jeibridge; 2 | 3 | import net.neoforged.fml.common.Mod; 4 | 5 | @Mod("connectorextras_jei_bridge") 6 | public class JEIBridge { 7 | public static final String JEI_MODID = "jei"; 8 | } 9 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # eclipse 2 | bin 3 | *.launch 4 | .settings 5 | .metadata 6 | .classpath 7 | .project 8 | 9 | # idea 10 | out 11 | *.ipr 12 | *.iws 13 | *.iml 14 | .idea 15 | 16 | # gradle 17 | build 18 | .gradle 19 | 20 | # other 21 | eclipse 22 | run 23 | 24 | # Files from Forge MDK 25 | forge*changelog.txt 26 | -------------------------------------------------------------------------------- /amecs-api/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.3-bin.zip 4 | networkTimeout=10000 5 | validateDistributionUrl=true 6 | zipStoreBase=GRADLE_USER_HOME 7 | zipStorePath=wrapper/dists 8 | -------------------------------------------------------------------------------- /modmenu-bridge/src/main/java/dev/su5ed/sinytra/connectorextras/modmenu/ModMenuDummy.java: -------------------------------------------------------------------------------- 1 | package dev.su5ed.sinytra.connectorextras.modmenu; 2 | 3 | import net.neoforged.fml.common.Mod; 4 | 5 | @Mod(ModMenuDummy.MODMENU_MODID) 6 | public class ModMenuDummy { 7 | public static final String MODMENU_MODID = "modmenu"; 8 | } 9 | -------------------------------------------------------------------------------- /rei-bridge/src/main/java/dev/su5ed/sinytra/connectorextras/reibridge/REIBridge.java: -------------------------------------------------------------------------------- 1 | package dev.su5ed.sinytra.connectorextras.reibridge; 2 | 3 | import net.neoforged.fml.common.Mod; 4 | 5 | @Mod("connectorextras_rei_bridge") 6 | public class REIBridge { 7 | public static final String REI_MODID = "roughlyenoughitems"; 8 | } 9 | -------------------------------------------------------------------------------- /amecs-api/.giup: -------------------------------------------------------------------------------- 1 | { 2 | "merge-paths": [ 3 | "1.15", 4 | "1.15->1.14", 5 | "1.15->1.16->1.17->1.18->1.19->1.19.3->1.19.4->1.20->unstable" 6 | ], 7 | "commands": [ 8 | { 9 | "title": "Build and publish", 10 | "run": "./gradlew publish", 11 | "nt": "gradlew publish" 12 | }, 13 | "git push" 14 | ] 15 | } 16 | -------------------------------------------------------------------------------- /pehkui-bridge/src/main/java/dev/su5ed/sinytra/connectorextras/pehkuibridge/PehkuiBridge.java: -------------------------------------------------------------------------------- 1 | package dev.su5ed.sinytra.connectorextras.pehkuibridge; 2 | 3 | import net.neoforged.fml.common.Mod; 4 | 5 | @Mod("connectorextras_pehkui_bridge") 6 | public class PehkuiBridge { 7 | public static final String PEHKUI_MODID = "pehkui"; 8 | } 9 | -------------------------------------------------------------------------------- /extras-utils/build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | id("dev.architectury.loom") 3 | } 4 | 5 | val versionForge: String by rootProject 6 | 7 | dependencies { 8 | mappings(loom.officialMojangMappings()) 9 | neoForge("net.neoforged:neoforge:$versionForge") 10 | } 11 | 12 | tasks.jar { 13 | manifest.attributes("FMLModType" to "LIBRARY") 14 | } -------------------------------------------------------------------------------- /jei-bridge/src/main/resources/mixins.jeibridge.json: -------------------------------------------------------------------------------- 1 | { 2 | "minVersion": "0.8", 3 | "compatibilityLevel": "JAVA_16", 4 | "required": true, 5 | "package": "dev.su5ed.sinytra.connectorextras.jeibridge.mixin", 6 | "plugin": "dev.su5ed.sinytra.connectorextras.jeibridge.JEIBridgeMixinPlugin", 7 | "mixins": [ 8 | "ForgePluginFinderMixin" 9 | ] 10 | } 11 | -------------------------------------------------------------------------------- /pehkui-bridge/src/main/resources/mixins.pehkuibridge.json: -------------------------------------------------------------------------------- 1 | { 2 | "minVersion": "0.8", 3 | "compatibilityLevel": "JAVA_16", 4 | "required": true, 5 | "package": "dev.su5ed.sinytra.connectorextras.pehkuibridge.mixin", 6 | "plugin": "dev.su5ed.sinytra.connectorextras.pehkuibridge.PehkuiBridgeMixinPlugin", 7 | "mixins": [ 8 | "ScaleTypeMixin" 9 | ] 10 | } 11 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | blank_issues_enabled: true 2 | contact_links: 3 | - name: GitHub Discussions 4 | url: https://github.com/Sinytra/ConnectorExtras/discussions 5 | about: Please look here for frequently asked questions and questions on how to use Connector Extras. 6 | - name: Discord 7 | url: https://discord.gg/mamk7z3TKZ 8 | about: Join us on our discord! -------------------------------------------------------------------------------- /intermediary-deobf/build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | id("dev.architectury.loom") 3 | } 4 | 5 | val versionTechRebornEnergy: String by project 6 | 7 | dependencies { 8 | mappings(loom.officialMojangMappings()) 9 | 10 | modImplementation(group = "teamreborn", name = "energy", version = versionTechRebornEnergy) { 11 | isTransitive = false 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /modmenu-bridge/src/main/java/dev/su5ed/sinytra/connectorextras/modmenu/ModMenuCompat.java: -------------------------------------------------------------------------------- 1 | package dev.su5ed.sinytra.connectorextras.modmenu; 2 | 3 | import net.neoforged.fml.common.Mod; 4 | 5 | @Mod(ModMenuCompat.MODID) 6 | public class ModMenuCompat { 7 | public static final String MODID = "connectorextras_modmenu_bridge"; 8 | 9 | public ModMenuCompat() {} 10 | } 11 | -------------------------------------------------------------------------------- /emi-bridge/src/main/resources/mixins.emibridge.json: -------------------------------------------------------------------------------- 1 | { 2 | "minVersion": "0.8", 3 | "compatibilityLevel": "JAVA_16", 4 | "required": true, 5 | "package": "dev.su5ed.sinytra.connectorextras.emibridge.mixin", 6 | "plugin": "dev.su5ed.sinytra.connectorextras.emibridge.EMIBridgeMixinPlugin", 7 | "mixins": [ 8 | "EmiAgnosForgeMixin", 9 | "MainEntrypointMixin" 10 | ] 11 | } 12 | -------------------------------------------------------------------------------- /amecs-api/src/main/resources/amecsapi.mixins.json: -------------------------------------------------------------------------------- 1 | { 2 | "required": true, 3 | "package": "de.siphalor.amecs.impl.mixin", 4 | "compatibilityLevel": "JAVA_8", 5 | "mixins": [], 6 | "client": [ 7 | "KeyMappingLookupAccessor", 8 | "MixinInputUtilType", 9 | "MixinKeyBinding", 10 | "MixinKeyboard", 11 | "MixinMinecraftClient", 12 | "MixinMouse" 13 | ], 14 | "server": [], 15 | "injectors": { 16 | "defaultRequire": 1 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /rei-bridge/src/main/resources/mixins.reibridge.json: -------------------------------------------------------------------------------- 1 | { 2 | "minVersion": "0.8", 3 | "compatibilityLevel": "JAVA_16", 4 | "required": true, 5 | "package": "dev.su5ed.sinytra.connectorextras.reibridge.mixin", 6 | "plugin": "dev.su5ed.sinytra.connectorextras.reibridge.REIBridgeMixinPlugin", 7 | "client": [ 8 | "client.RoughlyEnoughItemsCoreClientMixin" 9 | ], 10 | "mixins": [ 11 | "RoughlyEnoughItemsCoreMixin" 12 | ] 13 | } 14 | -------------------------------------------------------------------------------- /kubejs-bridge/src/main/resources/mixins.connectorextras_kubejs_bridge.json: -------------------------------------------------------------------------------- 1 | { 2 | "minVersion": "0.8", 3 | "compatibilityLevel": "JAVA_16", 4 | "required": true, 5 | "plugin": "dev.su5ed.sinytra.connectorextras.kubejs.KubeJSCompatMixinPlugin", 6 | "package": "dev.su5ed.sinytra.connectorextras.kubejs.mixin", 7 | "mixins": [ 8 | "KubeJSMixin" 9 | ], 10 | "client": [ 11 | "MinecraftMixin" 12 | ], 13 | "server": [ 14 | "ServerMainMixin" 15 | ] 16 | } 17 | -------------------------------------------------------------------------------- /forgeconfigapiport/build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | id("dev.architectury.loom") 3 | } 4 | 5 | val versionMc: String by rootProject 6 | val versionForge: String by rootProject 7 | 8 | dependencies { 9 | mappings(loom.officialMojangMappings()) 10 | forge(group = "net.minecraftforge", name = "forge", version = "$versionMc-$versionForge") 11 | 12 | modImplementation(group = "dev.su5ed.sinytra.fabric-api", name = "fabric-api-base", version = "0.4.30+ef105b4977") 13 | } 14 | -------------------------------------------------------------------------------- /pehkui-bridge/build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | id("dev.architectury.loom") 3 | } 4 | 5 | val versionForge: String by rootProject 6 | 7 | dependencies { 8 | mappings(loom.officialMojangMappings()) 9 | neoForge("net.neoforged:neoforge:$versionForge") 10 | 11 | modImplementation(group = "org.sinytra.forgified-fabric-api", name = "fabric-api-base", version = "0.4.42+d1308dedd1") 12 | 13 | modImplementation(group = "curse.maven", name = "pehkui-319596", version = "5446174") 14 | } 15 | -------------------------------------------------------------------------------- /rei-bridge/src/main/java/dev/su5ed/sinytra/connectorextras/reibridge/REIBridgeSetup.java: -------------------------------------------------------------------------------- 1 | package dev.su5ed.sinytra.connectorextras.reibridge; 2 | 3 | import com.google.common.base.Suppliers; 4 | import me.shedaniel.rei.fabric.PluginDetectorImpl; 5 | import me.shedaniel.rei.impl.init.PluginDetector; 6 | 7 | import java.util.function.Supplier; 8 | 9 | public final class REIBridgeSetup { 10 | public static final Supplier FABRIC_PLUGIN_DETECTOR = Suppliers.memoize(PluginDetectorImpl::new); 11 | } 12 | -------------------------------------------------------------------------------- /amecs-api/gradle.properties: -------------------------------------------------------------------------------- 1 | org.gradle.jvmargs = -Xmx1G 2 | 3 | #Fabric properties 4 | minecraft_major_version = 1.20 5 | minecraft_version = 1.20-pre1 6 | yarn_mappings = 7 7 | loader_version = 0.14.19 8 | 9 | #Mod properties 10 | mod_version = 1.5.3 11 | maven_group = de.siphalor 12 | archives_base_name = amecsapi 13 | 14 | # Dependencies 15 | lombok_version = 1.18.28 16 | fabric_api_version = 0.80.3+1.20 17 | forge_version = 1.20.1-47.1.3 18 | loom.platform=forge -------------------------------------------------------------------------------- /src/main/java/dev/su5ed/sinytra/connectorextras/ConnectorExtras.java: -------------------------------------------------------------------------------- 1 | package dev.su5ed.sinytra.connectorextras; 2 | 3 | import dev.su5ed.sinytra.connectorextras.misc.MCPitanLibBridge; 4 | import net.neoforged.bus.api.IEventBus; 5 | import net.neoforged.fml.ModList; 6 | import net.neoforged.fml.common.Mod; 7 | 8 | @Mod("connectorextras") 9 | public class ConnectorExtras { 10 | 11 | public ConnectorExtras(IEventBus bus) { 12 | if (ModList.get().isLoaded("mcpitanlibarch")) { 13 | MCPitanLibBridge.init(bus); 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /amecs-api/src/main/resources/assets/amecsapi/lang/de_de.json: -------------------------------------------------------------------------------- 1 | { 2 | "key.amecsapi.mouse.scroll.up": "Mausrad auf", 3 | "key.amecsapi.mouse.scroll.down": "Mausrad ab", 4 | 5 | "amecsapi.modifier.alt": "Alt", 6 | "amecsapi.modifier.alt.short": "Alt", 7 | "amecsapi.modifier.alt.tiny": "A", 8 | "amecsapi.modifier.control": "Steuerung", 9 | "amecsapi.modifier.control.short": "Strg", 10 | "amecsapi.modifier.control.tiny": "S", 11 | "amecsapi.modifier.shift": "Umschalt", 12 | "amecsapi.modifier.shift.short": "Umst", 13 | "amecsapi.modifier.shift.tiny": "U" 14 | } 15 | -------------------------------------------------------------------------------- /modmenu-bridge/build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | id("dev.architectury.loom") 3 | } 4 | 5 | val versionForge: String by rootProject 6 | val versionYarn: String by rootProject 7 | 8 | dependencies { 9 | mappings(loom.layered { 10 | mappings("net.fabricmc:yarn:$versionYarn:v2") 11 | mappings("dev.architectury:yarn-mappings-patch-neoforge:1.21+build.4") 12 | }) 13 | neoForge("net.neoforged:neoforge:$versionForge") 14 | 15 | modImplementation(group = "org.sinytra", name = "forgified-fabric-loader", version = "2.5.29+0.16.0+1.21") 16 | } 17 | -------------------------------------------------------------------------------- /reach-entity-attributes/src/main/resources/mixins.reach-entity-attributes.json: -------------------------------------------------------------------------------- 1 | { 2 | "minVersion": "0.8", 3 | "compatibilityLevel": "JAVA_16", 4 | "required": true, 5 | "package": "com.jamieswhiteshirt.reachentityattributes.mixin", 6 | "client": [ 7 | "client.GameRendererMixin" 8 | ], 9 | "mixins": [ 10 | "EntityAttributeInstanceAccessor", 11 | "ChestStateManagerMixin", 12 | "ForgingScreenHandlerMixin", 13 | "PlayerEntityInteractionHandlerMixin", 14 | "ScreenHandlerMixin" 15 | ], 16 | "refmap": "refmap.reach-entity-attributes.json" 17 | } 18 | -------------------------------------------------------------------------------- /amecs-api/src/main/resources/assets/amecsapi/lang/fi_fi.json: -------------------------------------------------------------------------------- 1 | { 2 | "amecsapi.modifier.alt.tiny": "A", 3 | "amecsapi.modifier.control": "Control", 4 | "amecsapi.modifier.control.short": "Ctrl", 5 | "amecsapi.modifier.control.tiny": "C", 6 | "amecsapi.modifier.shift": "Shift", 7 | "amecsapi.modifier.shift.short": "Shft", 8 | "amecsapi.modifier.shift.tiny": "S", 9 | "amecsapi.modifier.alt": "Alt", 10 | "amecsapi.modifier.alt.short": "Alt", 11 | "key.amecsapi.mouse.scroll.up": "Selaa Ylös", 12 | "key.amecsapi.mouse.scroll.down": "Selaa Alas" 13 | } 14 | -------------------------------------------------------------------------------- /amecs-api/src/main/resources/assets/amecsapi/lang/pt_br.json: -------------------------------------------------------------------------------- 1 | { 2 | "amecsapi.modifier.alt": "Alt", 3 | "amecsapi.modifier.alt.short": "Alt", 4 | "amecsapi.modifier.alt.tiny": "A", 5 | "amecsapi.modifier.control": "Control", 6 | "amecsapi.modifier.control.short": "Ctrl", 7 | "amecsapi.modifier.control.tiny": "C", 8 | "amecsapi.modifier.shift": "Shift", 9 | "amecsapi.modifier.shift.short": "Shft", 10 | "amecsapi.modifier.shift.tiny": "S", 11 | "key.amecsapi.mouse.scroll.up": "Rolar para cima", 12 | "key.amecsapi.mouse.scroll.down": "Rolar para baixo" 13 | } 14 | -------------------------------------------------------------------------------- /amecs-api/src/main/resources/assets/amecsapi/lang/pt_pt.json: -------------------------------------------------------------------------------- 1 | { 2 | "key.amecsapi.mouse.scroll.up": "Rolar para cima", 3 | "key.amecsapi.mouse.scroll.down": "Rolar para baixo", 4 | "amecsapi.modifier.alt": "Alt", 5 | "amecsapi.modifier.alt.short": "Alt", 6 | "amecsapi.modifier.alt.tiny": "A", 7 | "amecsapi.modifier.control": "Control", 8 | "amecsapi.modifier.control.short": "Ctrl", 9 | "amecsapi.modifier.control.tiny": "C", 10 | "amecsapi.modifier.shift": "Shift", 11 | "amecsapi.modifier.shift.short": "Shft", 12 | "amecsapi.modifier.shift.tiny": "S" 13 | } 14 | -------------------------------------------------------------------------------- /amecs-api/src/main/resources/assets/amecsapi/lang/it_it.json: -------------------------------------------------------------------------------- 1 | { 2 | "key.amecsapi.mouse.scroll.down": "Scorrere verso il basso", 3 | "amecsapi.modifier.alt": "Alt", 4 | "amecsapi.modifier.alt.short": "Alt", 5 | "amecsapi.modifier.alt.tiny": "A", 6 | "amecsapi.modifier.control.short": "Ctrl", 7 | "amecsapi.modifier.control.tiny": "C", 8 | "amecsapi.modifier.shift": "Maiuscolo", 9 | "amecsapi.modifier.shift.short": "Maiusc", 10 | "amecsapi.modifier.shift.tiny": "S", 11 | "amecsapi.modifier.control": "Control", 12 | "key.amecsapi.mouse.scroll.up": "Scorrere verso l'alto" 13 | } 14 | -------------------------------------------------------------------------------- /reach-entity-attributes/gradle.properties: -------------------------------------------------------------------------------- 1 | org.gradle.jvmargs = -Xmx4G -Dfile.encoding=UTF-8 2 | #org.gradle.logging.level = info 3 | org.gradle.parallel = true 4 | 5 | # Fabric Properties 6 | # check these on https://fabricmc.net/versions.html 7 | minecraft_version = 1.20.1 8 | yarn_mappings = 1.20.1+build.1 9 | loader_version = 0.14.21 10 | 11 | # Mod Properties 12 | mod_version = 2.4.0 13 | maven_group = dev.su5ed.sinytra 14 | archives_base_name = reach-entity-attributes 15 | 16 | # Dependencies 17 | fabric_version = 0.83.0+1.20 18 | forge_version = 1.20.1-47.1.3 19 | jsr305_version = 3.0.2 20 | 21 | loom.platform=forge -------------------------------------------------------------------------------- /amecs-api/LICENSE_HEADER: -------------------------------------------------------------------------------- 1 | Copyright 2020-2023 Siphalor 2 | 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | 7 | http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | Unless required by applicable law or agreed to in writing, software 10 | distributed under the License is distributed on an "AS IS" BASIS, 11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | See the License for the specific language governing permissions and 13 | limitations under the License. 14 | -------------------------------------------------------------------------------- /src/main/java/dev/su5ed/sinytra/connectorextras/misc/MCPitanLibBridge.java: -------------------------------------------------------------------------------- 1 | package dev.su5ed.sinytra.connectorextras.misc; 2 | 3 | import net.neoforged.bus.api.IEventBus; 4 | import net.neoforged.fml.event.lifecycle.FMLCommonSetupEvent; 5 | import net.pitan76.mcpitanlib.api.item.CreativeTabManager; 6 | 7 | public final class MCPitanLibBridge { 8 | 9 | public static void init(IEventBus bus) { 10 | bus.addListener(MCPitanLibBridge::onCommonSetup); 11 | } 12 | 13 | private static void onCommonSetup(FMLCommonSetupEvent event) { 14 | CreativeTabManager.allRegister(); 15 | } 16 | 17 | private MCPitanLibBridge() {} 18 | } 19 | -------------------------------------------------------------------------------- /amecs-api/src/main/resources/assets/amecsapi/lang/en_us.json: -------------------------------------------------------------------------------- 1 | { 2 | "key.amecsapi.mouse.scroll.up": "Scroll Up", 3 | "key.amecsapi.mouse.scroll.down": "Scroll Down", 4 | "key.amecsapi.mouse.scroll.left": "Scroll Left", 5 | "key.amecsapi.mouse.scroll.right": "Scroll Right", 6 | 7 | "amecsapi.modifier.alt": "Alt", 8 | "amecsapi.modifier.alt.short": "Alt", 9 | "amecsapi.modifier.alt.tiny": "A", 10 | "amecsapi.modifier.control": "Control", 11 | "amecsapi.modifier.control.short": "Ctrl", 12 | "amecsapi.modifier.control.tiny": "C", 13 | "amecsapi.modifier.shift": "Shift", 14 | "amecsapi.modifier.shift.short": "Shft", 15 | "amecsapi.modifier.shift.tiny": "S" 16 | } 17 | -------------------------------------------------------------------------------- /terrablender-bridge/src/main/java/dev/su5ed/sinytra/connectorextras/terrablenderbridge/TerraBlenderBridgeSetup.java: -------------------------------------------------------------------------------- 1 | package dev.su5ed.sinytra.connectorextras.terrablenderbridge; 2 | 3 | import net.fabricmc.loader.api.FabricLoader; 4 | import terrablender.api.TerraBlenderApi; 5 | 6 | public final class TerraBlenderBridgeSetup { 7 | 8 | public static void init() { 9 | FabricLoader.getInstance().getEntrypointContainers("terrablender", TerraBlenderApi.class).forEach(entrypoint -> { 10 | TerraBlenderApi api = entrypoint.getEntrypoint(); 11 | api.onTerraBlenderInitialized(); 12 | }); 13 | } 14 | 15 | private TerraBlenderBridgeSetup() {} 16 | } 17 | -------------------------------------------------------------------------------- /kubejs-bridge/src/main/java/dev/su5ed/sinytra/connectorextras/kubejs/KubeJSCompat.java: -------------------------------------------------------------------------------- 1 | package dev.su5ed.sinytra.connectorextras.kubejs; 2 | 3 | import net.neoforged.fml.common.Mod; 4 | import net.neoforged.fml.loading.LoadingModList; 5 | 6 | @Mod(KubeJSCompat.MODID) 7 | public class KubeJSCompat { 8 | public static final String MODID = "connectorextras_kubejs_bridge"; 9 | private static final String KUBEJS_MODID = "kubejs"; 10 | private static final String CONNECTOR_MODID = "connectormod"; 11 | 12 | public static boolean isEnabled() { 13 | return LoadingModList.get().getModFileById(KUBEJS_MODID) != null && LoadingModList.get().getModFileById(CONNECTOR_MODID) != null; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /emi-bridge/src/main/java/dev/su5ed/sinytra/connectorextras/emibridge/EMIBridge.java: -------------------------------------------------------------------------------- 1 | package dev.su5ed.sinytra.connectorextras.emibridge; 2 | 3 | import com.mojang.logging.LogUtils; 4 | import dev.su5ed.sinytra.connectorextras.util.HackyModuleInjector; 5 | import net.neoforged.fml.common.Mod; 6 | import org.slf4j.Logger; 7 | 8 | @Mod("connectorextras_emi_bridge") 9 | public class EMIBridge { 10 | private static final Logger LOGGER = LogUtils.getLogger(); 11 | public static final String EMI_MODID = "emi"; 12 | 13 | public static void injectModule() { 14 | LOGGER.info("Injecting EMI API classes"); 15 | HackyModuleInjector.injectModuleSources(EMI_MODID, EMIBridge.class.getResource("/relocate")); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | # Sets default memory used for gradle commands. Can be overridden by user or command line properties. 2 | # This is required to provide enough memory for the Minecraft decompilation process. 3 | org.gradle.jvmargs=-Xmx4G 4 | org.gradle.daemon=false 5 | org.gradle.parallel=true 6 | 7 | loom.platform=neoforge 8 | fabric.loom.multiProjectOptimisation=true 9 | 10 | # Versions 11 | versionMc=1.21.1 12 | versionForge=21.1.4 13 | versionConnectorExtras=1.12.1 14 | versionYarn=1.21.1+build.3 15 | 16 | # Publishing 17 | curseForgeId=913445 18 | modrinthId=FYpiwiBR 19 | githubRepository=Sinytra/ConnectorExtras 20 | publishBranch=master 21 | 22 | # Dependencies 23 | connectorCurseForge=sinytra-connector 24 | connectorModrinth=u58R1TMW 25 | -------------------------------------------------------------------------------- /modmenu-bridge/src/main/java/dev/su5ed/sinytra/connectorextras/modmenu/mixin/MinecraftMixin.java: -------------------------------------------------------------------------------- 1 | package dev.su5ed.sinytra.connectorextras.modmenu.mixin; 2 | 3 | import dev.su5ed.sinytra.connectorextras.modmenu.ModMenuCompatSetup; 4 | import net.minecraft.client.MinecraftClient; 5 | import org.spongepowered.asm.mixin.Mixin; 6 | import org.spongepowered.asm.mixin.injection.At; 7 | import org.spongepowered.asm.mixin.injection.Inject; 8 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; 9 | 10 | @Mixin(MinecraftClient.class) 11 | public class MinecraftMixin { 12 | 13 | @Inject(method = "lambda$new$7", at = @At("HEAD")) 14 | private void initModMenuCompat(CallbackInfo ci) { 15 | ModMenuCompatSetup.init(); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /energy-bridge/build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | id("dev.architectury.loom") 3 | } 4 | 5 | val versionForge: String by rootProject 6 | 7 | dependencies { 8 | mappings(loom.officialMojangMappings()) 9 | neoForge("net.neoforged:neoforge:$versionForge") 10 | 11 | implementation(group = "org.sinytra", name = "forgified-fabric-loader", version = "2.5.29+0.16.0+1.21") 12 | modImplementation(group = "org.sinytra.forgified-fabric-api", name = "fabric-api-lookup-api-v1", version = "1.6.68+c21168c3d1") 13 | modImplementation(group = "org.sinytra.forgified-fabric-api", name = "fabric-transfer-api-v1", version = "5.1.16+7f12564fd1") 14 | 15 | implementation(project(path = ":intermediary-deobf", configuration = "modRuntimeClasspathMainMapped")) 16 | } 17 | -------------------------------------------------------------------------------- /emi-bridge/src/main/java/dev/su5ed/sinytra/connectorextras/emibridge/mixin/MainEntrypointMixin.java: -------------------------------------------------------------------------------- 1 | package dev.su5ed.sinytra.connectorextras.emibridge.mixin; 2 | 3 | import dev.su5ed.sinytra.connectorextras.emibridge.EMIBridge; 4 | import org.spongepowered.asm.mixin.Mixin; 5 | import org.spongepowered.asm.mixin.injection.At; 6 | import org.spongepowered.asm.mixin.injection.Inject; 7 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; 8 | 9 | @Mixin({net.minecraft.client.main.Main.class, net.minecraft.server.Main.class}) 10 | public class MainEntrypointMixin { 11 | 12 | @Inject(method = "main", at = @At("HEAD"), remap = false) 13 | private static void beforeGameLaunch(String[] strings, CallbackInfo ci) { 14 | EMIBridge.injectModule(); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /reach-entity-attributes/src/main/java/com/jamieswhiteshirt/reachentityattributes/DynamicEntityAttributeModifier.java: -------------------------------------------------------------------------------- 1 | package com.jamieswhiteshirt.reachentityattributes; 2 | 3 | import net.minecraft.entity.attribute.EntityAttributeModifier; 4 | 5 | import java.util.UUID; 6 | import java.util.function.DoubleSupplier; 7 | 8 | public class DynamicEntityAttributeModifier extends EntityAttributeModifier { 9 | private final DoubleSupplier valueSupplier; 10 | 11 | public DynamicEntityAttributeModifier(UUID uuid, String name, DoubleSupplier value, Operation operation) { 12 | super(uuid, name, 0.0, operation); 13 | this.valueSupplier = value; 14 | } 15 | 16 | @Override 17 | public double getValue() { 18 | return this.valueSupplier.getAsDouble(); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /jei-bridge/build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | id("dev.architectury.loom") 3 | } 4 | 5 | val versionForge: String by rootProject 6 | 7 | repositories { 8 | maven("https://maven.blamejared.com/") 9 | } 10 | 11 | dependencies { 12 | mappings(loom.officialMojangMappings()) 13 | neoForge("net.neoforged:neoforge:$versionForge") 14 | 15 | implementation(group = "org.sinytra", name = "forgified-fabric-loader", version = "2.5.29+0.16.0+1.21") 16 | modImplementation(group = "org.sinytra.forgified-fabric-api", name = "fabric-api-lookup-api-v1", version = "1.6.68+c21168c3d1") 17 | modImplementation(group = "org.sinytra.forgified-fabric-api", name = "fabric-transfer-api-v1", version = "5.1.16+7f12564fd1") 18 | 19 | modImplementation(group = "mezz.jei", name = "jei-1.21-neoforge", version = "19.7.0.90") 20 | } 21 | -------------------------------------------------------------------------------- /amecs-api/src/main/resources/META-INF/mods.toml: -------------------------------------------------------------------------------- 1 | modLoader="javafml" 2 | loaderVersion="[47,)" 3 | license="Apache-2.0" 4 | issueTrackerURL="https://github.com/Sinytra/ConnectorExtras/issues" 5 | 6 | [[mods]] 7 | modId="amecsapi" 8 | version="${file.jarVersion}" 9 | displayName="Amecs API" 10 | authors="Siphalor, Klotzi111" 11 | displayURL="https://github.com/Sinytra/ConnectorExtras" 12 | description=''' 13 | The keybinding modifier API of Amecs 14 | ''' 15 | logoFile="assets/amecsapi/icon.png" 16 | displayTest = 'IGNORE_ALL_VERSION' 17 | [[dependencies.amecsapi]] 18 | modId="forge" 19 | mandatory=true 20 | versionRange="[47,)" 21 | ordering="NONE" 22 | side="BOTH" 23 | [[dependencies.amecsapi]] 24 | modId="minecraft" 25 | mandatory=true 26 | versionRange="[1.20.1,1.21)" 27 | ordering="NONE" 28 | side="BOTH" 29 | -------------------------------------------------------------------------------- /reach-entity-attributes/src/main/java/com/jamieswhiteshirt/reachentityattributes/mixin/EntityAttributeInstanceAccessor.java: -------------------------------------------------------------------------------- 1 | package com.jamieswhiteshirt.reachentityattributes.mixin; 2 | 3 | import net.minecraft.entity.attribute.EntityAttributeInstance; 4 | import org.spongepowered.asm.mixin.Mixin; 5 | import org.spongepowered.asm.mixin.Mutable; 6 | import org.spongepowered.asm.mixin.gen.Accessor; 7 | import org.spongepowered.asm.mixin.gen.Invoker; 8 | 9 | import java.util.function.Consumer; 10 | 11 | @Mixin(EntityAttributeInstance.class) 12 | public interface EntityAttributeInstanceAccessor { 13 | @Accessor 14 | Consumer getUpdateCallback(); 15 | 16 | @Accessor 17 | @Mutable 18 | void setUpdateCallback(Consumer updateCallback); 19 | 20 | @Invoker 21 | void callOnUpdate(); 22 | } 23 | -------------------------------------------------------------------------------- /amecs-api/.github/workflows/push-main.yaml: -------------------------------------------------------------------------------- 1 | on: 2 | push: 3 | branches: 4 | - "1.15" 5 | 6 | 7 | jobs: 8 | auto-fix: 9 | runs-on: ubuntu-latest 10 | steps: 11 | - name: Checkout 12 | uses: actions/checkout@v3 13 | with: 14 | token: "${{ secrets.CUSTOMGHTOKEN }}" 15 | 16 | - name: Fix language file names 17 | run: | 18 | for lang in src/main/resources/assets/*/lang/*.json 19 | do 20 | rename=$(echo "$lang" | sed -e 's/\b\w\+\.json$/\L\0/' -e 's/\b\([a-z]\+\)\.json$/\/\1_\1.json/') 21 | mv "$lang" "$rename" || true 22 | done 23 | 24 | - name: Commit 25 | uses: EndBug/add-and-commit@v9 26 | with: 27 | add: 'src/main/resources/assets' 28 | default_author: github_actions 29 | message: Fix language file names 30 | -------------------------------------------------------------------------------- /amecs-api/src/main/java/de/siphalor/amecs/impl/AmecsAPIMod.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2023 Siphalor 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package de.siphalor.amecs.impl; 18 | 19 | import net.minecraftforge.fml.common.Mod; 20 | 21 | @Mod(AmecsAPI.MOD_ID) 22 | public class AmecsAPIMod { 23 | } 24 | -------------------------------------------------------------------------------- /amecs-api/src/testmod/resources/META-INF/mods.toml: -------------------------------------------------------------------------------- 1 | modLoader="javafml" 2 | loaderVersion="[47,)" 3 | license="Apache-2.0" 4 | issueTrackerURL="https://github.com/Sinytra/ConnectorExtras/issues" 5 | 6 | [[mods]] 7 | modId="amecsapi_testmod" 8 | version="${file.jarVersion}" 9 | displayName="Amecs API Testmod" 10 | authors="Siphalor, Klotzi111" 11 | displayURL="https://github.com/Sinytra/ConnectorExtras" 12 | description=''' 13 | The keybinding modifier API of Amecs 14 | ''' 15 | logoFile="assets/amecsapi/icon.png" 16 | displayTest = 'IGNORE_ALL_VERSION' 17 | [[dependencies.amecsapi_testmod]] 18 | modId="forge" 19 | mandatory=true 20 | versionRange="[47,)" 21 | ordering="NONE" 22 | side="BOTH" 23 | [[dependencies.amecsapi_testmod]] 24 | modId="minecraft" 25 | mandatory=true 26 | versionRange="[1.20.1,1.21)" 27 | ordering="NONE" 28 | side="BOTH" 29 | -------------------------------------------------------------------------------- /terrablender-bridge/build.gradle.kts: -------------------------------------------------------------------------------- 1 | import org.gradle.jvm.tasks.Jar 2 | 3 | plugins { 4 | id("dev.architectury.loom") 5 | } 6 | 7 | val versionForge: String by rootProject 8 | val relocateDirectory: Jar.(String, String) -> Unit by rootProject.extra 9 | 10 | repositories { 11 | maven("https://maven.minecraftforge.net") 12 | } 13 | 14 | dependencies { 15 | mappings(loom.officialMojangMappings()) 16 | neoForge("net.neoforged:neoforge:$versionForge") 17 | 18 | compileOnly(project(":extras-utils")) 19 | 20 | modImplementation(group = "org.sinytra", name = "forgified-fabric-loader", version = "2.5.29+0.16.0+1.21") 21 | 22 | modImplementation(group = "com.github.glitchfiend", name = "TerraBlender-forge", version = "1.20.1-3.0.0.167") 23 | } 24 | 25 | tasks.remapJar { 26 | relocateDirectory(this, "terrablender/api", "relocate/terrablender/api") 27 | } 28 | -------------------------------------------------------------------------------- /reach-entity-attributes/src/main/resources/META-INF/mods.toml: -------------------------------------------------------------------------------- 1 | modLoader="javafml" 2 | loaderVersion="[47,)" 3 | license="MIT" 4 | issueTrackerURL="https://github.com/Sinytra/ConnectorExtras/issues" 5 | 6 | [[mods]] 7 | modId="reach_entity_attributes" 8 | version="${file.jarVersion}" 9 | displayName="Reach Entity Attributes" 10 | authors="JamiesWhiteShirt, Chloe Dawn" 11 | displayURL="https://github.com/Sinytra/ConnectorExtras" 12 | description=''' 13 | Implements entity attributes for reach distance and attack range 14 | ''' 15 | displayTest = 'IGNORE_ALL_VERSION' 16 | [[dependencies.reach_entity_attributes]] 17 | modId="forge" 18 | mandatory=true 19 | versionRange="[47,)" 20 | ordering="NONE" 21 | side="BOTH" 22 | [[dependencies.reach_entity_attributes]] 23 | modId="minecraft" 24 | mandatory=true 25 | versionRange="[1.20.1,1.21)" 26 | ordering="NONE" 27 | side="BOTH" 28 | -------------------------------------------------------------------------------- /emi-bridge/src/main/resources/META-INF/neoforge.mods.toml: -------------------------------------------------------------------------------- 1 | modLoader="javafml" 2 | loaderVersion="*" 3 | license="MIT" 4 | issueTrackerURL="https://github.com/Sinytra/ConnectorExtras/issues" 5 | 6 | [[mods]] 7 | modId="connectorextras_emi_bridge" 8 | version="${file.jarVersion}" 9 | displayName="Connector Extras EMI Bridge" 10 | authors="Su5eD" 11 | displayURL="https://github.com/Sinytra/ConnectorExtras" 12 | description=''' 13 | Loads EMI plugins of Fabric mods on Forge. 14 | ''' 15 | displayTest = 'IGNORE_ALL_VERSION' 16 | [[mixins]] 17 | config="mixins.emibridge.json" 18 | [[dependencies.connectorextras_emi_bridge]] 19 | modId="neoforge" 20 | type="required" 21 | versionRange="*" 22 | ordering="NONE" 23 | side="BOTH" 24 | [[dependencies.connectorextras_emi_bridge]] 25 | modId="minecraft" 26 | type="required" 27 | versionRange="[1.21,1.22)" 28 | ordering="NONE" 29 | side="BOTH" 30 | -------------------------------------------------------------------------------- /jei-bridge/src/main/resources/META-INF/neoforge.mods.toml: -------------------------------------------------------------------------------- 1 | modLoader="javafml" 2 | loaderVersion="*" 3 | license="MIT" 4 | issueTrackerURL="https://github.com/Sinytra/ConnectorExtras/issues" 5 | 6 | [[mods]] 7 | modId="connectorextras_jei_bridge" 8 | version="${file.jarVersion}" 9 | displayName="Connector Extras JEI Bridge" 10 | authors="Su5eD" 11 | displayURL="https://github.com/Sinytra/ConnectorExtras" 12 | description=''' 13 | Loads JEI plugins of Fabric mods on Forge. 14 | ''' 15 | displayTest = 'IGNORE_ALL_VERSION' 16 | [[mixins]] 17 | config="mixins.jeibridge.json" 18 | [[dependencies.connectorextras_jei_bridge]] 19 | modId="neoforge" 20 | type="required" 21 | versionRange="*" 22 | ordering="NONE" 23 | side="BOTH" 24 | [[dependencies.connectorextras_jei_bridge]] 25 | modId="minecraft" 26 | type="required" 27 | versionRange="[1.21,1.22)" 28 | ordering="NONE" 29 | side="BOTH" 30 | -------------------------------------------------------------------------------- /terrablender-bridge/src/main/resources/META-INF/neoforge.mods.toml: -------------------------------------------------------------------------------- 1 | modLoader="javafml" 2 | loaderVersion="*" 3 | license="MIT" 4 | issueTrackerURL="https://github.com/Sinytra/ConnectorExtras/issues" 5 | 6 | [[mods]] 7 | modId="connectorextras_terrablender_bridge" 8 | version="${file.jarVersion}" 9 | displayName="Connector Extras Terrablender Bridge" 10 | authors="Su5eD" 11 | displayURL="https://github.com/Sinytra/ConnectorExtras" 12 | description=''' 13 | Loads TerraBlender Fabric API entrypoints of Fabric mods on Forge. 14 | ''' 15 | displayTest = 'IGNORE_ALL_VERSION' 16 | [[dependencies.connectorextras_terrablender_bridge]] 17 | modId="neoforge" 18 | type="required" 19 | versionRange="*" 20 | ordering="NONE" 21 | side="BOTH" 22 | [[dependencies.connectorextras_terrablender_bridge]] 23 | modId="minecraft" 24 | type="required" 25 | versionRange="[1.21,1.22)" 26 | ordering="NONE" 27 | side="BOTH" 28 | -------------------------------------------------------------------------------- /pehkui-bridge/src/main/resources/META-INF/neoforge.mods.toml: -------------------------------------------------------------------------------- 1 | modLoader="javafml" 2 | loaderVersion="*" 3 | license="MIT" 4 | issueTrackerURL="https://github.com/Sinytra/ConnectorExtras/issues" 5 | 6 | [[mods]] 7 | modId="connectorextras_pehkui_bridge" 8 | version="${file.jarVersion}" 9 | displayName="Connector Extras Pehkui Bridge" 10 | authors="Su5eD" 11 | displayURL="https://github.com/Sinytra/ConnectorExtras" 12 | description=''' 13 | Compatibility bridge for Pehkui's Fabric API on Forge 14 | ''' 15 | displayTest = 'IGNORE_ALL_VERSION' 16 | [[mixins]] 17 | config="mixins.pehkuibridge.json" 18 | [[dependencies.connectorextras_pehkui_bridge]] 19 | modId="neoforge" 20 | type="required" 21 | versionRange="*" 22 | ordering="NONE" 23 | side="BOTH" 24 | [[dependencies.connectorextras_pehkui_bridge]] 25 | modId="minecraft" 26 | type="required" 27 | versionRange="[1.21,1.22)" 28 | ordering="NONE" 29 | side="BOTH" 30 | -------------------------------------------------------------------------------- /kubejs-bridge/src/main/resources/META-INF/neoforge.mods.toml: -------------------------------------------------------------------------------- 1 | modLoader="javafml" 2 | loaderVersion="*" 3 | license="MIT" 4 | issueTrackerURL="https://github.com/Sinytra/ConnectorExtras/issues" 5 | 6 | [[mods]] 7 | modId="connectorextras_kubejs_bridge" 8 | version="${file.jarVersion}" 9 | displayName="Connector Extras KubeJS Bridge" 10 | authors="Su5eD" 11 | displayURL="https://github.com/Sinytra/ConnectorExtras" 12 | description=''' 13 | Provides KubeJS plugin support for Fabric mods on Forge 14 | ''' 15 | displayTest = 'IGNORE_ALL_VERSION' 16 | [[mixins]] 17 | config="mixins.connectorextras_kubejs_bridge.json" 18 | [[dependencies.connectorextras_kubejs_bridge]] 19 | modId="neoforge" 20 | type="required" 21 | versionRange="*" 22 | ordering="NONE" 23 | side="BOTH" 24 | [[dependencies.connectorextras_kubejs_bridge]] 25 | modId="minecraft" 26 | type="required" 27 | versionRange="[1.21,1.22)" 28 | ordering="NONE" 29 | side="BOTH" 30 | -------------------------------------------------------------------------------- /forgeconfigapiport/src/main/resources/META-INF/mods.toml: -------------------------------------------------------------------------------- 1 | modLoader="javafml" 2 | loaderVersion="[47,)" 3 | license="MPL-2.0" 4 | issueTrackerURL="https://github.com/Sinytra/ConnectorExtras/issues" 5 | 6 | [[mods]] 7 | modId="forgeconfigapiport" 8 | version="8.0.0" 9 | displayName="Forge Config API Port (ConnectorExtras)" 10 | authors="Su5eD" 11 | credits="Fuzs - upstream author" 12 | displayURL="https://github.com/Sinytra/ConnectorExtras" 13 | description=''' 14 | Forge's whole config system provided to the Fabric ecosystem. Designed for a multiloader architecture. 15 | ''' 16 | logoFile="mod_logo.png" 17 | displayTest = 'IGNORE_ALL_VERSION' 18 | 19 | [[dependencies.forgeconfigapiport]] 20 | modId="forge" 21 | mandatory=true 22 | versionRange="[47,)" 23 | ordering="NONE" 24 | side="BOTH" 25 | [[dependencies.forgeconfigapiport]] 26 | modId="minecraft" 27 | mandatory=true 28 | versionRange="[1.20.1,1.21)" 29 | ordering="NONE" 30 | side="BOTH" 31 | -------------------------------------------------------------------------------- /src/main/resources/META-INF/neoforge.mods.toml: -------------------------------------------------------------------------------- 1 | modLoader="javafml" 2 | loaderVersion="*" 3 | license="MIT" 4 | issueTrackerURL="https://github.com/Sinytra/ConnectorExtras/issues" 5 | 6 | [[mods]] 7 | modId="connectorextras" 8 | version="${file.jarVersion}" 9 | displayName="Connector Extras" 10 | authors="Su5eD" 11 | displayURL="https://github.com/Sinytra/ConnectorExtras" 12 | description=''' 13 | Integrating Connector with third-party APIs 14 | ''' 15 | displayTest = 'IGNORE_ALL_VERSION' 16 | [[dependencies.connectorextras]] 17 | modId="neoforge" 18 | type="required" 19 | versionRange="*" 20 | ordering="NONE" 21 | side="BOTH" 22 | [[dependencies.connectorextras]] 23 | modId="minecraft" 24 | type="required" 25 | versionRange="[1.21,1.22)" 26 | ordering="NONE" 27 | side="BOTH" 28 | [[dependencies.connectorextras_kubejs_bridge]] 29 | modId="connector" 30 | type="required" 31 | versionRange="*" 32 | ordering="NONE" 33 | side="BOTH" 34 | -------------------------------------------------------------------------------- /energy-bridge/src/main/resources/META-INF/neoforge.mods.toml: -------------------------------------------------------------------------------- 1 | modLoader="javafml" 2 | loaderVersion="*" 3 | license="MIT" 4 | issueTrackerURL="https://github.com/Sinytra/ConnectorExtras/issues" 5 | 6 | [[mods]] 7 | modId="connectorextras_energy_bridge" 8 | version="${file.jarVersion}" 9 | displayName="Connector Extras Energy Bridge" 10 | authors="Su5eD" 11 | displayURL="https://github.com/Sinytra/ConnectorExtras" 12 | description=''' 13 | A bridge between Forge Energy (FE) and Team Reborn's Energy API (E) that allows two-way conversion of energy units, for both BlockEntities and ItemStacks. 14 | ''' 15 | displayTest = 'IGNORE_ALL_VERSION' 16 | [[dependencies.connectorextras_energy_bridge]] 17 | modId="neoforge" 18 | type="required" 19 | versionRange="*" 20 | ordering="NONE" 21 | side="BOTH" 22 | [[dependencies.connectorextras_energy_bridge]] 23 | modId="minecraft" 24 | type="required" 25 | versionRange="[1.21,1.22)" 26 | ordering="NONE" 27 | side="BOTH" 28 | -------------------------------------------------------------------------------- /kubejs-bridge/build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | id("dev.architectury.loom") 3 | } 4 | 5 | val versionForge: String by rootProject 6 | 7 | repositories { 8 | maven { 9 | url = uri("https://maven.architectury.dev") 10 | content { 11 | includeGroup("dev.architectury") 12 | } 13 | } 14 | maven { 15 | url = uri("https://maven.saps.dev/minecraft") 16 | content { 17 | includeGroup("dev.latvian.mods") 18 | } 19 | } 20 | } 21 | 22 | dependencies { 23 | mappings(loom.officialMojangMappings()) 24 | neoForge("net.neoforged:neoforge:$versionForge") 25 | 26 | modImplementation("org.sinytra:connector:2.0.0-beta.1+1.21+dev-g2cf85c4") 27 | modImplementation("dev.latvian.mods:kubejs-neoforge:2100.7.0-build.120") 28 | modImplementation("dev.latvian.mods:rhino-neoforge:2006.2.4-build.17") 29 | modImplementation(group = "dev.architectury", name = "architectury-neoforge", version = "13.0.6") 30 | } 31 | -------------------------------------------------------------------------------- /rei-bridge/src/main/java/dev/su5ed/sinytra/connectorextras/reibridge/mixin/RoughlyEnoughItemsCoreMixin.java: -------------------------------------------------------------------------------- 1 | package dev.su5ed.sinytra.connectorextras.reibridge.mixin; 2 | 3 | import dev.su5ed.sinytra.connectorextras.reibridge.REIBridgeSetup; 4 | import me.shedaniel.rei.RoughlyEnoughItemsCore; 5 | import me.shedaniel.rei.impl.init.PluginDetector; 6 | import org.spongepowered.asm.mixin.Mixin; 7 | import org.spongepowered.asm.mixin.injection.At; 8 | import org.spongepowered.asm.mixin.injection.Inject; 9 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; 10 | 11 | @Mixin(RoughlyEnoughItemsCore.class) 12 | public class RoughlyEnoughItemsCoreMixin { 13 | 14 | @Inject(method = "onInitialize", at = @At("HEAD"), remap = false) 15 | private void initializeFabricPlugin(CallbackInfo ci) { 16 | PluginDetector detector = REIBridgeSetup.FABRIC_PLUGIN_DETECTOR.get(); 17 | detector.detectCommonPlugins(); 18 | detector.detectServerPlugins(); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /kubejs-bridge/src/main/java/dev/su5ed/sinytra/connectorextras/kubejs/mixin/ServerMainMixin.java: -------------------------------------------------------------------------------- 1 | package dev.su5ed.sinytra.connectorextras.kubejs.mixin; 2 | 3 | import dev.su5ed.sinytra.connectorextras.kubejs.KubeJSCompat; 4 | import dev.su5ed.sinytra.connectorextras.kubejs.KubeJSCompatSetup; 5 | import net.minecraft.server.Main; 6 | import org.spongepowered.asm.mixin.Mixin; 7 | import org.spongepowered.asm.mixin.injection.At; 8 | import org.spongepowered.asm.mixin.injection.Inject; 9 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; 10 | 11 | @Mixin(value = Main.class, priority = 100) 12 | public abstract class ServerMainMixin { 13 | @Inject(method = "main", at = @At(value = "INVOKE", target = "Lnet/neoforged/neoforge/server/loading/ServerModLoader;load()V"), remap = false) 14 | private static void kubejsBridgeEarlyInit(CallbackInfo ci) { 15 | if (KubeJSCompat.isEnabled()) { 16 | KubeJSCompatSetup.initFabricPlugins(); 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /rei-bridge/src/main/resources/META-INF/neoforge.mods.toml: -------------------------------------------------------------------------------- 1 | modLoader="javafml" 2 | loaderVersion="*" 3 | license="MIT" 4 | issueTrackerURL="https://github.com/Sinytra/ConnectorExtras/issues" 5 | 6 | [[mods]] 7 | modId="connectorextras_rei_bridge" 8 | version="${file.jarVersion}" 9 | displayName="Connector Extras REI Bridge" 10 | authors="Su5eD" 11 | displayURL="https://github.com/Sinytra/ConnectorExtras" 12 | description=''' 13 | Runs REI's Fabric plugin detector on Forge in addition to the default one, allowing it to load plugins from mods of both platforms at once. 14 | ''' 15 | displayTest = 'IGNORE_ALL_VERSION' 16 | [[mixins]] 17 | config="mixins.reibridge.json" 18 | [[dependencies.connectorextras_rei_bridge]] 19 | modId="neoforge" 20 | type="required" 21 | versionRange="*" 22 | ordering="NONE" 23 | side="BOTH" 24 | [[dependencies.connectorextras_rei_bridge]] 25 | modId="minecraft" 26 | type="required" 27 | versionRange="[1.21,1.22)" 28 | ordering="NONE" 29 | side="BOTH" 30 | -------------------------------------------------------------------------------- /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | name: Build 2 | on: [push, pull_request, merge_group] 3 | jobs: 4 | build: 5 | runs-on: ubuntu-22.04 6 | steps: 7 | - uses: actions/checkout@v3 8 | with: 9 | fetch-depth: 0 10 | - uses: actions/setup-java@v3 11 | with: 12 | distribution: 'microsoft' 13 | java-version: '21' 14 | - uses: gradle/actions/wrapper-validation@v3 15 | - name: Setup Gradle 16 | uses: gradle/actions/setup-gradle@v3 17 | with: 18 | gradle-home-cache-cleanup: true 19 | gradle-home-cache-excludes: | 20 | gradle.properties 21 | - name: Setup gradle.properties 22 | env: 23 | GRADLE_PROPERTIES: ${{ vars.GRADLE_PROPERTIES }} 24 | shell: bash 25 | run: | 26 | mkdir -p ~/.gradle/ 27 | echo "GRADLE_USER_HOME=${HOME}/.gradle" >> $GITHUB_ENV 28 | echo "${GRADLE_PROPERTIES}" > ~/.gradle/gradle.properties 29 | - run: ./gradlew build --stacktrace 30 | -------------------------------------------------------------------------------- /settings.gradle.kts: -------------------------------------------------------------------------------- 1 | pluginManagement { 2 | repositories { 3 | gradlePluginPortal() 4 | maven { 5 | name = "NeoForged" 6 | url = uri("https://maven.neoforged.net") 7 | } 8 | maven { 9 | name = "Architectury" 10 | url = uri("https://maven.architectury.dev") 11 | } 12 | maven { 13 | name = "FabricMC" 14 | url = uri("https://maven.fabricmc.net") 15 | } 16 | } 17 | plugins { 18 | id("org.gradle.toolchains.foojay-resolver-convention") version "0.5.0" 19 | } 20 | } 21 | 22 | rootProject.name = "ConnectorExtras" 23 | 24 | include( 25 | // "reach-entity-attributes", 26 | "rei-bridge", 27 | "energy-bridge", 28 | "intermediary-deobf", 29 | "emi-bridge", 30 | "terrablender-bridge", 31 | "modmenu-bridge", 32 | // "amecs-api", 33 | // "forgeconfigapiport", 34 | "extras-utils", 35 | "kubejs-bridge", 36 | "jei-bridge", 37 | "pehkui-bridge" 38 | ) 39 | -------------------------------------------------------------------------------- /rei-bridge/build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | id("dev.architectury.loom") 3 | } 4 | 5 | val versionForge: String by rootProject 6 | 7 | repositories { 8 | maven("https://maven.shedaniel.me") 9 | } 10 | 11 | dependencies { 12 | mappings(loom.officialMojangMappings()) 13 | neoForge("net.neoforged:neoforge:$versionForge") 14 | 15 | implementation(group = "org.sinytra", name = "forgified-fabric-loader", version = "2.5.29+0.16.0+1.21") 16 | modImplementation(group = "org.sinytra.forgified-fabric-api", name = "fabric-api-lookup-api-v1", version = "1.6.68+c21168c3d1") 17 | modImplementation(group = "org.sinytra.forgified-fabric-api", name = "fabric-transfer-api-v1", version = "5.1.16+7f12564fd1") 18 | 19 | modImplementation(group = "me.shedaniel", name = "RoughlyEnoughItems-neoforge", version = "16.0.744") 20 | modRuntimeOnly(group = "dev.architectury", name = "architectury-neoforge", version = "13.0.6") 21 | modRuntimeOnly(group = "me.shedaniel.cloth", name = "cloth-config-neoforge", version = "15.0.128") 22 | } 23 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Handle line endings automatically for files detected as text 2 | # and leave all files detected as binary untouched. 3 | * text=auto 4 | 5 | # 6 | # The above will handle all files NOT found below 7 | # 8 | # These files are text and should be normalized (Convert crlf => lf) 9 | *.css text 10 | *.df text 11 | *.htm text 12 | *.html text 13 | *.java text 14 | *.js text 15 | *.json text 16 | *.jsp text 17 | *.jspf text 18 | *.properties text 19 | *.sh text 20 | *.tld text 21 | *.txt text 22 | *.xml text 23 | 24 | # These files are binary and should be left untouched 25 | # (binary is a macro for -text -diff) 26 | *.class binary 27 | *.dll binary 28 | *.ear binary 29 | *.gif binary 30 | *.ico binary 31 | *.jar binary 32 | *.jpg binary 33 | *.jpeg binary 34 | *.png binary 35 | *.so binary 36 | *.war binary 37 | -------------------------------------------------------------------------------- /kubejs-bridge/src/main/java/dev/su5ed/sinytra/connectorextras/kubejs/mixin/MinecraftMixin.java: -------------------------------------------------------------------------------- 1 | package dev.su5ed.sinytra.connectorextras.kubejs.mixin; 2 | 3 | import dev.su5ed.sinytra.connectorextras.kubejs.KubeJSCompat; 4 | import dev.su5ed.sinytra.connectorextras.kubejs.KubeJSCompatSetup; 5 | import net.minecraft.client.Minecraft; 6 | import net.minecraft.client.main.GameConfig; 7 | import org.spongepowered.asm.mixin.Mixin; 8 | import org.spongepowered.asm.mixin.injection.At; 9 | import org.spongepowered.asm.mixin.injection.Inject; 10 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; 11 | 12 | @Mixin(value = Minecraft.class, priority = 100) 13 | public abstract class MinecraftMixin { 14 | @Inject(method = "", at = @At(value = "INVOKE", target = "Ljava/lang/Thread;currentThread()Ljava/lang/Thread;"), remap = false) 15 | private void kubejsBridgeEarlyInit(GameConfig gameConfig, CallbackInfo ci) { 16 | if (KubeJSCompat.isEnabled()) { 17 | KubeJSCompatSetup.initFabricPlugins(); 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /modmenu-bridge/src/main/java/com/terraformersmc/modmenu/config/option/StringSetConfigOption.java: -------------------------------------------------------------------------------- 1 | package com.terraformersmc.modmenu.config.option; 2 | 3 | import net.minecraft.text.Text; 4 | 5 | import java.util.Set; 6 | 7 | public class StringSetConfigOption { 8 | private final String key, translationKey; 9 | private final Set defaultValue; 10 | 11 | public StringSetConfigOption(String key, Set defaultValue) { 12 | super(); 13 | ConfigOptionStorage.setStringSet(key, defaultValue); 14 | this.key = key; 15 | this.translationKey = ""; 16 | this.defaultValue = defaultValue; 17 | } 18 | 19 | public String getKey() { 20 | return key; 21 | } 22 | 23 | public Set getValue() { 24 | return ConfigOptionStorage.getStringSet(key); 25 | } 26 | 27 | public void setValue(Set value) { 28 | ConfigOptionStorage.setStringSet(key, value); 29 | } 30 | 31 | public Text getMessage() { 32 | return Text.translatable(translationKey); 33 | } 34 | 35 | public Set getDefaultValue() { 36 | return defaultValue; 37 | } 38 | } -------------------------------------------------------------------------------- /reach-entity-attributes/LICENSE.md: -------------------------------------------------------------------------------- 1 | Copyright 2019 Erlend Åmdal 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | 5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | 7 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /forgeconfigapiport/src/main/java/dev/su5ed/sinytra/connectorextras/forgeconfigapiport/ForgeConfigPathsImpl.java: -------------------------------------------------------------------------------- 1 | package dev.su5ed.sinytra.connectorextras.forgeconfigapiport; 2 | 3 | import fuzs.forgeconfigapiport.api.config.v2.ForgeConfigPaths; 4 | import net.minecraft.server.MinecraftServer; 5 | import net.minecraftforge.fml.loading.FMLPaths; 6 | 7 | import java.nio.file.Path; 8 | 9 | public class ForgeConfigPathsImpl implements ForgeConfigPaths { 10 | @Override 11 | public Path getClientConfigDirectory() { 12 | return FMLPaths.CONFIGDIR.get(); 13 | } 14 | 15 | @Override 16 | public Path getCommonConfigDirectory() { 17 | return FMLPaths.CONFIGDIR.get(); 18 | } 19 | 20 | @Override 21 | public Path getServerConfigDirectory(MinecraftServer server) { 22 | return FMLPaths.CONFIGDIR.get(); 23 | } 24 | 25 | @Override 26 | public boolean forceGlobalServerConfigs() { 27 | return false; 28 | } 29 | 30 | @Override 31 | public Path getDefaultConfigsDirectory() { 32 | return FMLPaths.CONFIGDIR.get(); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /terrablender-bridge/src/main/java/terrablender/api/TerraBlenderApi.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) Glitchfiend 3 | * 4 | * This program is free software; you can redistribute it and/or 5 | * modify it under the terms of the GNU Lesser General Public 6 | * License as published by the Free Software Foundation; either 7 | * version 3 of the License, or (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | * Lesser General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU Lesser General Public License 15 | * along with this program; if not, write to the Free Software Foundation, 16 | * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 17 | */ 18 | package terrablender.api; 19 | 20 | /** 21 | * Called using the terrablender entrypoint. 22 | */ 23 | public interface TerraBlenderApi 24 | { 25 | default void onTerraBlenderInitialized() {} 26 | } -------------------------------------------------------------------------------- /terrablender-bridge/src/main/java/dev/su5ed/sinytra/connectorextras/terrablenderbridge/TerraBlenderBridge.java: -------------------------------------------------------------------------------- 1 | package dev.su5ed.sinytra.connectorextras.terrablenderbridge; 2 | 3 | import com.mojang.logging.LogUtils; 4 | import dev.su5ed.sinytra.connectorextras.util.HackyModuleInjector; 5 | import net.neoforged.bus.api.IEventBus; 6 | import net.neoforged.fml.common.Mod; 7 | import net.neoforged.fml.event.lifecycle.FMLCommonSetupEvent; 8 | import org.slf4j.Logger; 9 | 10 | @Mod("connectorextras_terrablender_bridge") 11 | public class TerraBlenderBridge { 12 | private static final Logger LOGGER = LogUtils.getLogger(); 13 | 14 | public TerraBlenderBridge(IEventBus bus) { 15 | LOGGER.info("Injecting TerraBlender API classes"); 16 | 17 | if (HackyModuleInjector.injectModuleSources("terrablender", TerraBlenderBridge.class.getResource("/relocate"))) { 18 | bus.addListener(TerraBlenderBridge::onCommonSetup); 19 | } 20 | } 21 | 22 | private static void onCommonSetup(FMLCommonSetupEvent event) { 23 | event.enqueueWork(TerraBlenderBridgeSetup::init); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /rei-bridge/src/main/java/dev/su5ed/sinytra/connectorextras/reibridge/mixin/client/RoughlyEnoughItemsCoreClientMixin.java: -------------------------------------------------------------------------------- 1 | package dev.su5ed.sinytra.connectorextras.reibridge.mixin.client; 2 | 3 | import dev.su5ed.sinytra.connectorextras.reibridge.REIBridgeSetup; 4 | import me.shedaniel.rei.RoughlyEnoughItemsCoreClient; 5 | import me.shedaniel.rei.impl.init.PluginDetector; 6 | import org.spongepowered.asm.mixin.Mixin; 7 | import org.spongepowered.asm.mixin.injection.At; 8 | import org.spongepowered.asm.mixin.injection.Inject; 9 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; 10 | 11 | @Mixin(RoughlyEnoughItemsCoreClient.class) 12 | public class RoughlyEnoughItemsCoreClientMixin { 13 | 14 | @Inject(method = "onInitializeClient", at = @At(value = "INVOKE", target = "Lme/shedaniel/rei/RoughlyEnoughItemsCore;getPluginDetector()Lme/shedaniel/rei/impl/init/PluginDetector;"), remap = false) 15 | private void initializeFabricPluginClient(CallbackInfo ci) { 16 | PluginDetector detector = REIBridgeSetup.FABRIC_PLUGIN_DETECTOR.get(); 17 | detector.detectClientPlugins().get().run(); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 Su5eD 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 all 13 | 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 THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /reach-entity-attributes/src/main/java/com/jamieswhiteshirt/reachentityattributes/mixin/ScreenHandlerMixin.java: -------------------------------------------------------------------------------- 1 | package com.jamieswhiteshirt.reachentityattributes.mixin; 2 | 3 | import com.jamieswhiteshirt.reachentityattributes.ReachEntityAttributes; 4 | import net.minecraft.block.Block; 5 | import net.minecraft.entity.player.PlayerEntity; 6 | import net.minecraft.screen.ScreenHandler; 7 | import org.spongepowered.asm.mixin.Mixin; 8 | import org.spongepowered.asm.mixin.injection.Constant; 9 | import org.spongepowered.asm.mixin.injection.ModifyConstant; 10 | 11 | @Mixin(ScreenHandler.class) 12 | abstract class ScreenHandlerMixin { 13 | @ModifyConstant( 14 | method = "method_17696(Lnet/minecraft/block/Block;Lnet/minecraft/entity/player/PlayerEntity;Lnet/minecraft/world/World;Lnet/minecraft/util/math/BlockPos;)Ljava/lang/Boolean;", 15 | require = 0, allow = 1, constant = @Constant(doubleValue = 64.0)) 16 | private static double getActualReachDistance(final double reachDistance, final Block block, final PlayerEntity player) { 17 | return ReachEntityAttributes.getSquaredReachDistance(player, reachDistance); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /emi-bridge/build.gradle.kts: -------------------------------------------------------------------------------- 1 | import org.gradle.jvm.tasks.Jar 2 | 3 | plugins { 4 | id("dev.architectury.loom") 5 | } 6 | 7 | val versionForge: String by rootProject 8 | val relocateDirectory: Jar.(String, String) -> Unit by rootProject.extra 9 | 10 | repositories { 11 | maven("https://maven.terraformersmc.com/releases") 12 | } 13 | 14 | dependencies { 15 | mappings(loom.officialMojangMappings()) 16 | neoForge("net.neoforged:neoforge:$versionForge") 17 | 18 | compileOnly(project(":extras-utils")) 19 | 20 | implementation(group = "org.sinytra", name = "forgified-fabric-loader", version = "2.5.29+0.16.0+1.21") 21 | modImplementation(group = "org.sinytra.forgified-fabric-api", name = "fabric-api-lookup-api-v1", version = "1.6.68+c21168c3d1") 22 | modImplementation(group = "org.sinytra.forgified-fabric-api", name = "fabric-transfer-api-v1", version = "5.1.16+7f12564fd1") 23 | 24 | modImplementation(group = "dev.emi", name = "emi-neoforge", version = "1.1.10+1.21") 25 | } 26 | 27 | tasks.remapJar { 28 | // Painfully move dev/emi into relocate/dev/emi - gradle does NOT make this easy ... 29 | relocateDirectory(this, "dev/emi", "relocate/dev/emi") 30 | } 31 | -------------------------------------------------------------------------------- /modmenu-bridge/src/main/resources/META-INF/neoforge.mods.toml: -------------------------------------------------------------------------------- 1 | modLoader="javafml" 2 | loaderVersion="*" 3 | license="MIT" 4 | issueTrackerURL="https://github.com/Sinytra/ConnectorExtras/issues" 5 | 6 | [[mods]] 7 | modId="connectorextras_modmenu_bridge" 8 | version="${file.jarVersion}" 9 | displayName="Connector Extras ModMenu Bridge" 10 | authors="Su5eD" 11 | displayURL="https://github.com/Sinytra/ConnectorExtras" 12 | description=''' 13 | Integrates ModMenu the config screen factory with Forge's mod list gui. 14 | ''' 15 | displayTest = 'IGNORE_ALL_VERSION' 16 | 17 | [[mods]] 18 | modId = "modmenu" 19 | version = "11.0.1" 20 | displayName = "ModMenu (Connector Extras)" 21 | description = ''' 22 | Dummy mod provided by Connector Extras to allow mods detecting ModMenu to function as expected. 23 | ''' 24 | [[mixins]] 25 | config="mixins.connectorextras_modmenu_bridge.json" 26 | [[dependencies.connectorextras_modmenu_bridge]] 27 | modId="neoforge" 28 | type="required" 29 | versionRange="*" 30 | ordering="NONE" 31 | side="BOTH" 32 | [[dependencies.connectorextras_modmenu_bridge]] 33 | modId="minecraft" 34 | type="required" 35 | versionRange="[1.21,1.22)" 36 | ordering="NONE" 37 | side="BOTH" 38 | -------------------------------------------------------------------------------- /kubejs-bridge/src/main/java/dev/su5ed/sinytra/connectorextras/kubejs/KubeJSCompatMixinPlugin.java: -------------------------------------------------------------------------------- 1 | package dev.su5ed.sinytra.connectorextras.kubejs; 2 | 3 | import org.objectweb.asm.tree.ClassNode; 4 | import org.spongepowered.asm.mixin.extensibility.IMixinConfigPlugin; 5 | import org.spongepowered.asm.mixin.extensibility.IMixinInfo; 6 | 7 | import java.util.List; 8 | import java.util.Set; 9 | 10 | public class KubeJSCompatMixinPlugin implements IMixinConfigPlugin { 11 | @Override 12 | public void onLoad(String s) {} 13 | 14 | @Override 15 | public String getRefMapperConfig() { 16 | return null; 17 | } 18 | 19 | @Override 20 | public boolean shouldApplyMixin(String s, String s1) { 21 | return KubeJSCompat.isEnabled(); 22 | } 23 | 24 | @Override 25 | public void acceptTargets(Set set, Set set1) { 26 | 27 | } 28 | 29 | @Override 30 | public List getMixins() { 31 | return null; 32 | } 33 | 34 | @Override 35 | public void preApply(String s, ClassNode classNode, String s1, IMixinInfo iMixinInfo) { 36 | 37 | } 38 | 39 | @Override 40 | public void postApply(String s, ClassNode classNode, String s1, IMixinInfo iMixinInfo) { 41 | 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /reach-entity-attributes/src/main/java/com/jamieswhiteshirt/reachentityattributes/mixin/ForgingScreenHandlerMixin.java: -------------------------------------------------------------------------------- 1 | package com.jamieswhiteshirt.reachentityattributes.mixin; 2 | 3 | import com.jamieswhiteshirt.reachentityattributes.ReachEntityAttributes; 4 | import net.minecraft.entity.player.PlayerEntity; 5 | import net.minecraft.screen.ForgingScreenHandler; 6 | import net.minecraft.screen.ScreenHandler; 7 | import net.minecraft.screen.ScreenHandlerType; 8 | import org.spongepowered.asm.mixin.Mixin; 9 | import org.spongepowered.asm.mixin.injection.Constant; 10 | import org.spongepowered.asm.mixin.injection.ModifyConstant; 11 | 12 | @Mixin(ForgingScreenHandler.class) 13 | abstract class ForgingScreenHandlerMixin extends ScreenHandler { 14 | ForgingScreenHandlerMixin(final ScreenHandlerType type, final int id) { 15 | super(type, id); 16 | } 17 | 18 | @ModifyConstant( 19 | method = "method_24924(Lnet/minecraft/entity/player/PlayerEntity;Lnet/minecraft/world/World;Lnet/minecraft/util/math/BlockPos;)Ljava/lang/Boolean;", 20 | require = 0, allow = 1, constant = @Constant(doubleValue = 64.0)) 21 | private double getActualReachDistance(final double reachDistance, final PlayerEntity player) { 22 | return ReachEntityAttributes.getSquaredReachDistance(player, reachDistance); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /reach-entity-attributes/src/main/java/com/jamieswhiteshirt/reachentityattributes/mixin/client/GameRendererMixin.java: -------------------------------------------------------------------------------- 1 | package com.jamieswhiteshirt.reachentityattributes.mixin.client; 2 | 3 | import com.jamieswhiteshirt.reachentityattributes.ReachEntityAttributes; 4 | import net.minecraft.client.MinecraftClient; 5 | import net.minecraft.client.render.GameRenderer; 6 | import net.minecraft.resource.SynchronousResourceReloader; 7 | import org.spongepowered.asm.mixin.Final; 8 | import org.spongepowered.asm.mixin.Mixin; 9 | import org.spongepowered.asm.mixin.Shadow; 10 | import org.spongepowered.asm.mixin.injection.At; 11 | import org.spongepowered.asm.mixin.injection.ModifyVariable; 12 | 13 | @Mixin(GameRenderer.class) 14 | abstract class GameRendererMixin implements SynchronousResourceReloader/*, AutoCloseable*/ { 15 | @Shadow @Final MinecraftClient client; 16 | 17 | @ModifyVariable(method = "updateTargetedEntity(F)V", at = @At(value = "INVOKE", target = "Lnet/minecraft/util/math/Vec3d;squaredDistanceTo(Lnet/minecraft/util/math/Vec3d;)D", ordinal = 1), ordinal = 4) 18 | private double getActualAttackRange1(final double entityReach) { 19 | if (this.client.player != null) { 20 | return ReachEntityAttributes.getAttackRange(this.client.player, entityReach); 21 | } 22 | return entityReach; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /jei-bridge/src/main/java/dev/su5ed/sinytra/connectorextras/jeibridge/mixin/ForgePluginFinderMixin.java: -------------------------------------------------------------------------------- 1 | package dev.su5ed.sinytra.connectorextras.jeibridge.mixin; 2 | 3 | import com.llamalad7.mixinextras.injector.ModifyReturnValue; 4 | import mezz.jei.api.IModPlugin; 5 | import mezz.jei.neoforge.startup.ForgePluginFinder; 6 | import net.fabricmc.loader.api.FabricLoader; 7 | import net.fabricmc.loader.api.entrypoint.EntrypointContainer; 8 | import org.spongepowered.asm.mixin.Mixin; 9 | import org.spongepowered.asm.mixin.injection.At; 10 | 11 | import java.util.ArrayList; 12 | import java.util.List; 13 | 14 | @Mixin(ForgePluginFinder.class) 15 | public abstract class ForgePluginFinderMixin { 16 | @ModifyReturnValue(method = "getModPlugins", at = @At("RETURN"), remap = false) 17 | private static List connectorextras_jei_bridge$addFabricPlugins(List forgePlugins) { 18 | List fabricPlugins = FabricLoader.getInstance() 19 | .getEntrypointContainers("jei_mod_plugin", IModPlugin.class) 20 | .stream() 21 | .map(EntrypointContainer::getEntrypoint) 22 | .toList(); 23 | List merged = new ArrayList<>(); 24 | merged.addAll(forgePlugins); 25 | merged.addAll(fabricPlugins); 26 | return merged; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /amecs-api/src/main/java/de/siphalor/amecs/impl/AmecsAPI.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2023 Siphalor 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package de.siphalor.amecs.impl; 18 | 19 | import de.siphalor.amecs.api.KeyModifiers; 20 | import net.minecraftforge.fml.common.Mod; 21 | import org.jetbrains.annotations.ApiStatus; 22 | 23 | @ApiStatus.Internal 24 | public class AmecsAPI { 25 | public static final String MOD_ID = "amecsapi"; 26 | public static final String MOD_NAME = "Amecs API"; 27 | 28 | public static final KeyModifiers CURRENT_MODIFIERS = new KeyModifiers(); 29 | 30 | // this is used by KTIG 31 | public static boolean TRIGGER_KEYBINDING_ON_SCROLL = true; 32 | 33 | public static String makeKeyID(String keyName) { 34 | return "key." + MOD_ID + "." + keyName; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /kubejs-bridge/src/main/java/dev/su5ed/sinytra/connectorextras/kubejs/mixin/KubeJSMixin.java: -------------------------------------------------------------------------------- 1 | package dev.su5ed.sinytra.connectorextras.kubejs.mixin; 2 | 3 | import dev.architectury.platform.Mod; 4 | import dev.latvian.mods.kubejs.KubeJS; 5 | import dev.latvian.mods.kubejs.plugin.KubeJSPlugin; 6 | import dev.su5ed.sinytra.connectorextras.kubejs.KubeJSCompatSetup; 7 | import org.spongepowered.asm.mixin.Mixin; 8 | import org.spongepowered.asm.mixin.injection.At; 9 | import org.spongepowered.asm.mixin.injection.ModifyArg; 10 | import org.spongepowered.asm.mixin.injection.Redirect; 11 | 12 | import java.util.List; 13 | import java.util.function.Consumer; 14 | 15 | @Mixin(KubeJS.class) 16 | public abstract class KubeJSMixin { 17 | 18 | @ModifyArg(method = "", at = @At(value = "INVOKE", target = "Ldev/latvian/mods/kubejs/plugin/KubeJSPlugins;load(Ljava/util/List;Z)V")) 19 | private List removeInitializedMods(List mods) { 20 | return mods.stream().filter(m -> !KubeJSCompatSetup.loadedMods.contains(m.getModId())).toList(); 21 | } 22 | 23 | @Redirect(method = "", at = @At(value = "INVOKE", target = "Ldev/latvian/mods/kubejs/plugin/KubeJSPlugins;forEachPlugin(Ljava/util/function/Consumer;)V")) 24 | private void initNeoForgePlugins(Consumer callback) { 25 | KubeJSCompatSetup.forForgePluginsOnly(callback); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /amecs-api/src/main/java/de/siphalor/amecs/impl/mixin/KeyMappingLookupAccessor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2023 Siphalor 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package de.siphalor.amecs.impl.mixin; 18 | 19 | import net.minecraft.client.option.KeyBinding; 20 | import net.minecraft.client.util.InputUtil; 21 | import net.minecraftforge.client.settings.KeyMappingLookup; 22 | import net.minecraftforge.client.settings.KeyModifier; 23 | import org.spongepowered.asm.mixin.Mixin; 24 | import org.spongepowered.asm.mixin.gen.Accessor; 25 | 26 | import java.util.Collection; 27 | import java.util.EnumMap; 28 | import java.util.Map; 29 | 30 | @Mixin(KeyMappingLookup.class) 31 | public interface KeyMappingLookupAccessor { 32 | @Accessor 33 | EnumMap>> getMap(); 34 | } 35 | -------------------------------------------------------------------------------- /emi-bridge/src/main/java/dev/su5ed/sinytra/connectorextras/emibridge/mixin/EmiAgnosForgeMixin.java: -------------------------------------------------------------------------------- 1 | package dev.su5ed.sinytra.connectorextras.emibridge.mixin; 2 | 3 | import dev.emi.emi.api.EmiPlugin; 4 | import dev.emi.emi.platform.neoforge.EmiAgnosNeoForge; 5 | import dev.emi.emi.registry.EmiPluginContainer; 6 | import net.fabricmc.loader.api.FabricLoader; 7 | import org.spongepowered.asm.mixin.Mixin; 8 | import org.spongepowered.asm.mixin.injection.At; 9 | import org.spongepowered.asm.mixin.injection.ModifyVariable; 10 | 11 | import java.util.List; 12 | import java.util.Set; 13 | import java.util.stream.Collectors; 14 | 15 | @Mixin(EmiAgnosNeoForge.class) 16 | public class EmiAgnosForgeMixin { 17 | 18 | @ModifyVariable(method = "getPluginsAgnos", at = @At("RETURN"), remap = false) 19 | private List connectorextras_emi_bridge$addFabricPlugins(List orig) { 20 | Set ids = orig.stream().map(EmiPluginContainer::id).collect(Collectors.toSet()); 21 | orig.addAll(FabricLoader.getInstance() 22 | .getEntrypointContainers("emi", EmiPlugin.class) 23 | .stream() 24 | .filter(plugin -> !ids.contains(plugin.getProvider().getMetadata().getId())) 25 | .map(p -> new EmiPluginContainer(p.getEntrypoint(), p.getProvider().getMetadata().getId())) 26 | .toList()); 27 | return orig; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /amecs-api/src/main/java/de/siphalor/amecs/api/input/InputEventHandler.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2023 Siphalor 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package de.siphalor.amecs.api.input; 18 | 19 | import net.fabricmc.api.EnvType; 20 | import net.fabricmc.api.Environment; 21 | import net.minecraft.client.MinecraftClient; 22 | 23 | /** 24 | * This interface is used for input event handling and is (un-)registered in {@link InputHandlerManager} 25 | * 26 | * @see #handleInput 27 | * @see InputHandlerManager 28 | */ 29 | @Environment(EnvType.CLIENT) 30 | public interface InputEventHandler { 31 | 32 | /** 33 | * This method is called from {@link InputHandlerManager#handleInputEvents(MinecraftClient)} 34 | * 35 | * @see InputHandlerManager#handleInputEvents(MinecraftClient) 36 | * 37 | * @param client 38 | */ 39 | public void handleInput(MinecraftClient client); 40 | 41 | } 42 | -------------------------------------------------------------------------------- /reach-entity-attributes/src/main/java/com/jamieswhiteshirt/reachentityattributes/mixin/PlayerEntityInteractionHandlerMixin.java: -------------------------------------------------------------------------------- 1 | package com.jamieswhiteshirt.reachentityattributes.mixin; 2 | 3 | import com.jamieswhiteshirt.reachentityattributes.ReachEntityAttributes; 4 | import net.minecraft.entity.Entity; 5 | import net.minecraft.network.packet.c2s.play.PlayerInteractEntityC2SPacket; 6 | import net.minecraft.server.network.ServerPlayNetworkHandler; 7 | import org.spongepowered.asm.mixin.Final; 8 | import org.spongepowered.asm.mixin.Mixin; 9 | import org.spongepowered.asm.mixin.Shadow; 10 | import org.spongepowered.asm.mixin.injection.At; 11 | import org.spongepowered.asm.mixin.injection.Inject; 12 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; 13 | 14 | @Mixin(targets = "net.minecraft.server.network.ServerPlayNetworkHandler$1") 15 | abstract class PlayerEntityInteractionHandlerMixin implements PlayerInteractEntityC2SPacket.Handler { 16 | @Shadow(aliases = "field_28963") @Final private ServerPlayNetworkHandler field_28963; 17 | @Shadow(aliases = {"field_28962", "val$entity"}) @Final private Entity field_28962; 18 | 19 | @Inject(method = "attack()V", at = @At("HEAD"), require = 1, allow = 1, cancellable = true) 20 | private void ensureWithinAttackRange(final CallbackInfo ci) { 21 | if (!ReachEntityAttributes.isWithinAttackRange(this.field_28963.player, this.field_28962)) { 22 | ci.cancel(); 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /modmenu-bridge/src/main/java/com/terraformersmc/modmenu/api/ConfigScreenFactory.java: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2018-2020 Prospector 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | package com.terraformersmc.modmenu.api; 25 | 26 | import net.minecraft.client.gui.screen.Screen; 27 | 28 | @FunctionalInterface 29 | public interface ConfigScreenFactory { 30 | S create(Screen parent); 31 | } -------------------------------------------------------------------------------- /kubejs-bridge/src/main/java/dev/su5ed/sinytra/connectorextras/kubejs/KubeJSCompatSetup.java: -------------------------------------------------------------------------------- 1 | package dev.su5ed.sinytra.connectorextras.kubejs; 2 | 3 | import dev.latvian.mods.kubejs.plugin.KubeJSPlugin; 4 | import dev.latvian.mods.kubejs.plugin.KubeJSPlugins; 5 | import net.neoforged.fml.loading.FMLEnvironment; 6 | import net.neoforged.neoforgespi.language.IModInfo; 7 | import net.neoforged.neoforgespi.locating.IModFile; 8 | import org.sinytra.connector.ConnectorEarlyLoader; 9 | 10 | import java.util.List; 11 | import java.util.function.Consumer; 12 | 13 | public class KubeJSCompatSetup { 14 | public static List loadedMods; 15 | public static List fabricPlugins; 16 | 17 | public static void initFabricPlugins() { 18 | List mods = ConnectorEarlyLoader.getConnectorMods(); 19 | loadedMods = mods.stream().map(IModInfo::getModId).toList(); 20 | List files = mods.stream().map(m -> m.getOwningFile().getFile()).toList(); 21 | 22 | KubeJSPlugins.load(files, FMLEnvironment.dist.isClient()); 23 | fabricPlugins = List.copyOf(KubeJSPlugins.getAll()); 24 | 25 | KubeJSPlugins.forEachPlugin(KubeJSPlugin::init); 26 | KubeJSPlugins.forEachPlugin(KubeJSPlugin::initStartup); 27 | } 28 | 29 | public static void forForgePluginsOnly(Consumer callback) { 30 | KubeJSPlugins.forEachPlugin(plugin -> { 31 | if (!fabricPlugins.contains(plugin)) { 32 | callback.accept(plugin); 33 | } 34 | }); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /amecs-api/src/main/java/de/siphalor/amecs/impl/mixin/MixinMinecraftClient.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2023 Siphalor 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package de.siphalor.amecs.impl.mixin; 18 | 19 | import org.spongepowered.asm.mixin.Mixin; 20 | import org.spongepowered.asm.mixin.injection.At; 21 | import org.spongepowered.asm.mixin.injection.Inject; 22 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; 23 | 24 | import de.siphalor.amecs.api.input.InputHandlerManager; 25 | import net.fabricmc.api.EnvType; 26 | import net.fabricmc.api.Environment; 27 | import net.minecraft.client.MinecraftClient; 28 | 29 | @Environment(EnvType.CLIENT) 30 | @Mixin(value = MinecraftClient.class, priority = 50) 31 | public abstract class MixinMinecraftClient { 32 | 33 | @Inject(method = "handleInputEvents()V", at = @At(value = "HEAD")) 34 | private void handleInputEvents(CallbackInfo ci) { 35 | InputHandlerManager.handleInputEvents((MinecraftClient) (Object) this); 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /reach-entity-attributes/src/main/java/com/jamieswhiteshirt/reachentityattributes/mixin/ChestStateManagerMixin.java: -------------------------------------------------------------------------------- 1 | package com.jamieswhiteshirt.reachentityattributes.mixin; 2 | 3 | import com.jamieswhiteshirt.reachentityattributes.ReachEntityAttributes; 4 | import net.minecraft.block.entity.ViewerCountManager; 5 | import net.minecraft.entity.player.PlayerEntity; 6 | import net.minecraft.util.math.BlockPos; 7 | import net.minecraft.world.World; 8 | import org.objectweb.asm.Opcodes; 9 | import org.spongepowered.asm.mixin.Mixin; 10 | import org.spongepowered.asm.mixin.Shadow; 11 | import org.spongepowered.asm.mixin.injection.At; 12 | import org.spongepowered.asm.mixin.injection.Redirect; 13 | 14 | @Mixin(ViewerCountManager.class) 15 | abstract class ChestStateManagerMixin { 16 | @Shadow 17 | protected abstract boolean isPlayerViewing(final PlayerEntity player); 18 | 19 | @Redirect( 20 | method = "updateViewerCount(Lnet/minecraft/world/World;Lnet/minecraft/util/math/BlockPos;Lnet/minecraft/block/BlockState;)V", 21 | require = 1, allow = 1, 22 | at = @At(value = "INVOKE", opcode = Opcodes.INVOKEVIRTUAL, 23 | target = "Lnet/minecraft/block/entity/ViewerCountManager;getInRangeViewerCount(Lnet/minecraft/world/World;Lnet/minecraft/util/math/BlockPos;)I")) 24 | private int getReachAccountingOpenCount(final ViewerCountManager manager, final World world, final BlockPos pos) { 25 | return ReachEntityAttributes.getPlayersWithinReach(this::isPlayerViewing, world, pos.getX(), pos.getY(), pos.getZ(), 5.0).size(); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: Release 2 | 3 | on: 4 | workflow_dispatch: 5 | inputs: 6 | release_type: 7 | description: 'The published artifact release type' 8 | required: false 9 | default: 'STABLE' 10 | type: choice 11 | options: 12 | - STABLE 13 | - BETA 14 | - ALPHA 15 | 16 | permissions: 17 | actions: read 18 | contents: write 19 | 20 | jobs: 21 | build: 22 | runs-on: ubuntu-22.04 23 | steps: 24 | - uses: actions/checkout@v3 25 | with: 26 | fetch-depth: 0 27 | - uses: FabricMC/fabric-action-scripts@v2 28 | id: changelog 29 | with: 30 | context: changelog 31 | workflow_id: release.yml 32 | - uses: actions/setup-java@v3 33 | with: 34 | distribution: 'microsoft' 35 | java-version: '21' 36 | - uses: gradle/actions/wrapper-validation@v3 37 | - name: Setup Gradle 38 | uses: gradle/actions/setup-gradle@v3 39 | with: 40 | gradle-home-cache-cleanup: true 41 | gradle-home-cache-excludes: | 42 | gradle.properties 43 | - name: Build with Gradle 44 | run: ./gradlew clean build publishMods --stacktrace 45 | env: 46 | PUBLISH_RELEASE_TYPE: ${{ inputs.release_type }} 47 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 48 | CURSEFORGE_TOKEN: ${{ secrets.CURSEFORGE_TOKEN }} 49 | MODRINTH_TOKEN: ${{ secrets.MODRINTH_TOKEN }} 50 | CHANGELOG: ${{ steps.changelog.outputs.changelog }} 51 | -------------------------------------------------------------------------------- /emi-bridge/src/main/java/dev/su5ed/sinytra/connectorextras/emibridge/EMIBridgeMixinPlugin.java: -------------------------------------------------------------------------------- 1 | package dev.su5ed.sinytra.connectorextras.emibridge; 2 | 3 | import com.google.common.base.Suppliers; 4 | import net.neoforged.fml.loading.LoadingModList; 5 | import org.objectweb.asm.tree.ClassNode; 6 | import org.spongepowered.asm.mixin.extensibility.IMixinConfigPlugin; 7 | import org.spongepowered.asm.mixin.extensibility.IMixinInfo; 8 | 9 | import java.util.List; 10 | import java.util.Set; 11 | import java.util.function.Supplier; 12 | 13 | public class EMIBridgeMixinPlugin implements IMixinConfigPlugin { 14 | private static final Supplier EMI_LOADED = Suppliers.memoize(() -> LoadingModList.get().getModFileById(EMIBridge.EMI_MODID) != null); 15 | 16 | @Override 17 | public void onLoad(String mixinPackage) {} 18 | 19 | @Override 20 | public String getRefMapperConfig() { 21 | return null; 22 | } 23 | 24 | @Override 25 | public boolean shouldApplyMixin(String targetClassName, String mixinClassName) { 26 | return EMI_LOADED.get(); 27 | } 28 | 29 | @Override 30 | public List getMixins() { 31 | return null; 32 | } 33 | 34 | @Override 35 | public void acceptTargets(Set myTargets, Set otherTargets) {} 36 | 37 | @Override 38 | public void preApply(String targetClassName, ClassNode targetClass, String mixinClassName, IMixinInfo mixinInfo) {} 39 | 40 | @Override 41 | public void postApply(String targetClassName, ClassNode targetClass, String mixinClassName, IMixinInfo mixinInfo) {} 42 | } 43 | -------------------------------------------------------------------------------- /jei-bridge/src/main/java/dev/su5ed/sinytra/connectorextras/jeibridge/JEIBridgeMixinPlugin.java: -------------------------------------------------------------------------------- 1 | package dev.su5ed.sinytra.connectorextras.jeibridge; 2 | 3 | import com.google.common.base.Suppliers; 4 | import net.neoforged.fml.loading.LoadingModList; 5 | import org.objectweb.asm.tree.ClassNode; 6 | import org.spongepowered.asm.mixin.extensibility.IMixinConfigPlugin; 7 | import org.spongepowered.asm.mixin.extensibility.IMixinInfo; 8 | 9 | import java.util.List; 10 | import java.util.Set; 11 | import java.util.function.Supplier; 12 | 13 | public class JEIBridgeMixinPlugin implements IMixinConfigPlugin { 14 | private static final Supplier JEI_LOADED = Suppliers.memoize(() -> LoadingModList.get().getModFileById(JEIBridge.JEI_MODID) != null); 15 | 16 | @Override 17 | public void onLoad(String mixinPackage) {} 18 | 19 | @Override 20 | public String getRefMapperConfig() { 21 | return null; 22 | } 23 | 24 | @Override 25 | public boolean shouldApplyMixin(String targetClassName, String mixinClassName) { 26 | return JEI_LOADED.get(); 27 | } 28 | 29 | @Override 30 | public List getMixins() { 31 | return null; 32 | } 33 | 34 | @Override 35 | public void acceptTargets(Set myTargets, Set otherTargets) {} 36 | 37 | @Override 38 | public void preApply(String targetClassName, ClassNode targetClass, String mixinClassName, IMixinInfo mixinInfo) {} 39 | 40 | @Override 41 | public void postApply(String targetClassName, ClassNode targetClass, String mixinClassName, IMixinInfo mixinInfo) {} 42 | } 43 | -------------------------------------------------------------------------------- /rei-bridge/src/main/java/dev/su5ed/sinytra/connectorextras/reibridge/REIBridgeMixinPlugin.java: -------------------------------------------------------------------------------- 1 | package dev.su5ed.sinytra.connectorextras.reibridge; 2 | 3 | import com.google.common.base.Suppliers; 4 | import net.neoforged.fml.loading.LoadingModList; 5 | import org.objectweb.asm.tree.ClassNode; 6 | import org.spongepowered.asm.mixin.extensibility.IMixinConfigPlugin; 7 | import org.spongepowered.asm.mixin.extensibility.IMixinInfo; 8 | 9 | import java.util.List; 10 | import java.util.Set; 11 | import java.util.function.Supplier; 12 | 13 | public class REIBridgeMixinPlugin implements IMixinConfigPlugin { 14 | private static final Supplier REI_LOADED = Suppliers.memoize(() -> LoadingModList.get().getModFileById(REIBridge.REI_MODID) != null); 15 | 16 | @Override 17 | public void onLoad(String mixinPackage) {} 18 | 19 | @Override 20 | public String getRefMapperConfig() { 21 | return null; 22 | } 23 | 24 | @Override 25 | public boolean shouldApplyMixin(String targetClassName, String mixinClassName) { 26 | return REI_LOADED.get(); 27 | } 28 | 29 | @Override 30 | public List getMixins() { 31 | return null; 32 | } 33 | 34 | @Override 35 | public void acceptTargets(Set myTargets, Set otherTargets) {} 36 | 37 | @Override 38 | public void preApply(String targetClassName, ClassNode targetClass, String mixinClassName, IMixinInfo mixinInfo) {} 39 | 40 | @Override 41 | public void postApply(String targetClassName, ClassNode targetClass, String mixinClassName, IMixinInfo mixinInfo) {} 42 | } 43 | -------------------------------------------------------------------------------- /energy-bridge/src/main/java/dev/su5ed/sinytra/connectorextras/energybridge/EnergyBridgeConfig.java: -------------------------------------------------------------------------------- 1 | package dev.su5ed.sinytra.connectorextras.energybridge; 2 | 3 | import net.neoforged.neoforge.common.ModConfigSpec; 4 | import org.apache.commons.lang3.tuple.Pair; 5 | 6 | public final class EnergyBridgeConfig { 7 | public static final ModConfigSpec COMMON_SPEC; 8 | 9 | public static final Common COMMON; 10 | 11 | static { 12 | Pair commonPair = new ModConfigSpec.Builder().configure(Common::new); 13 | COMMON = commonPair.getLeft(); 14 | COMMON_SPEC = commonPair.getRight(); 15 | } 16 | 17 | private EnergyBridgeConfig() { 18 | } 19 | 20 | public static final class Common { 21 | public final ModConfigSpec.IntValue fabricToForgeEnergy; 22 | public final ModConfigSpec.IntValue forgeToFabricEnergy; 23 | 24 | private Common(ModConfigSpec.Builder builder) { 25 | builder.push("general"); 26 | this.fabricToForgeEnergy = builder 27 | .comment("The amount of FE (Forge Energy) converted from 1 E (Team Reborn Energy). Setting the value to 0 disables this conversion.") 28 | .defineInRange("fabricToForgeEnergy", 10, 0, Integer.MAX_VALUE); 29 | this.forgeToFabricEnergy = builder 30 | .comment("The amount of FE (Forge Energy) required for 1 E (Team Reborn Energy). Setting the value to 0 disables this conversion.") 31 | .defineInRange("forgeToFabricEnergy", 10, 0, Integer.MAX_VALUE); 32 | builder.pop(); 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /pehkui-bridge/src/main/java/dev/su5ed/sinytra/connectorextras/pehkuibridge/PehkuiBridgeMixinPlugin.java: -------------------------------------------------------------------------------- 1 | package dev.su5ed.sinytra.connectorextras.pehkuibridge; 2 | 3 | import com.google.common.base.Suppliers; 4 | import net.neoforged.fml.loading.LoadingModList; 5 | import org.objectweb.asm.tree.ClassNode; 6 | import org.spongepowered.asm.mixin.extensibility.IMixinConfigPlugin; 7 | import org.spongepowered.asm.mixin.extensibility.IMixinInfo; 8 | 9 | import java.util.List; 10 | import java.util.Set; 11 | import java.util.function.Supplier; 12 | 13 | public class PehkuiBridgeMixinPlugin implements IMixinConfigPlugin { 14 | private static final Supplier PEHKUI_LOADED = Suppliers.memoize(() -> LoadingModList.get().getModFileById(PehkuiBridge.PEHKUI_MODID) != null); 15 | 16 | @Override 17 | public void onLoad(String mixinPackage) {} 18 | 19 | @Override 20 | public String getRefMapperConfig() { 21 | return null; 22 | } 23 | 24 | @Override 25 | public boolean shouldApplyMixin(String targetClassName, String mixinClassName) { 26 | return PEHKUI_LOADED.get(); 27 | } 28 | 29 | @Override 30 | public List getMixins() { 31 | return null; 32 | } 33 | 34 | @Override 35 | public void acceptTargets(Set myTargets, Set otherTargets) {} 36 | 37 | @Override 38 | public void preApply(String targetClassName, ClassNode targetClass, String mixinClassName, IMixinInfo mixinInfo) {} 39 | 40 | @Override 41 | public void postApply(String targetClassName, ClassNode targetClass, String mixinClassName, IMixinInfo mixinInfo) {} 42 | } 43 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.yml: -------------------------------------------------------------------------------- 1 | name: Bug Report 2 | description: Report an issue you've encountered 3 | labels: [bug] 4 | body: 5 | - type: markdown 6 | attributes: 7 | value: "## Welcome!" 8 | - type: markdown 9 | attributes: 10 | value: | 11 | Thank you for taking your time to report this bug! 12 | Make sure you are running the latest version before reporting. 13 | - type: input 14 | id: description 15 | attributes: 16 | label: Describe the bug 17 | description: "A clear and concise description of what the bug is." 18 | validations: 19 | required: true 20 | - type: textarea 21 | id: repro 22 | attributes: 23 | label: Steps to reproduce 24 | description: | 25 | How do you trigger this bug? Please walk us through it step by step. 26 | If applicable, add screenshots to help explain your problem. 27 | value: | 28 | 1. 29 | 2. 30 | 3. 31 | ... 32 | validations: 33 | required: true 34 | - type: input 35 | id: logs 36 | attributes: 37 | label: Logs 38 | description: | 39 | If applicable (crash, error output in console), please provide your crash report or latest.log 40 | To upload logs, use an external site to post the crash report, such as [Ubuntu Pastebin](https://paste.ubuntu.com/), [Pastebin](http://pastebin.com/), or [Github Gist](https://gist.github.com/) 41 | - type: textarea 42 | id: context 43 | attributes: 44 | label: Additional context 45 | description: "Add any other context about the problem here, such as the modpack you're playing or other mods that might be causing this bug." -------------------------------------------------------------------------------- /reach-entity-attributes/README.md: -------------------------------------------------------------------------------- 1 | # Reach Entity Attributes 2 | [![Maven Repository](https://img.shields.io/maven-metadata/v/https/maven.jamieswhiteshirt.com/libs-release/com/jamieswhiteshirt/reach-entity-attributes/maven-metadata.xml.svg)](https://maven.jamieswhiteshirt.com/libs-release/com/jamieswhiteshirt/reach-entity-attributes/) 3 | 4 | **A library mod for Minecraft that implements entity attributes for reach distance and attack range** 5 | 6 | ## Usage 7 | 8 | ### Setup 9 | To use and include this mod in your project, add the following to your buildscript: 10 | 11 | ```groovy 12 | repositories { 13 | maven { 14 | url "https://maven.jamieswhiteshirt.com/libs-release" 15 | content { 16 | includeGroup "com.jamieswhiteshirt" 17 | } 18 | } 19 | } 20 | 21 | dependencies { 22 | include modImplementation("com.jamieswhiteshirt:reach-entity-attributes:$VERSION") 23 | } 24 | ``` 25 | 26 | ### API 27 | 28 | ### `com.jamieswhiteshirt.reachentityattributes.ReachEntityAttributes.REACH` 29 | Represents the reach distance modifier of an entity that is added to the base value. In vanilla, the base values are 4.5 for survival and 5.0 for creative. 30 | 31 | ### `com.jamieswhiteshirt.reachentityattributes.ReachEntityAttributes.ATTACK_RANGE` 32 | Represents the attack range modifier of an entity that is added to the base value. In vanilla, the base values are 3.0 for survival and 6.0 for creative. 33 | 34 | A player's reach is typically greater than their attack range. Any attack range beyond the player's reach will be ineffective. 35 | 36 | --- 37 | ## Development 38 | 39 | To get started, refer to the [Fabric documentation](https://fabricmc.net/wiki/tutorial:setup). 40 | -------------------------------------------------------------------------------- /amecs-api/src/testmod/java/de/siphalor/amecs/testmod/ClientInit.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2023 Siphalor 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package de.siphalor.amecs.testmod; 18 | 19 | import de.siphalor.amecs.api.KeyModifiers; 20 | import net.fabricmc.fabric.api.client.keybinding.v1.KeyBindingHelper; 21 | import net.minecraft.client.util.InputUtil; 22 | import net.minecraft.util.Identifier; 23 | import net.minecraftforge.fml.common.Mod; 24 | import net.minecraftforge.fml.loading.FMLLoader; 25 | import org.lwjgl.glfw.GLFW; 26 | 27 | @Mod("amecsapi_testmod") 28 | public class ClientInit { 29 | 30 | public ClientInit() { 31 | if (FMLLoader.getDist().isClient()) { 32 | KeyBindingHelper.registerKeyBinding(new TestPriorityKeybinding(new Identifier("amecsapi-testmod", "priority"), InputUtil.Type.KEYSYM, GLFW.GLFW_KEY_Z, "key.categories.misc", new KeyModifiers(), () -> { 33 | System.out.println("priority"); 34 | return true; 35 | }, () -> { 36 | System.out.println("priority release"); 37 | return true; 38 | })); 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /energy-bridge/src/main/java/dev/su5ed/sinytra/connectorextras/energybridge/FabricEnergySlotHandler.java: -------------------------------------------------------------------------------- 1 | package dev.su5ed.sinytra.connectorextras.energybridge; 2 | 3 | import net.fabricmc.fabric.api.transfer.v1.item.ItemVariant; 4 | import net.fabricmc.fabric.api.transfer.v1.storage.base.SingleSlotStorage; 5 | import net.fabricmc.fabric.api.transfer.v1.transaction.TransactionContext; 6 | import net.minecraft.world.item.ItemStack; 7 | 8 | public class FabricEnergySlotHandler implements SingleSlotStorage { 9 | 10 | private ItemStack stack; 11 | 12 | public FabricEnergySlotHandler(ItemStack stack) { 13 | this.stack = stack; 14 | } 15 | 16 | @Override 17 | public long insert(ItemVariant resource, long maxAmount, TransactionContext transaction) { 18 | this.stack = resource.toStack(); 19 | return maxAmount; 20 | } 21 | 22 | @Override 23 | public long extract(ItemVariant resource, long maxAmount, TransactionContext transaction) { 24 | this.stack = resource.toStack(); 25 | return maxAmount; 26 | } 27 | 28 | @Override 29 | public boolean isResourceBlank() { 30 | return getResource().isBlank(); 31 | } 32 | 33 | @Override 34 | public ItemVariant getResource() { 35 | return ItemVariant.of(stack); 36 | } 37 | 38 | public ItemStack getStack() { 39 | return stack; 40 | } 41 | 42 | public void setStack(ItemStack stack) { 43 | this.stack = stack; 44 | } 45 | 46 | @Override 47 | public long getAmount() { 48 | return stack.getCount(); 49 | } 50 | 51 | @Override 52 | public long getCapacity() { 53 | return stack.getMaxStackSize(); 54 | } 55 | 56 | } 57 | -------------------------------------------------------------------------------- /reach-entity-attributes/src/main/resources/META-INF/asm/vehicleInventoryAttackRangeHook.js: -------------------------------------------------------------------------------- 1 | var ASMAPI = Java.type('net.minecraftforge.coremod.api.ASMAPI'); 2 | var Opcodes = Java.type('org.objectweb.asm.Opcodes'); 3 | var InsnList = Java.type('org.objectweb.asm.tree.InsnList'); 4 | var MethodInsnNode = Java.type('org.objectweb.asm.tree.MethodInsnNode'); 5 | var LdcInsnNode = Java.type('org.objectweb.asm.tree.LdcInsnNode'); 6 | 7 | function initializeCoreMod() { 8 | return { 9 | 'vehicleInventoryAttackRangeHook': { 10 | 'target': { 11 | 'type': 'METHOD', 12 | 'class': 'net.minecraft.entity.vehicle.VehicleInventory', 13 | 'methodName': 'm_219954_', 14 | 'methodDesc': '(Lnet/minecraft/world/entity/player/Player;)Z' 15 | }, 16 | 'transformer': function (node) { 17 | for (var i = 0; i < node.instructions.size(); i++) { 18 | var insn = node.instructions.get(i); 19 | if (insn instanceof LdcInsnNode && insn.cst === 8.0) { 20 | var list = new InsnList(); 21 | list.add(new VarInsnNode(Opcodes.ALOAD, 1)); 22 | list.add(new MethodInsnNode(Opcodes.INVOKESTATIC, "com/jamieswhiteshirt/reachentityattributes/ReachEntityAttributes", "getAttackRangeDistance", "(ZLnet/minecraft/entity/player/PlayerEntity;)Z")); 23 | node.instructions.insert(insn, list); 24 | ASMAPI.log('DEBUG', 'Injected attach range check into VehicleInventory'); 25 | break; 26 | } 27 | } 28 | return node; 29 | } 30 | } 31 | } 32 | } -------------------------------------------------------------------------------- /amecs-api/src/testmod/java/de/siphalor/amecs/testmod/TestPriorityKeybinding.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2023 Siphalor 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package de.siphalor.amecs.testmod; 18 | 19 | import de.siphalor.amecs.api.AmecsKeyBinding; 20 | import de.siphalor.amecs.api.KeyModifiers; 21 | import de.siphalor.amecs.api.PriorityKeyBinding; 22 | import net.minecraft.client.util.InputUtil; 23 | import net.minecraft.util.Identifier; 24 | 25 | import java.util.function.BooleanSupplier; 26 | 27 | public class TestPriorityKeybinding extends AmecsKeyBinding implements PriorityKeyBinding { 28 | private final BooleanSupplier action; 29 | private final BooleanSupplier releaseAction; 30 | 31 | public TestPriorityKeybinding(Identifier id, InputUtil.Type type, int code, String category, KeyModifiers defaultModifiers, BooleanSupplier action, BooleanSupplier releaseAction) { 32 | super(id, type, code, category, defaultModifiers); 33 | this.action = action; 34 | this.releaseAction = releaseAction; 35 | } 36 | 37 | @Override 38 | public boolean onPressedPriority() { 39 | return action.getAsBoolean(); 40 | } 41 | 42 | @Override 43 | public boolean onReleasedPriority() { 44 | return releaseAction.getAsBoolean(); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /amecs-api/src/main/resources/META-INF/asm/mouseScrollHook.js: -------------------------------------------------------------------------------- 1 | var ASMAPI = Java.type('net.minecraftforge.coremod.api.ASMAPI'); 2 | var Opcodes = Java.type('org.objectweb.asm.Opcodes'); 3 | var MethodInsnNode = Java.type('org.objectweb.asm.tree.MethodInsnNode'); 4 | var InsnNode = Java.type('org.objectweb.asm.tree.InsnNode'); 5 | var VarInsnNode = Java.type('org.objectweb.asm.tree.VarInsnNode'); 6 | 7 | function initializeCoreMod() { 8 | return { 9 | 'mouseScrollHook': { 10 | 'target': { 11 | 'type': 'METHOD', 12 | 'class': 'net.minecraft.client.MouseHandler', 13 | 'methodName': 'm_91526_', 14 | 'methodDesc': '(JDD)V' 15 | }, 16 | 'transformer': function (node) { 17 | var mappedMethodName = ASMAPI.mapMethod("m_6050_"); 18 | for(var i = 0; i < node.instructions.size(); i++) { 19 | var insn = node.instructions.get(i); 20 | if (insn instanceof MethodInsnNode && insn.getOpcode() == Opcodes.INVOKEVIRTUAL && insn.owner == "net/minecraft/client/gui/screens/Screen" && insn.name == mappedMethodName) { 21 | var list = ASMAPI.listOf( 22 | new VarInsnNode(Opcodes.ALOAD, 0), 23 | new InsnNode(Opcodes.DUP_X1), 24 | new InsnNode(Opcodes.POP), 25 | new MethodInsnNode(Opcodes.INVOKEVIRTUAL, "net/minecraft/client/MouseHandler", "amecs$onMouseScrolledScreen", "(Z)Z", false) 26 | ); 27 | node.instructions.insert(insn, list); 28 | ASMAPI.log('DEBUG', 'Injected mouse scroll hook'); 29 | } 30 | } 31 | return node; 32 | } 33 | } 34 | } 35 | } -------------------------------------------------------------------------------- /jei-bridge/src/main/java/mezz/jei/api/fabric/ingredients/fluids/JeiFluidIngredient.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is licensed under the MIT License, part of Just Enough Items. 3 | * Copyright (c) 2014-2015 mezz 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 all 13 | * 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 THE 21 | * SOFTWARE. 22 | */ 23 | 24 | package mezz.jei.api.fabric.ingredients.fluids; 25 | 26 | import net.fabricmc.fabric.api.transfer.v1.fluid.FluidVariant; 27 | 28 | /** 29 | * A simple record type that implements {@link IJeiFluidIngredient} 30 | * 31 | * @since 19.5.6 32 | */ 33 | public record JeiFluidIngredient(FluidVariant fluid, long amount) implements IJeiFluidIngredient { 34 | @Override 35 | public FluidVariant getFluidVariant() { 36 | return fluid; 37 | } 38 | 39 | @Override 40 | public long getAmount() { 41 | return amount; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /amecs-api/src/main/java/de/siphalor/amecs/api/PriorityKeyBinding.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2023 Siphalor 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package de.siphalor.amecs.api; 18 | 19 | import net.fabricmc.api.EnvType; 20 | import net.fabricmc.api.Environment; 21 | 22 | /** 23 | * An interface to be used on {@link net.minecraft.client.option.KeyBinding}s. 24 | * This key binding triggers without further conditions before any other checks or conditions. 25 | */ 26 | @Environment(EnvType.CLIENT) 27 | public interface PriorityKeyBinding { 28 | /** 29 | * This method gets triggered when this key binding matches on an input event.
30 | * Since there are no other checks before the invocation you need to check yourself for possible open screens. 31 | * 32 | * @return Return true to cancel propagation of this event. Return false for normal evaluation. 33 | */ 34 | boolean onPressedPriority(); 35 | 36 | /** 37 | * This method gets triggered when this key binding matches on an input release event.
38 | * Since there are no other checks before the invocation you need to check yourself for possible open screens. 39 | * 40 | * @return Return true to cancel propagation of this event. Return false for normal evaluation. 41 | */ 42 | default boolean onReleasedPriority() { 43 | return false; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /jei-bridge/src/main/java/mezz/jei/api/fabric/ingredients/fluids/IJeiFluidIngredient.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is licensed under the MIT License, part of Just Enough Items. 3 | * Copyright (c) 2014-2015 mezz 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 all 13 | * 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 THE 21 | * SOFTWARE. 22 | */ 23 | 24 | package mezz.jei.api.fabric.ingredients.fluids; 25 | 26 | import net.fabricmc.fabric.api.transfer.v1.fluid.FluidVariant; 27 | 28 | /** 29 | * Built-in ingredient for representing Fluids in Fabric Minecraft. 30 | * 31 | * @since 10.1.0 32 | */ 33 | public interface IJeiFluidIngredient { 34 | /** 35 | * @return the fluid variant represented by this ingredient. 36 | * 37 | * @since 18.0.0 38 | */ 39 | FluidVariant getFluidVariant(); 40 | 41 | /** 42 | * @return the amount of fluid. 43 | * 44 | * @since 10.1.0 45 | */ 46 | long getAmount(); 47 | } 48 | -------------------------------------------------------------------------------- /amecs-api/src/main/java/de/siphalor/amecs/impl/mixin/MixinKeyboard.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2023 Siphalor 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package de.siphalor.amecs.impl.mixin; 18 | 19 | import de.siphalor.amecs.impl.KeyBindingManager; 20 | import net.fabricmc.api.EnvType; 21 | import net.fabricmc.api.Environment; 22 | import net.minecraft.client.Keyboard; 23 | import net.minecraft.client.util.InputUtil; 24 | import org.spongepowered.asm.mixin.Mixin; 25 | import org.spongepowered.asm.mixin.injection.At; 26 | import org.spongepowered.asm.mixin.injection.Inject; 27 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; 28 | 29 | @Environment(EnvType.CLIENT) 30 | @Mixin(Keyboard.class) 31 | public class MixinKeyboard { 32 | 33 | @Inject(method = "onKey", at = @At(value = "FIELD", target = "Lnet/minecraft/client/MinecraftClient;currentScreen:Lnet/minecraft/client/gui/screen/Screen;", ordinal = 0, shift = At.Shift.BEFORE), cancellable = true) 34 | private void onKeyPriority(long window, int key, int scanCode, int action, int modifiers, CallbackInfo callbackInfo) { 35 | if (action == 1) { 36 | if (KeyBindingManager.onKeyPressedPriority(InputUtil.fromKeyCode(key, scanCode))) { 37 | callbackInfo.cancel(); 38 | } 39 | } else if (action == 0) { 40 | if (KeyBindingManager.onKeyReleasedPriority(InputUtil.fromKeyCode(key, scanCode))) { 41 | callbackInfo.cancel(); 42 | } 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /forgeconfigapiport/src/main/java/dev/su5ed/sinytra/connectorextras/forgeconfigapiport/ForgeConfigApiPortImpl.java: -------------------------------------------------------------------------------- 1 | package dev.su5ed.sinytra.connectorextras.forgeconfigapiport; 2 | 3 | import fuzs.forgeconfigapiport.api.config.v2.ForgeConfigRegistry; 4 | import fuzs.forgeconfigapiport.api.config.v2.ModConfigEvents; 5 | import net.fabricmc.fabric.api.event.Event; 6 | import net.minecraftforge.eventbus.api.IEventBus; 7 | import net.minecraftforge.fml.common.Mod; 8 | import net.minecraftforge.fml.event.config.ModConfigEvent; 9 | import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext; 10 | 11 | @Mod(ForgeConfigApiPortImpl.MODID) 12 | public class ForgeConfigApiPortImpl { 13 | public static final String MODID = "forgeconfigapiport"; 14 | 15 | // TODO Normalize modids 16 | public ForgeConfigApiPortImpl() { 17 | IEventBus bus = FMLJavaModLoadingContext.get().getModEventBus(); 18 | 19 | bus.addListener(ForgeConfigApiPortImpl::onConfigLoad); 20 | bus.addListener(ForgeConfigApiPortImpl::onConfigReload); 21 | bus.addListener(ForgeConfigApiPortImpl::onConfigUnload); 22 | 23 | ((ForgeConfigRegistryImpl) ForgeConfigRegistry.INSTANCE).processConfigs(); 24 | } 25 | 26 | private static void onConfigLoad(ModConfigEvent.Loading event) { 27 | Event fabricEvent = ModConfigEvents.loading(event.getConfig().getModId()); 28 | fabricEvent.invoker().onModConfigLoading(event.getConfig()); 29 | } 30 | 31 | private static void onConfigReload(ModConfigEvent.Reloading event) { 32 | Event fabricEvent = ModConfigEvents.reloading(event.getConfig().getModId()); 33 | fabricEvent.invoker().onModConfigReloading(event.getConfig()); 34 | } 35 | 36 | private static void onConfigUnload(ModConfigEvent.Unloading event) { 37 | Event fabricEvent = ModConfigEvents.unloading(event.getConfig().getModId()); 38 | fabricEvent.invoker().onModConfigUnloading(event.getConfig()); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /amecs-api/src/main/java/de/siphalor/amecs/impl/mixin/MixinInputUtilType.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2023 Siphalor 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package de.siphalor.amecs.impl.mixin; 18 | 19 | import de.siphalor.amecs.api.KeyBindingUtils; 20 | import de.siphalor.amecs.impl.AmecsAPI; 21 | import net.fabricmc.api.EnvType; 22 | import net.fabricmc.api.Environment; 23 | import net.minecraft.client.util.InputUtil; 24 | import org.spongepowered.asm.mixin.Mixin; 25 | import org.spongepowered.asm.mixin.Unique; 26 | import org.spongepowered.asm.mixin.injection.At; 27 | import org.spongepowered.asm.mixin.injection.Inject; 28 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; 29 | 30 | @Environment(EnvType.CLIENT) 31 | @Mixin(InputUtil.Type.class) 32 | public abstract class MixinInputUtilType { 33 | @SuppressWarnings("UnresolvedMixinReference") 34 | @Inject(method = "", at = @At("RETURN")) 35 | private static void onRegisterKeyCodes(CallbackInfo callbackInfo) { 36 | createScrollKey("mouse.scroll.up", KeyBindingUtils.MOUSE_SCROLL_UP); 37 | createScrollKey("mouse.scroll.down", KeyBindingUtils.MOUSE_SCROLL_DOWN); 38 | } 39 | 40 | @Unique 41 | private static void createScrollKey(String name, int keyCode) { 42 | String keyName = AmecsAPI.makeKeyID(name); 43 | InputUtil.Type.mapKey(InputUtil.Type.MOUSE, keyName, keyCode); 44 | 45 | // Legacy compatibility (amecsapi <1.3) 46 | InputUtil.Key.KEYS.put("amecsapi.key." + name, InputUtil.fromTranslationKey(keyName)); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /emi-bridge/src/main/java/dev/emi/emi/api/FabricEmiStack.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is licensed under the MIT License, part of EMI. 3 | * Copyright (c) 2022 Emi 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 all 13 | * 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 THE 21 | * SOFTWARE. 22 | */ 23 | 24 | package dev.emi.emi.api; 25 | 26 | import dev.emi.emi.api.stack.EmiStack; 27 | import net.fabricmc.fabric.api.transfer.v1.fluid.FluidVariant; 28 | import net.fabricmc.fabric.api.transfer.v1.item.ItemVariant; 29 | 30 | public final class FabricEmiStack { 31 | 32 | public static EmiStack of(ItemVariant variant) { 33 | return EmiStack.of(variant.toStack()); 34 | } 35 | 36 | public static EmiStack of(ItemVariant variant, long amount) { 37 | return EmiStack.of(variant.toStack((int) amount)); 38 | } 39 | 40 | public static EmiStack of(FluidVariant variant) { 41 | return EmiStack.of(variant.getFluid(), variant.getComponents()); 42 | } 43 | 44 | public static EmiStack of(FluidVariant variant, long amount) { 45 | return EmiStack.of(variant.getFluid(), variant.getComponents(), amount); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /modmenu-bridge/src/main/java/com/terraformersmc/modmenu/config/option/ConfigOptionStorage.java: -------------------------------------------------------------------------------- 1 | package com.terraformersmc.modmenu.config.option; 2 | 3 | import java.util.HashMap; 4 | import java.util.Map; 5 | import java.util.Set; 6 | 7 | public class ConfigOptionStorage { 8 | private static final Map BOOLEAN_OPTIONS = new HashMap<>(); 9 | private static final Map> ENUM_OPTIONS = new HashMap<>(); 10 | private static final Map> STRING_SET_OPTIONS = new HashMap<>(); 11 | 12 | public static void setStringSet(String key, Set value) { 13 | STRING_SET_OPTIONS.put(key, value); 14 | } 15 | 16 | public static Set getStringSet(String key) { 17 | return STRING_SET_OPTIONS.get(key); 18 | } 19 | 20 | public static void setBoolean(String key, boolean value) { 21 | BOOLEAN_OPTIONS.put(key, value); 22 | } 23 | 24 | public static void toggleBoolean(String key) { 25 | setBoolean(key, !getBoolean(key)); 26 | } 27 | 28 | public static boolean getBoolean(String key) { 29 | return BOOLEAN_OPTIONS.get(key); 30 | } 31 | 32 | @SuppressWarnings("unchecked") 33 | public static > E getEnum(String key, Class typeClass) { 34 | return (E) ENUM_OPTIONS.get(key); 35 | } 36 | 37 | public static Enum getEnumTypeless(String key, Class> typeClass) { 38 | return ENUM_OPTIONS.get(key); 39 | } 40 | 41 | public static > void setEnum(String key, E value) { 42 | ENUM_OPTIONS.put(key, value); 43 | } 44 | 45 | public static void setEnumTypeless(String key, Enum value) { 46 | ENUM_OPTIONS.put(key, value); 47 | } 48 | 49 | public static > E cycleEnum(String key, Class typeClass) { 50 | return cycleEnum(key, typeClass, 1); 51 | } 52 | 53 | 54 | public static > E cycleEnum(String key, Class typeClass, int amount) { 55 | E[] values = typeClass.getEnumConstants(); 56 | E currentValue = getEnum(key, typeClass); 57 | E newValue = values[(currentValue.ordinal() + amount) % values.length]; 58 | setEnum(key, newValue); 59 | return newValue; 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /energy-bridge/src/main/java/dev/su5ed/sinytra/connectorextras/energybridge/EnergyBridge.java: -------------------------------------------------------------------------------- 1 | package dev.su5ed.sinytra.connectorextras.energybridge; 2 | 3 | import com.google.common.primitives.Ints; 4 | import net.neoforged.bus.api.IEventBus; 5 | import net.neoforged.fml.ModContainer; 6 | import net.neoforged.fml.ModList; 7 | import net.neoforged.fml.common.Mod; 8 | import net.neoforged.fml.config.ModConfig; 9 | import net.neoforged.neoforge.common.ModConfigSpec; 10 | 11 | @Mod(EnergyBridge.MODID) 12 | public class EnergyBridge { 13 | public static final String MODID = "connectorextras_energy_bridge"; 14 | 15 | public EnergyBridge(IEventBus bus, ModContainer container) { 16 | if (ModList.get().isLoaded("team_reborn_energy")) { 17 | EnergyBridgeSetup.init(bus); 18 | } 19 | container.registerConfig(ModConfig.Type.COMMON, EnergyBridgeConfig.COMMON_SPEC); 20 | } 21 | 22 | public static int convertFabricToForgeEnergy(long amount) { 23 | return convertForward(amount, EnergyBridgeConfig.COMMON.fabricToForgeEnergy); 24 | } 25 | 26 | public static long unConvertFabricToForgeEnergy(int amount) { 27 | return convertBackwards(amount, EnergyBridgeConfig.COMMON.fabricToForgeEnergy); 28 | } 29 | 30 | public static long convertForgeToFabricEnergy(int amount) { 31 | return convertBackwards(amount, EnergyBridgeConfig.COMMON.forgeToFabricEnergy); 32 | } 33 | 34 | public static int unConvertForgeToFabricEnergy(long amount) { 35 | return convertForward(amount, EnergyBridgeConfig.COMMON.forgeToFabricEnergy); 36 | } 37 | 38 | public static int convertForward(long amount, ModConfigSpec.IntValue ratio) { 39 | if (amount > Integer.MAX_VALUE) { 40 | return Integer.MAX_VALUE; 41 | } 42 | if (amount < Integer.MIN_VALUE) { 43 | return Integer.MIN_VALUE; 44 | } 45 | long fe = ratio.get() * amount; 46 | return Ints.saturatedCast(fe); 47 | } 48 | 49 | private static long convertBackwards(int amount, ModConfigSpec.IntValue ratio) { 50 | int value = ratio.get(); 51 | return value == 0 ? 0 : amount / value; 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /amecs-api/src/main/java/de/siphalor/amecs/api/input/InputHandlerManager.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2023 Siphalor 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package de.siphalor.amecs.api.input; 18 | 19 | import net.fabricmc.api.EnvType; 20 | import net.fabricmc.api.Environment; 21 | import net.minecraft.client.MinecraftClient; 22 | import org.jetbrains.annotations.ApiStatus; 23 | 24 | import java.util.LinkedHashSet; 25 | 26 | /** 27 | * This class allows you to (un-)register {@link InputEventHandler}s 28 | * 29 | * @see InputEventHandler#handleInput(MinecraftClient) 30 | * @see #handleInputEvents 31 | */ 32 | @Environment(EnvType.CLIENT) 33 | public class InputHandlerManager { 34 | 35 | // all methods and fields in this class must be used from main thread only or manual synchronization is required 36 | private static final LinkedHashSet INPUT_HANDLERS = new LinkedHashSet<>(); 37 | 38 | /** 39 | * This method is called from MinecraftClient.handleInputEvents() 40 | *
41 | * It calls all registered InputEventHandler 42 | * 43 | * @param client 44 | */ 45 | @ApiStatus.Internal 46 | public static void handleInputEvents(MinecraftClient client) { 47 | for (InputEventHandler handler : INPUT_HANDLERS) { 48 | handler.handleInput(client); 49 | } 50 | } 51 | 52 | public static boolean registerInputEventHandler(InputEventHandler handler) { 53 | return INPUT_HANDLERS.add(handler); 54 | } 55 | 56 | public static boolean removeInputEventHandler(InputEventHandler handler) { 57 | return INPUT_HANDLERS.remove(handler); 58 | } 59 | 60 | } 61 | -------------------------------------------------------------------------------- /modmenu-bridge/src/main/java/com/terraformersmc/modmenu/config/option/BooleanConfigOption.java: -------------------------------------------------------------------------------- 1 | package com.terraformersmc.modmenu.config.option; 2 | 3 | import net.minecraft.client.option.SimpleOption; 4 | import net.minecraft.screen.ScreenTexts; 5 | import net.minecraft.text.Text; 6 | 7 | public class BooleanConfigOption implements OptionConvertable { 8 | private final String key, translationKey; 9 | private final boolean defaultValue; 10 | private final Text enabledText; 11 | private final Text disabledText; 12 | 13 | public BooleanConfigOption(String key, boolean defaultValue, String enabledKey, String disabledKey) { 14 | ConfigOptionStorage.setBoolean(key, defaultValue); 15 | this.key = key; 16 | this.translationKey = ""; 17 | this.defaultValue = defaultValue; 18 | this.enabledText = Text.translatable(translationKey + "." + enabledKey); 19 | this.disabledText = Text.translatable(translationKey + "." + disabledKey); 20 | } 21 | 22 | public BooleanConfigOption(String key, boolean defaultValue) { 23 | this(key, defaultValue, "true", "false"); 24 | } 25 | 26 | public String getKey() { 27 | return key; 28 | } 29 | 30 | public boolean getValue() { 31 | return ConfigOptionStorage.getBoolean(key); 32 | } 33 | 34 | public void setValue(boolean value) { 35 | ConfigOptionStorage.setBoolean(key, value); 36 | } 37 | 38 | public void toggleValue() { 39 | ConfigOptionStorage.toggleBoolean(key); 40 | } 41 | 42 | public boolean getDefaultValue() { 43 | return defaultValue; 44 | } 45 | 46 | public Text getButtonText() { 47 | return ScreenTexts.composeGenericOptionText(Text.translatable(translationKey), 48 | getValue() ? enabledText : disabledText 49 | ); 50 | } 51 | 52 | @Override 53 | public SimpleOption asOption() { 54 | if (enabledText != null && disabledText != null) { 55 | return new SimpleOption<>(translationKey, 56 | SimpleOption.emptyTooltip(), 57 | (text, value) -> value ? enabledText : disabledText, 58 | SimpleOption.BOOLEAN, 59 | getValue(), 60 | newValue -> ConfigOptionStorage.setBoolean(key, newValue) 61 | ); 62 | } 63 | return SimpleOption.ofBoolean(translationKey, 64 | getValue(), 65 | (value) -> ConfigOptionStorage.setBoolean(key, value) 66 | ); 67 | } 68 | } -------------------------------------------------------------------------------- /rei-bridge/src/main/java/me/shedaniel/rei/fabric/ClientPluginDetector.java: -------------------------------------------------------------------------------- 1 | package me.shedaniel.rei.fabric; 2 | 3 | import com.google.common.base.Suppliers; 4 | import me.shedaniel.rei.api.client.plugins.REIClientPlugin; 5 | import me.shedaniel.rei.api.common.plugins.PluginManager; 6 | import me.shedaniel.rei.api.common.plugins.PluginView; 7 | import me.shedaniel.rei.impl.ClientInternals; 8 | import net.fabricmc.loader.api.FabricLoader; 9 | import net.minecraft.client.gui.GuiGraphics; 10 | import net.minecraft.client.gui.screens.inventory.tooltip.ClientTooltipComponent; 11 | import net.minecraft.world.inventory.tooltip.TooltipComponent; 12 | 13 | import java.lang.reflect.InvocationTargetException; 14 | import java.lang.reflect.Method; 15 | import java.util.List; 16 | import java.util.function.BiConsumer; 17 | import java.util.function.Supplier; 18 | 19 | public final class ClientPluginDetector { 20 | 21 | public static void detectClientPlugins() { 22 | PluginDetectorImpl.loadPlugin(REIClientPlugin.class, ((PluginView) PluginManager.getClientInstance())::registerPlugin); 23 | Supplier method = Suppliers.memoize(() -> { 24 | String methodName = FabricLoader.getInstance().isDevelopmentEnvironment() ? FabricLoader.getInstance().getMappingResolver().mapMethodName("intermediary", "net.minecraft.class_332", "method_51442", "(Ljava/util/List;Lnet/minecraft/class_5632;)V") 25 | : "lambda$renderTooltip$3"; 26 | try { 27 | Method declaredMethod = GuiGraphics.class.getDeclaredMethod(methodName, List.class, TooltipComponent.class); 28 | if (declaredMethod != null) declaredMethod.setAccessible(true); 29 | return declaredMethod; 30 | } catch (NoSuchMethodException e) { 31 | throw new RuntimeException(e); 32 | } 33 | }); 34 | ClientInternals.attachInstance((BiConsumer, TooltipComponent>) (lines, component) -> { 35 | try { 36 | method.get().invoke(null, lines, component); 37 | } catch (IllegalAccessException | InvocationTargetException e) { 38 | throw new RuntimeException(e); 39 | } 40 | }, "clientTooltipComponentProvider"); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /reach-entity-attributes/src/main/resources/META-INF/asm/inventoryValidationHook.js: -------------------------------------------------------------------------------- 1 | var ASMAPI = Java.type('net.minecraftforge.coremod.api.ASMAPI'); 2 | var Opcodes = Java.type('org.objectweb.asm.Opcodes'); 3 | var LabelNode = Java.type('org.objectweb.asm.tree.LabelNode'); 4 | var InsnList = Java.type('org.objectweb.asm.tree.InsnList'); 5 | var MethodInsnNode = Java.type('org.objectweb.asm.tree.MethodInsnNode'); 6 | var JumpInsnNode = Java.type('org.objectweb.asm.tree.JumpInsnNode'); 7 | var InsnNode = Java.type('org.objectweb.asm.tree.InsnNode'); 8 | var VarInsnNode = Java.type('org.objectweb.asm.tree.VarInsnNode'); 9 | 10 | function initializeCoreMod() { 11 | return { 12 | 'inventoryValidationHook': { 13 | 'target': { 14 | 'type': 'METHOD', 15 | 'class': 'net.minecraft.world.Container', 16 | 'methodName': 'm_271806_', 17 | 'methodDesc': '(Lnet/minecraft/world/level/block/entity/BlockEntity;Lnet/minecraft/world/entity/player/Player;I)Z' 18 | }, 19 | 'transformer': function (node) { 20 | var methodInsn = ASMAPI.findFirstMethodCall(node, ASMAPI.MethodType.VIRTUAL, "net/minecraft/core/BlockPos", "getX", "()I"); 21 | if (methodInsn != null) { 22 | var label = new LabelNode(); 23 | var list = new InsnList(); 24 | list.add(new VarInsnNode(Opcodes.ALOAD, 1)); 25 | list.add(new VarInsnNode(Opcodes.ALOAD, 4)); 26 | list.add(new VarInsnNode(Opcodes.ILOAD, 2)); 27 | list.add(new MethodInsnNode(Opcodes.INVOKESTATIC, "com/jamieswhiteshirt/reachentityattributes/ReachEntityAttributes", "checkWithinActualReach", "(Lnet/minecraft/world/entity/player/Player;Lnet/minecraft/core/BlockPos;I)Z")); 28 | list.add(new JumpInsnNode(Opcodes.IFEQ, label)); 29 | list.add(new InsnNode(Opcodes.ICONST_1)); 30 | list.add(new InsnNode(Opcodes.IRETURN)); 31 | list.add(label); 32 | node.instructions.insert(methodInsn, list); 33 | ASMAPI.log('DEBUG', 'Injected Inventory canPlayerUse attach range check'); 34 | } 35 | return node; 36 | } 37 | } 38 | } 39 | } -------------------------------------------------------------------------------- /forgeconfigapiport/src/main/java/fuzs/forgeconfigapiport/api/config/v2/ForgeConfigRegistry.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This Source Code Form is subject to the terms of the Mozilla Public 3 | * License, v. 2.0. If a copy of the MPL was not distributed with this 4 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 5 | */ 6 | package fuzs.forgeconfigapiport.api.config.v2; 7 | 8 | import dev.su5ed.sinytra.connectorextras.forgeconfigapiport.ForgeConfigRegistryImpl; 9 | import net.minecraftforge.fml.config.IConfigSpec; 10 | import net.minecraftforge.fml.config.ModConfig; 11 | 12 | /** 13 | * Registry for adding your configs. On Forge this is done using net.minecraftforge.fml.ModLoadingContext, which does not exist in Forge Config Api Port. 14 | *

Note that opposed to Forge, configs are loaded and usable immediately after registration. 15 | */ 16 | public interface ForgeConfigRegistry { 17 | /** 18 | * implementation instance for registering configs 19 | */ 20 | ForgeConfigRegistry INSTANCE = new ForgeConfigRegistryImpl(); 21 | 22 | /** 23 | * Register a new mod config, only difference from registering on Forge is modId has to be provided as there is no loading context to get that information from 24 | * 25 | * @param modId mod id of your mod 26 | * @param type type of this mod config (client, common, or server) 27 | * @param spec the built config spec 28 | * @return the {@link ModConfig} instance 29 | * 30 | * @throws IllegalArgumentException when no mod container is found for modId 31 | */ 32 | ModConfig register(String modId, ModConfig.Type type, IConfigSpec spec); 33 | 34 | /** 35 | * Register a new mod config, only difference from registering on Forge is modId has to be provided as there is no loading context to get that information from 36 | * 37 | * @param modId mod id of your mod 38 | * @param type type of this mod config (client, common, or server) 39 | * @param spec the built config spec 40 | * @param fileName file name to use instead of default 41 | * @return the {@link ModConfig} instance 42 | * 43 | * @throws IllegalArgumentException when no mod container is found for modId 44 | */ 45 | ModConfig register(String modId, ModConfig.Type type, IConfigSpec spec, String fileName); 46 | } 47 | -------------------------------------------------------------------------------- /modmenu-bridge/src/main/java/com/terraformersmc/modmenu/config/option/EnumConfigOption.java: -------------------------------------------------------------------------------- 1 | package com.terraformersmc.modmenu.config.option; 2 | 3 | import com.mojang.serialization.Codec; 4 | import net.minecraft.client.option.SimpleOption; 5 | import net.minecraft.screen.ScreenTexts; 6 | import net.minecraft.text.Text; 7 | 8 | import java.util.Arrays; 9 | import java.util.Locale; 10 | 11 | public class EnumConfigOption> implements OptionConvertable { 12 | private final String key, translationKey; 13 | private final Class enumClass; 14 | private final E defaultValue; 15 | 16 | public EnumConfigOption(String key, E defaultValue) { 17 | ConfigOptionStorage.setEnum(key, defaultValue); 18 | this.key = key; 19 | this.translationKey = ""; 20 | this.enumClass = defaultValue.getDeclaringClass(); 21 | this.defaultValue = defaultValue; 22 | } 23 | 24 | public String getKey() { 25 | return key; 26 | } 27 | 28 | public E getValue() { 29 | return ConfigOptionStorage.getEnum(key, enumClass); 30 | } 31 | 32 | public void setValue(E value) { 33 | ConfigOptionStorage.setEnum(key, value); 34 | } 35 | 36 | public void cycleValue() { 37 | ConfigOptionStorage.cycleEnum(key, enumClass); 38 | } 39 | 40 | public void cycleValue(int amount) { 41 | ConfigOptionStorage.cycleEnum(key, enumClass, amount); 42 | } 43 | 44 | public E getDefaultValue() { 45 | return defaultValue; 46 | } 47 | 48 | private static > Text getValueText(EnumConfigOption option, E value) { 49 | return Text.translatable(option.translationKey + "." + value.name().toLowerCase(Locale.ROOT)); 50 | } 51 | 52 | public Text getButtonText() { 53 | return ScreenTexts.composeGenericOptionText(Text.translatable(translationKey), getValueText(this, getValue())); 54 | } 55 | 56 | @Override 57 | public SimpleOption asOption() { 58 | return new SimpleOption<>(translationKey, 59 | SimpleOption.emptyTooltip(), 60 | (text, value) -> getValueText(this, value), 61 | new SimpleOption.PotentialValuesBasedCallbacks<>(Arrays.asList(enumClass.getEnumConstants()), 62 | Codec.STRING.xmap(string -> Arrays.stream(enumClass.getEnumConstants()) 63 | .filter(e -> e.name().toLowerCase().equals(string)) 64 | .findAny() 65 | .orElse(null), newValue -> newValue.name().toLowerCase()) 66 | ), 67 | getValue(), 68 | value -> ConfigOptionStorage.setEnum(key, value) 69 | ); 70 | } 71 | } -------------------------------------------------------------------------------- /modmenu-bridge/src/main/java/com/terraformersmc/modmenu/api/ModMenuApi.java: -------------------------------------------------------------------------------- 1 | package com.terraformersmc.modmenu.api; 2 | 3 | import com.google.common.collect.ImmutableMap; 4 | import net.minecraft.client.gui.screen.Screen; 5 | import net.minecraft.screen.ScreenTexts; 6 | import net.minecraft.text.Text; 7 | import net.neoforged.neoforge.client.gui.ModListScreen; 8 | 9 | import java.util.Map; 10 | import java.util.function.Consumer; 11 | 12 | public interface ModMenuApi { 13 | 14 | /** 15 | * Used for creating a {@link Screen} instance of the Mod Menu 16 | * "Mods" screen 17 | * 18 | * @param previous The screen before opening 19 | * @return A "Mods" Screen 20 | */ 21 | static Screen createModsScreen(Screen previous) { 22 | return new ModListScreen(previous); 23 | } 24 | 25 | /** 26 | * Used for creating a {@link Text} just like what would appear 27 | * on a Mod Menu Mods button 28 | * 29 | * @return The text that would be displayed on a Mods button 30 | */ 31 | static Text createModsButtonText() { 32 | return ScreenTexts.EMPTY; 33 | } 34 | 35 | /** 36 | * Used to construct a new config screen instance when your mod's 37 | * configuration button is selected on the mod menu screen. The 38 | * screen instance parameter is the active mod menu screen. 39 | * 40 | * @return A factory for constructing config screen instances. 41 | */ 42 | default ConfigScreenFactory getModConfigScreenFactory() { 43 | return screen -> null; 44 | } 45 | 46 | /** 47 | * Used to provide config screen factories for other mods. This takes second 48 | * priority to a mod's own config screen factory provider. For example, if 49 | * mod `xyz` supplies a config screen factory, mod `abc` providing a config 50 | * screen to `xyz` will be pointless, as the one provided by `xyz` will be 51 | * used. 52 | *

53 | * This method is NOT meant to be used to add a config screen factory to 54 | * your own mod. 55 | * 56 | * @return a map of mod ids to screen factories. 57 | */ 58 | default Map> getProvidedConfigScreenFactories() { 59 | return ImmutableMap.of(); 60 | } 61 | 62 | /** 63 | * Used to mark mods with a badge indicating that they are 64 | * provided by a modpack. 65 | *

66 | * Builtin mods such as `minecraft` cannot be marked as 67 | * provided by a modpack. 68 | */ 69 | default void attachModpackBadges(Consumer consumer) { 70 | return; 71 | } 72 | } -------------------------------------------------------------------------------- /amecs-api/src/main/java/de/siphalor/amecs/impl/mixin/MixinKeyBinding.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2023 Siphalor 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package de.siphalor.amecs.impl.mixin; 18 | 19 | import de.siphalor.amecs.api.PriorityKeyBinding; 20 | import de.siphalor.amecs.impl.KeyBindingManager; 21 | import net.fabricmc.api.EnvType; 22 | import net.fabricmc.api.Environment; 23 | import net.minecraft.client.option.KeyBinding; 24 | import net.minecraft.client.util.InputUtil; 25 | import net.minecraftforge.client.settings.IKeyConflictContext; 26 | import net.minecraftforge.client.settings.KeyModifier; 27 | import org.spongepowered.asm.mixin.Mixin; 28 | import org.spongepowered.asm.mixin.injection.At; 29 | import org.spongepowered.asm.mixin.injection.Inject; 30 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; 31 | 32 | @SuppressWarnings("WeakerAccess") 33 | @Environment(EnvType.CLIENT) 34 | @Mixin(KeyBinding.class) 35 | public abstract class MixinKeyBinding { 36 | 37 | @Inject(method = "(Ljava/lang/String;Lnet/minecraft/client/util/InputUtil$Type;ILjava/lang/String;)V", at = @At("RETURN")) 38 | private void onConstructed(String id, InputUtil.Type type, int defaultCode, String category, CallbackInfo callbackInfo) { 39 | if (this instanceof PriorityKeyBinding) { 40 | KeyBindingManager.register((KeyBinding) (Object) this); 41 | } 42 | } 43 | 44 | @Inject(method = "(Ljava/lang/String;Lnet/minecraftforge/client/settings/IKeyConflictContext;Lnet/minecraftforge/client/settings/KeyModifier;Lnet/minecraft/client/util/InputUtil$Key;Ljava/lang/String;)V", at = @At("RETURN")) 45 | private void onConstructedForge(String description, IKeyConflictContext keyConflictContext, KeyModifier keyModifier, InputUtil.Key keyCode, String category, CallbackInfo ci) { 46 | if (this instanceof PriorityKeyBinding) { 47 | KeyBindingManager.register((KeyBinding) (Object) this); 48 | } 49 | } 50 | 51 | } 52 | -------------------------------------------------------------------------------- /pehkui-bridge/src/main/java/dev/su5ed/sinytra/connectorextras/pehkuibridge/mixin/ScaleTypeMixin.java: -------------------------------------------------------------------------------- 1 | package dev.su5ed.sinytra.connectorextras.pehkuibridge.mixin; 2 | 3 | import net.fabricmc.fabric.api.event.Event; 4 | import net.fabricmc.fabric.api.event.EventFactory; 5 | import org.spongepowered.asm.mixin.Mixin; 6 | import org.spongepowered.asm.mixin.Unique; 7 | import org.spongepowered.asm.mixin.injection.At; 8 | import org.spongepowered.asm.mixin.injection.Inject; 9 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; 10 | import virtuoel.pehkui.api.ScaleEventCallback; 11 | import virtuoel.pehkui.api.ScaleType; 12 | 13 | @Mixin(ScaleType.class) 14 | public class ScaleTypeMixin { 15 | @Unique 16 | private Event connectorextras_scaleTypeChangedEvent; 17 | @Unique 18 | private Event connectorextras_preTickChangedEvent = connector_createScaleEvent(); 19 | @Unique 20 | private Event connectorextras_postTickChangedEvent = connector_createScaleEvent(); 21 | 22 | @Inject(method = "", at = @At("TAIL")) 23 | private void onInit(ScaleType.Builder builder, CallbackInfo ci) { 24 | this.connectorextras_scaleTypeChangedEvent = connector_createScaleEvent(); 25 | this.connectorextras_preTickChangedEvent = connector_createScaleEvent(); 26 | this.connectorextras_postTickChangedEvent = connector_createScaleEvent(); 27 | ((ScaleType) (Object) this).getScaleChangedEvent().add(data -> connectorextras_scaleTypeChangedEvent.invoker().onEvent(data)); 28 | ((ScaleType) (Object) this).getPreTickEvent().add(data -> connectorextras_preTickChangedEvent.invoker().onEvent(data)); 29 | ((ScaleType) (Object) this).getPostTickEvent().add(data -> connectorextras_postTickChangedEvent.invoker().onEvent(data)); 30 | } 31 | 32 | @Unique 33 | public Event getScaleChangedEvent() { 34 | return this.connectorextras_scaleTypeChangedEvent; 35 | } 36 | 37 | @Unique 38 | public Event getPreTickEvent() { 39 | return this.connectorextras_preTickChangedEvent; 40 | } 41 | 42 | @Unique 43 | public Event getPostTickEvent() { 44 | return this.connectorextras_postTickChangedEvent; 45 | } 46 | 47 | @Unique 48 | private static Event connector_createScaleEvent() { 49 | return EventFactory.createArrayBacked( 50 | ScaleEventCallback.class, 51 | data -> { 52 | }, 53 | callbacks -> data -> 54 | { 55 | for (ScaleEventCallback callback : callbacks) { 56 | callback.onEvent(data); 57 | } 58 | } 59 | ); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /modmenu-bridge/src/main/java/dev/su5ed/sinytra/connectorextras/modmenu/ModMenuCompatSetup.java: -------------------------------------------------------------------------------- 1 | package dev.su5ed.sinytra.connectorextras.modmenu; 2 | 3 | import com.mojang.logging.LogUtils; 4 | import com.terraformersmc.modmenu.api.ConfigScreenFactory; 5 | import com.terraformersmc.modmenu.api.ModMenuApi; 6 | import net.fabricmc.loader.api.FabricLoader; 7 | import net.minecraft.client.gui.screen.Screen; 8 | import net.neoforged.fml.ModList; 9 | import net.neoforged.neoforge.client.gui.IConfigScreenFactory; 10 | import net.neoforged.neoforge.client.gui.ModListScreen; 11 | import org.slf4j.Logger; 12 | 13 | import java.util.ArrayList; 14 | import java.util.HashMap; 15 | import java.util.List; 16 | import java.util.Map; 17 | 18 | public class ModMenuCompatSetup { 19 | private static final Logger LOGGER = LogUtils.getLogger(); 20 | 21 | public static void init() { 22 | Map> modFactories = new HashMap<>(); 23 | List>> providedFactories = new ArrayList<>(); 24 | FabricLoader.getInstance().getEntrypointContainers(ModMenuDummy.MODMENU_MODID, ModMenuApi.class).forEach(container -> { 25 | String modId = container.getProvider().getMetadata().getId(); 26 | try { 27 | ModMenuApi entry = container.getEntrypoint(); 28 | modFactories.put(modId, entry.getModConfigScreenFactory()); 29 | providedFactories.add(entry.getProvidedConfigScreenFactories()); 30 | } catch (Throwable t) { 31 | LOGGER.error("Failed to load ModMenuApi entrypoint for {}", modId, t); 32 | } 33 | }); 34 | 35 | providedFactories.forEach(map -> map.forEach(modFactories::putIfAbsent)); 36 | providedFactories.clear(); 37 | 38 | Screen dummyParent = new ModListScreen(null); 39 | modFactories.forEach((modId, factory) -> { 40 | // Ensure factory is active. This is required to avoid cases where the integration conditionally 41 | // disables itself (e.g. when cloth config is absent) and returns a dummy factory. 42 | try { 43 | if (factory.create(dummyParent) == null) { 44 | return; 45 | } 46 | } catch (Throwable t) { 47 | // If an error occurs, it might be due to us creating the factory so early. 48 | // Since we can't be sure about the factory's status, continue ahead 49 | LOGGER.warn("Error testing config screen factory status for mod {}", modId, t); 50 | } 51 | 52 | ModList.get().getModContainerById(modId).ifPresent(fmlContainer -> fmlContainer.registerExtensionPoint(IConfigScreenFactory.class, (mod, screen) -> factory.create(screen))); 53 | }); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /jei-bridge/src/main/java/mezz/jei/api/fabric/constants/FabricTypes.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is licensed under the MIT License, part of Just Enough Items. 3 | * Copyright (c) 2014-2015 mezz 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 all 13 | * 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 THE 21 | * SOFTWARE. 22 | */ 23 | 24 | package mezz.jei.api.fabric.constants; 25 | 26 | import mezz.jei.api.fabric.ingredients.fluids.IJeiFluidIngredient; 27 | import mezz.jei.api.fabric.ingredients.fluids.JeiFluidIngredient; 28 | import mezz.jei.api.ingredients.IIngredientType; 29 | import mezz.jei.api.ingredients.IIngredientTypeWithSubtypes; 30 | import net.fabricmc.fabric.api.transfer.v1.fluid.FluidConstants; 31 | import net.fabricmc.fabric.api.transfer.v1.fluid.FluidVariant; 32 | import net.minecraft.world.level.material.Fluid; 33 | 34 | /** 35 | * Built-in {@link IIngredientType} for Fabric Minecraft. 36 | * 37 | * @since 10.1.0 38 | */ 39 | public final class FabricTypes { 40 | /** 41 | * @since 10.1.0 42 | */ 43 | public static final IIngredientTypeWithSubtypes FLUID_STACK = new IIngredientTypeWithSubtypes<>() { 44 | @Override 45 | public String getUid() { 46 | return "fluid_stack"; 47 | } 48 | 49 | @Override 50 | public Class getIngredientClass() { 51 | return IJeiFluidIngredient.class; 52 | } 53 | 54 | @Override 55 | public Class getIngredientBaseClass() { 56 | return Fluid.class; 57 | } 58 | 59 | @Override 60 | public Fluid getBase(IJeiFluidIngredient ingredient) { 61 | return ingredient.getFluidVariant().getFluid(); 62 | } 63 | 64 | @Override 65 | public IJeiFluidIngredient getDefaultIngredient(Fluid base) { 66 | return new JeiFluidIngredient(FluidVariant.of(base), FluidConstants.BUCKET); 67 | } 68 | }; 69 | 70 | private FabricTypes() {} 71 | } 72 | -------------------------------------------------------------------------------- /forgeconfigapiport/src/main/java/fuzs/forgeconfigapiport/api/config/v2/ForgeConfigPaths.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This Source Code Form is subject to the terms of the Mozilla Public 3 | * License, v. 2.0. If a copy of the MPL was not distributed with this 4 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 5 | */ 6 | package fuzs.forgeconfigapiport.api.config.v2; 7 | 8 | import dev.su5ed.sinytra.connectorextras.forgeconfigapiport.ForgeConfigPathsImpl; 9 | import net.minecraft.server.MinecraftServer; 10 | 11 | import java.nio.file.Path; 12 | 13 | /** 14 | * Access to paths where different kinds of config files are stored by Forge. 15 | */ 16 | public interface ForgeConfigPaths { 17 | /** 18 | * implementation instance for retrieving config paths 19 | */ 20 | ForgeConfigPaths INSTANCE = new ForgeConfigPathsImpl(); 21 | 22 | /** 23 | * The directory where client configs are stored at. 24 | * 25 | * @return client config path 26 | */ 27 | Path getClientConfigDirectory(); 28 | 29 | /** 30 | * The directory where common configs are stored at. 31 | * 32 | * @return common config path 33 | */ 34 | Path getCommonConfigDirectory(); 35 | 36 | /** 37 | * The directory where server configs are stored at. By default, this is inside the world directory instead of the common .minecraft/config/ directory. 38 | *

Forge Config Api Port has a config setting (which is not present in Forge itself) to load server configs from the common directory instead. 39 | * This method will always provide the directory that is currently set via the Forge Config Api Port config. 40 | * 41 | * @param server the current {@link MinecraftServer} 42 | * @return server config path 43 | */ 44 | Path getServerConfigDirectory(final MinecraftServer server); 45 | 46 | /** 47 | * Prevent server config files from being saved inside the current world directory. Instead, save them to the global config directory in .minecraft/config/. 48 | * This option effectively disables per world server configs, but helps a lot with avoiding user confusion. 49 | * 50 | * @return are server configs stored in the global .minecraft/config/ directory 51 | */ 52 | boolean forceGlobalServerConfigs(); 53 | 54 | /** 55 | * Path where default configs are stored, by default inside of .minecraft/defaultconfigs. 56 | *

This path is configurable via the Forge Config Api Port config. 57 | *

Default configs are mainly intended for server configs to allow pre-configured configs to be applied to every 58 | * newly created world (since server configs are handled per world). This mechanic also applies to other config types (although they are only created once). 59 | * 60 | * @return default configs path 61 | */ 62 | Path getDefaultConfigsDirectory(); 63 | } 64 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /amecs-api/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 | @rem This is normally unused 30 | set APP_BASE_NAME=%~n0 31 | set APP_HOME=%DIRNAME% 32 | 33 | @rem Resolve any "." and ".." in APP_HOME to make it shorter. 34 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi 35 | 36 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 37 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" 38 | 39 | @rem Find java.exe 40 | if defined JAVA_HOME goto findJavaFromJavaHome 41 | 42 | set JAVA_EXE=java.exe 43 | %JAVA_EXE% -version >NUL 2>&1 44 | if %ERRORLEVEL% equ 0 goto execute 45 | 46 | echo. 47 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 48 | echo. 49 | echo Please set the JAVA_HOME variable in your environment to match the 50 | echo location of your Java installation. 51 | 52 | goto fail 53 | 54 | :findJavaFromJavaHome 55 | set JAVA_HOME=%JAVA_HOME:"=% 56 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 57 | 58 | if exist "%JAVA_EXE%" goto execute 59 | 60 | echo. 61 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 62 | echo. 63 | echo Please set the JAVA_HOME variable in your environment to match the 64 | echo location of your Java installation. 65 | 66 | goto fail 67 | 68 | :execute 69 | @rem Setup the command line 70 | 71 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 72 | 73 | 74 | @rem Execute Gradle 75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* 76 | 77 | :end 78 | @rem End local scope for the variables with windows NT shell 79 | if %ERRORLEVEL% equ 0 goto mainEnd 80 | 81 | :fail 82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 83 | rem the _cmd.exe /c_ return code! 84 | set EXIT_CODE=%ERRORLEVEL% 85 | if %EXIT_CODE% equ 0 set EXIT_CODE=1 86 | if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% 87 | exit /b %EXIT_CODE% 88 | 89 | :mainEnd 90 | if "%OS%"=="Windows_NT" endlocal 91 | 92 | :omega 93 | -------------------------------------------------------------------------------- /reach-entity-attributes/build.gradle: -------------------------------------------------------------------------------- 1 | import org.gradle.util.GradleVersion 2 | import java.time.Instant 3 | 4 | plugins { 5 | id "dev.architectury.loom" 6 | id "net.nemerosa.versioning" version "3.0.0" 7 | id "maven-publish" 8 | } 9 | 10 | group = maven_group 11 | version = mod_version 12 | 13 | final isReleaseVersion = !version.endsWith("-SNAPSHOT") 14 | 15 | java { 16 | withSourcesJar() 17 | } 18 | 19 | loom { 20 | forge { 21 | mixinConfig "mixins.reach-entity-attributes.json" 22 | } 23 | mixin { 24 | defaultRefmapName.set("refmap.reach-entity-attributes.json") 25 | } 26 | runs { 27 | configureEach { 28 | property "mixin.debug", "true" 29 | property "mixin.debug.export.decompile", "false" 30 | property "mixin.debug.verbose", "true" 31 | property "mixin.dumpTargetOnFailure", "true" 32 | property "mixin.checks", "true" 33 | property "mixin.hotSwap", "true" 34 | } 35 | } 36 | } 37 | 38 | dependencies { 39 | mappings "net.fabricmc:yarn:$yarn_mappings:v2" 40 | forge "net.minecraftforge:forge:$forge_version" 41 | implementation("com.google.code.findbugs:jsr305:$jsr305_version") { 42 | transitive = false 43 | } 44 | annotationProcessor "net.fabricmc:sponge-mixin:0.12.5+mixin.0.8.5" 45 | } 46 | 47 | compileJava { 48 | options.with { 49 | it.release.set(17) 50 | it.fork = true 51 | it.deprecation = true 52 | it.encoding = "UTF-8" 53 | it.compilerArgs = ["-Xlint:all", "-parameters"] 54 | } 55 | } 56 | 57 | jar { 58 | from "/LICENSE" 59 | manifest.attributes([ 60 | "Build-Timestamp": Instant.now(), 61 | "Build-Revision": versioning.info.commit, 62 | "Build-Jvm": "" + 63 | "${System.getProperty("java.version")} (" + 64 | "${System.getProperty("java.vm.vendor")} " + 65 | "${System.getProperty("java.vm.version")})", 66 | "Built-By": GradleVersion.current(), 67 | 68 | "Implementation-Title": project.name, 69 | "Implementation-Version": project.version, 70 | "Implementation-Vendor": project.group, 71 | 72 | "Specification-Title": "FabricMod", 73 | "Specification-Version": "1.0.0", 74 | "Specification-Vendor": "dev.sapphic", 75 | 76 | "Sealed": "true" 77 | ]) 78 | } 79 | 80 | publishing { 81 | publications { 82 | mavenJava(MavenPublication) { 83 | afterEvaluate { 84 | artifact remapJar 85 | artifact(sourcesJar.archiveFile) { 86 | classifier = "sources" 87 | builtBy remapSourcesJar 88 | } 89 | } 90 | } 91 | } 92 | repositories { 93 | maven { 94 | url = "https://maven.jamieswhiteshirt.com/libs-" + (isReleaseVersion ? "release" : "snapshot") 95 | credentials { 96 | username = project.properties.jwsMavenUser 97 | password = project.properties.jwsMavenPassword 98 | } 99 | } 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /rei-bridge/src/main/java/me/shedaniel/rei/impl/common/compat/FabricFluidAPISupportPlugin.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is licensed under the MIT License, part of Roughly Enough Items. 3 | * Copyright (c) 2018, 2019, 2020, 2021, 2022, 2023 shedaniel 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 all 13 | * 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 THE 21 | * SOFTWARE. 22 | */ 23 | 24 | package me.shedaniel.rei.impl.common.compat; 25 | 26 | import dev.architectury.event.CompoundEventResult; 27 | import dev.architectury.fluid.FluidStack; 28 | import me.shedaniel.rei.api.common.entry.EntryStack; 29 | import me.shedaniel.rei.api.common.fluid.FluidSupportProvider; 30 | import me.shedaniel.rei.api.common.plugins.REIServerPlugin; 31 | import me.shedaniel.rei.api.common.util.EntryStacks; 32 | import net.fabricmc.fabric.api.transfer.v1.context.ContainerItemContext; 33 | import net.fabricmc.fabric.api.transfer.v1.fluid.FluidStorage; 34 | import net.fabricmc.fabric.api.transfer.v1.fluid.FluidVariant; 35 | import net.fabricmc.fabric.api.transfer.v1.storage.Storage; 36 | import net.minecraft.world.item.ItemStack; 37 | 38 | import java.util.List; 39 | import java.util.stream.StreamSupport; 40 | 41 | public class FabricFluidAPISupportPlugin implements REIServerPlugin { 42 | @Override 43 | public void registerFluidSupport(FluidSupportProvider support) { 44 | support.register(entry -> { 45 | ItemStack stack = entry.getValue().copy(); 46 | Storage storage = FluidStorage.ITEM.find(stack, ContainerItemContext.withConstant(stack)); 47 | if (storage != null) { 48 | List> result = StreamSupport.stream(storage.spliterator(), false) 49 | .filter(view -> !view.isResourceBlank()) 50 | .map(view -> EntryStacks.of(FluidStack.create(view.getResource().getFluid(), view.getAmount(), view.getResource().getComponents()))) 51 | .toList(); 52 | if (!result.isEmpty()) { 53 | return CompoundEventResult.interruptTrue(result.stream()); 54 | } 55 | } 56 | return CompoundEventResult.pass(); 57 | }); 58 | } 59 | } -------------------------------------------------------------------------------- /amecs-api/README.md: -------------------------------------------------------------------------------- 1 |

2 | Logo 3 | 4 | # Amecs API (or Amecs' API) 5 | 6 | ![supported Minecraft versions: 1.14 | 1.15 | 1.16 | 1.17 | 1.18 | 1.19](https://img.shields.io/badge/support%20for%20MC-1.14%20%7C%201.15%20%7C%201.16%20%7C%201.17%20%7C%201.18%20%7C%201.19-%2356AD56?style=for-the-badge) 7 | 8 | [![latest maven release](https://img.shields.io/maven-metadata/v?color=0f9fbc&metadataUrl=https%3A%2F%2Fmaven.siphalor.de%2Fde%2Fsiphalor%2Famecsapi-1.16%2Fmaven-metadata.xml&style=flat-square)](https://maven.siphalor.de/de/siphalor/amecsapi-1.16/) 9 | 10 | This library mod provides modifier keys for Minecraft keybindings as well as some related keybinding utilities 11 | 12 | **  13 | [Amecs](https://github.com/Siphalor/amecs) · 14 | [Discord](https://discord.gg/6gaXmbj) 15 |  ** 16 | 17 |
18 | 19 | ## Usage 20 | If you're not a modder you're probably looking for [Amecs](https://github.com/Siphalor/amecs). 21 | 22 | If you **are** a modder then you can use Amecs with the following in your build.gradle: 23 | 24 | ```groovy 25 | repositories { 26 | maven { 27 | url "https://maven.siphalor.de/" 28 | name "Siphalor's Maven" 29 | } 30 | } 31 | 32 | // VERSION: Check the badge above for the latest version 33 | // MINECRAFT_VERSION: The major Minecraft version you're developing for (e.g. 1.15 for 1.15.2) 34 | dependencies { 35 | include(modImplementation("de.siphalor:amecsapi-MINECRAFT_VERSION:VERSION")) 36 | } 37 | ``` 38 | 39 | ## Features 40 | 41 | If you want to see some example of how to use this library, you can take a look at the [testmod](./src/testmod/java/de/siphalor/amecs/testmod). 42 | 43 | ### Modifier Keys 44 | 45 | Modifier keys can be set by the user for all keybindings, including Vanilla ones. 46 | 47 | If you want to define a keybinding that uses modifier keys for its default value, you can extend the [`AmecsKeyBinding`](./src/main/java/de/siphalor/amecs/api/AmecsKeyBinding.java) class. 48 | 49 | If you want to further integrate this library, check the [`KeyBindingUtils`](./src/main/java/de/siphalor/amecs/api/KeyBindingUtils.java) class. 50 | 51 | ### Priority Keybindings 52 | 53 | Priority keybindings are keybindings that are executed before all other keybindings and are allowed to cancel further evaluation. 54 | This has various use cases, for example: 55 | 56 | - Keybindings that work when not in-game 57 | - Keybindings that work regardless if the chat or a GUI is open 58 | 59 | You can make use of priority keybindings by implementing the [`PriorityKeyBinding`](src/main/java/de/siphalor/amecs/api/PriorityKeyBinding.java) interface. 60 | 61 | Please always carefully check if your priority keybinding takes action in the right context. 62 | For example, you oftentimes don't want to execute your priority keybinding when the chat is open. 63 | 64 | ### Keybinding Descriptions 65 | 66 | Keybinding descriptions are a way to provide a description for a keybinding that are shown as a tooltip when hovering over the keybinding in the controls menu. 67 | 68 | You can add descriptions by defining translations for the keybinding's translation key with the suffix `.amecsapi.description`. 69 | 70 | ## License 71 | 72 | This mod is licensed under [the Apache 2.0 license](./LICENSE). 73 | -------------------------------------------------------------------------------- /energy-bridge/src/main/java/dev/su5ed/sinytra/connectorextras/energybridge/FabricEnergyStorageHandler.java: -------------------------------------------------------------------------------- 1 | package dev.su5ed.sinytra.connectorextras.energybridge; 2 | 3 | import net.fabricmc.fabric.api.transfer.v1.transaction.Transaction; 4 | import net.minecraft.world.item.ItemStack; 5 | import net.neoforged.neoforge.energy.IEnergyStorage; 6 | import team.reborn.energy.api.EnergyStorage; 7 | 8 | public class FabricEnergyStorageHandler implements IEnergyStorage { 9 | private final EnergyStorage storage; 10 | private final ItemStack stack; 11 | private final FabricEnergySlotHandler handler; 12 | 13 | public FabricEnergyStorageHandler(EnergyStorage storage) { 14 | this.storage = storage; 15 | this.stack = null; 16 | this.handler = null; 17 | } 18 | 19 | public FabricEnergyStorageHandler(EnergyStorage storage, ItemStack stack, FabricEnergySlotHandler handler) { 20 | this.storage = storage; 21 | this.stack = stack; 22 | this.handler = handler; 23 | } 24 | 25 | @Override 26 | public int receiveEnergy(int amount, boolean simulate) { 27 | if (Transaction.isOpen()) { 28 | return 0; 29 | } 30 | try (Transaction transaction = Transaction.openOuter()) { 31 | long e = EnergyBridge.convertForgeToFabricEnergy(amount); 32 | long originalAmount = this.storage.getAmount(); 33 | long inserted = (int) this.storage.insert(e, transaction); 34 | if (!simulate) { 35 | transaction.commit(); 36 | if (stack != null) { 37 | stack.applyComponents(handler.getStack().getComponents()); 38 | } 39 | } else if (stack != null && originalAmount == (this.storage.getAmount() - inserted)) { 40 | //Some implementations just commit the transaction by themselves, so it must be reverted afterwards 41 | //We can't just extract the energy because the storage could be insert-only 42 | handler.setStack(stack); 43 | } 44 | return EnergyBridge.unConvertForgeToFabricEnergy(inserted); 45 | } 46 | } 47 | 48 | @Override 49 | public int extractEnergy(int amount, boolean simulate) { 50 | if (Transaction.isOpen()) { 51 | return 0; 52 | } 53 | try (Transaction transaction = Transaction.openOuter()) { 54 | long e = EnergyBridge.unConvertFabricToForgeEnergy(amount); 55 | long extracted = (int) this.storage.extract(e, transaction); 56 | if (!simulate) { 57 | transaction.commit(); 58 | if (stack != null) { 59 | stack.applyComponents(handler.getStack().getComponents()); 60 | } 61 | } 62 | return EnergyBridge.convertFabricToForgeEnergy(extracted); 63 | } 64 | } 65 | 66 | @Override 67 | public int getEnergyStored() { 68 | return EnergyBridge.convertFabricToForgeEnergy(this.storage.getAmount()); 69 | } 70 | 71 | @Override 72 | public int getMaxEnergyStored() { 73 | return EnergyBridge.convertFabricToForgeEnergy(this.storage.getCapacity()); 74 | } 75 | 76 | @Override 77 | public boolean canExtract() { 78 | return this.storage.supportsExtraction(); 79 | } 80 | 81 | @Override 82 | public boolean canReceive() { 83 | return this.storage.supportsInsertion(); 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /energy-bridge/src/main/java/dev/su5ed/sinytra/connectorextras/energybridge/ForgeEnergyStorageHandler.java: -------------------------------------------------------------------------------- 1 | package dev.su5ed.sinytra.connectorextras.energybridge; 2 | 3 | import net.fabricmc.fabric.api.transfer.v1.context.ContainerItemContext; 4 | import net.fabricmc.fabric.api.transfer.v1.item.ItemVariant; 5 | import net.fabricmc.fabric.api.transfer.v1.transaction.Transaction; 6 | import net.fabricmc.fabric.api.transfer.v1.transaction.TransactionContext; 7 | import net.minecraft.world.item.ItemStack; 8 | import net.neoforged.neoforge.energy.IEnergyStorage; 9 | import team.reborn.energy.api.EnergyStorage; 10 | 11 | public class ForgeEnergyStorageHandler implements EnergyStorage { 12 | private final IEnergyStorage storage; 13 | private final ContainerItemContext context; 14 | private final ItemStack stack; 15 | 16 | public ForgeEnergyStorageHandler(IEnergyStorage storage) { 17 | this.storage = storage; 18 | this.context = null; 19 | this.stack = null; 20 | } 21 | 22 | public ForgeEnergyStorageHandler(IEnergyStorage storage, ContainerItemContext context, ItemStack stack) { 23 | this.storage = storage; 24 | this.context = context; 25 | this.stack = stack; 26 | } 27 | 28 | @Override 29 | public long insert(long maxAmount, TransactionContext transaction) { 30 | int fe = EnergyBridge.convertFabricToForgeEnergy(maxAmount); 31 | int inserted = this.storage.receiveEnergy(fe, true); 32 | transaction.addCloseCallback((context, result) -> { 33 | if (result.wasCommitted()) { 34 | this.storage.receiveEnergy(fe, false); 35 | updateStack(); 36 | } 37 | }); 38 | return EnergyBridge.unConvertFabricToForgeEnergy(inserted); 39 | } 40 | 41 | @Override 42 | public long extract(long maxAmount, TransactionContext transaction) { 43 | int fe = EnergyBridge.unConvertForgeToFabricEnergy(maxAmount); 44 | int extracted = this.storage.extractEnergy(fe, true); 45 | transaction.addCloseCallback((context, result) -> { 46 | if (result.wasCommitted()) { 47 | this.storage.extractEnergy(fe, false); 48 | updateStack(); 49 | } 50 | }); 51 | return EnergyBridge.convertForgeToFabricEnergy(extracted); 52 | } 53 | 54 | private void updateStack() { 55 | if (stack != null) { 56 | //We can't open a new Transaction while one is closing, so we make a new Thread 57 | Thread thread = new Thread(() -> { 58 | try (Transaction t = Transaction.openOuter()) { 59 | //Update the item (NBT). 60 | this.context.extract(this.context.getItemVariant(), 1, t); 61 | this.context.insert(ItemVariant.of(stack), 1, t); 62 | t.commit(); 63 | } 64 | }); 65 | thread.start(); 66 | } 67 | } 68 | 69 | @Override 70 | public long getAmount() { 71 | return EnergyBridge.convertForgeToFabricEnergy(this.storage.getEnergyStored()); 72 | } 73 | 74 | @Override 75 | public long getCapacity() { 76 | return EnergyBridge.convertForgeToFabricEnergy(this.storage.getMaxEnergyStored()); 77 | } 78 | 79 | @Override 80 | public boolean supportsInsertion() { 81 | return this.storage.canReceive(); 82 | } 83 | 84 | @Override 85 | public boolean supportsExtraction() { 86 | return this.storage.canExtract(); 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /forgeconfigapiport/src/main/java/dev/su5ed/sinytra/connectorextras/forgeconfigapiport/ForgeConfigRegistryImpl.java: -------------------------------------------------------------------------------- 1 | package dev.su5ed.sinytra.connectorextras.forgeconfigapiport; 2 | 3 | import cpw.mods.modlauncher.api.LamdbaExceptionUtils; 4 | import fuzs.forgeconfigapiport.api.config.v2.ForgeConfigRegistry; 5 | import net.minecraftforge.fml.ModContainer; 6 | import net.minecraftforge.fml.ModList; 7 | import net.minecraftforge.fml.config.IConfigSpec; 8 | import net.minecraftforge.fml.config.ModConfig; 9 | import net.minecraftforge.fml.unsafe.UnsafeHacks; 10 | 11 | import java.lang.reflect.Constructor; 12 | import java.lang.reflect.Field; 13 | import java.util.HashMap; 14 | import java.util.Map; 15 | import java.util.function.Function; 16 | 17 | public class ForgeConfigRegistryImpl implements ForgeConfigRegistry { 18 | private final Map configs = new HashMap<>(); 19 | 20 | @Override 21 | public ModConfig register(String modId, ModConfig.Type type, IConfigSpec spec) { 22 | return createModConfig(modId, c -> new ModConfig(type, spec, c)); 23 | } 24 | 25 | @Override 26 | public ModConfig register(String modId, ModConfig.Type type, IConfigSpec spec, String fileName) { 27 | return createModConfig(modId, c -> new ModConfig(type, spec, c, fileName)); 28 | } 29 | 30 | public void processConfigs() { 31 | Field containerField = LamdbaExceptionUtils.uncheck(() -> { 32 | Field field = ModConfig.class.getDeclaredField("container"); 33 | field.setAccessible(true); 34 | return field; 35 | }); 36 | configs.forEach((modid, config) -> { 37 | ModContainer container = getModContainer(modid); 38 | container.addConfig(config); 39 | try { 40 | UnsafeHacks.setField(containerField, config, container); 41 | } catch (Throwable t) { 42 | throw new RuntimeException(t); 43 | } 44 | }); 45 | configs.clear(); 46 | } 47 | 48 | private ModConfig createModConfig(String modid, Function configConstructor) { 49 | ModList modList = ModList.get(); 50 | if (modList == null) { 51 | ModContainer container = createPlaceholderContainer(modid); 52 | ModConfig config = configConstructor.apply(container); 53 | configs.put(modid, config); 54 | return config; 55 | } else { 56 | ModContainer container = getModContainer(modid); 57 | ModConfig config = configConstructor.apply(container); 58 | container.addConfig(config); 59 | return config; 60 | } 61 | } 62 | 63 | private static ModContainer createPlaceholderContainer(String modId) { 64 | try { 65 | Class cls = Class.forName("net.minecraftforge.fml.ModLoader$ErroredModContainer"); 66 | Constructor ctr = cls.getDeclaredConstructor(); 67 | ctr.setAccessible(true); 68 | ModContainer container = (ModContainer) ctr.newInstance(); 69 | Field modidField = ModContainer.class.getDeclaredField("modId"); 70 | modidField.setAccessible(true); 71 | UnsafeHacks.setField(modidField, container, modId); 72 | 73 | return container; 74 | } catch (Throwable t) { 75 | throw new RuntimeException(t); 76 | } 77 | } 78 | 79 | private static ModContainer getModContainer(String modid) { 80 | return ModList.get().getModContainerById(modid).orElseThrow(() -> new RuntimeException("Mod container not found for mod " + modid)); 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /amecs-api/src/main/java/de/siphalor/amecs/api/KeyModifier.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2023 Siphalor 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package de.siphalor.amecs.api; 18 | 19 | import com.google.common.collect.BiMap; 20 | import com.google.common.collect.ImmutableBiMap; 21 | import de.siphalor.amecs.impl.AmecsAPI; 22 | import net.fabricmc.api.EnvType; 23 | import net.fabricmc.api.Environment; 24 | import net.minecraft.client.util.InputUtil; 25 | import org.apache.commons.lang3.ArrayUtils; 26 | 27 | import java.util.function.Function; 28 | import java.util.stream.Collectors; 29 | import java.util.stream.Stream; 30 | 31 | @SuppressWarnings("WeakerAccess") 32 | @Environment(EnvType.CLIENT) 33 | public enum KeyModifier { 34 | // the order of the enums makes a difference when generating the shown name in the gui 35 | // with this order the old text order is preserved. But now the id values do not increment nicely. But changing them would eliminate 36 | // backward compatibility with the old save format 37 | NONE("none", -1), 38 | ALT("alt", 0, 342, 346), 39 | SHIFT("shift", 2, 340, 344), 40 | CONTROL("control", 1, 341, 345); 41 | 42 | // using this array for the values because it is faster than calling values() every time 43 | public static final KeyModifier[] VALUES = KeyModifier.values(); 44 | private static final BiMap FORGE_MAP = ImmutableBiMap.copyOf(Stream.of(VALUES) 45 | .collect(Collectors.toMap(Function.identity(), m -> net.minecraftforge.client.settings.KeyModifier.valueFromString(m.name())))); 46 | 47 | public final String name; 48 | public final int id; 49 | // these keyCodes are all from Type: InputUtil.Type.KEYSYM 50 | final int[] keyCodes; 51 | 52 | KeyModifier(String name, int id, int... keyCodes) { 53 | this.name = name; 54 | this.id = id; 55 | this.keyCodes = keyCodes; 56 | } 57 | 58 | public static KeyModifier fromKeyCode(int keyCode) { 59 | for (KeyModifier keyModifier : VALUES) { 60 | if (keyModifier == NONE) { 61 | continue; 62 | } 63 | if (keyModifier.matches(keyCode)) { 64 | return keyModifier; 65 | } 66 | } 67 | return NONE; 68 | } 69 | 70 | public static KeyModifier fromKey(InputUtil.Key key) { 71 | if (key == null || key.getCategory() != InputUtil.Type.KEYSYM) { 72 | return NONE; 73 | } 74 | return fromKeyCode(key.getCode()); 75 | } 76 | 77 | public boolean matches(int keyCode) { 78 | return ArrayUtils.contains(keyCodes, keyCode); 79 | } 80 | 81 | public String getTranslationKey() { 82 | return AmecsAPI.MOD_ID + ".modifier." + name; 83 | } 84 | 85 | public static int getModifierCount() { 86 | return VALUES.length - 1; // remove 1 for NONE 87 | } 88 | 89 | public net.minecraftforge.client.settings.KeyModifier toForgeKeyModifier() { 90 | return FORGE_MAP.getOrDefault(this, net.minecraftforge.client.settings.KeyModifier.NONE); 91 | } 92 | 93 | public static KeyModifier fromForgeKeyModifier(net.minecraftforge.client.settings.KeyModifier modifier) { 94 | return FORGE_MAP.inverse().getOrDefault(modifier, NONE); 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /amecs-api/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'dev.architectury.loom' 3 | id 'maven-publish' 4 | id 'org.cadixdev.licenser' version '0.6.1' 5 | } 6 | 7 | sourceCompatibility = JavaVersion.VERSION_1_8 8 | targetCompatibility = JavaVersion.VERSION_1_8 9 | 10 | archivesBaseName = project.archives_base_name 11 | version = "$mod_version+mc$minecraft_version".toString() 12 | group = project.maven_group 13 | 14 | sourceSets { 15 | testmod { 16 | compileClasspath += main.compileClasspath 17 | runtimeClasspath += main.runtimeClasspath 18 | } 19 | } 20 | 21 | loom { 22 | accessWidenerPath.set(file("src/main/resources/amecsapi.accesswidener")) 23 | forge { 24 | mixinConfig "amecsapi.mixins.json" 25 | convertAccessWideners = true 26 | } 27 | mixin { 28 | defaultRefmapName.set("refmap.amecsapi.json") 29 | } 30 | runs { 31 | configureEach { 32 | property "mixin.debug", "true" 33 | property "mixin.debug.export.decompile", "false" 34 | property "mixin.debug.verbose", "true" 35 | property "mixin.dumpTargetOnFailure", "true" 36 | property "mixin.checks", "true" 37 | property "mixin.hotSwap", "true" 38 | } 39 | testmodClient { 40 | client() 41 | source sourceSets.testmod 42 | } 43 | } 44 | loom.mods.register("amecsapi_testmod") { 45 | sourceSet sourceSets.testmod 46 | } 47 | } 48 | 49 | repositories { 50 | maven { 51 | name "Siphalor's Maven" 52 | url "https://maven.siphalor.de" 53 | } 54 | maven { 55 | url "https://jitpack.io" 56 | } 57 | mavenLocal() 58 | } 59 | 60 | dependencies { 61 | //to change the versions see the gradle.properties file 62 | forge "net.minecraftforge:forge:$forge_version" 63 | mappings "net.fabricmc:yarn:${project.minecraft_version}+build.${project.yarn_mappings}:v2" 64 | modImplementation "net.fabricmc:fabric-loader:${project.loader_version}" 65 | 66 | compileOnly(annotationProcessor("org.projectlombok:lombok:$lombok_version")) 67 | testCompileOnly(testAnnotationProcessor("org.projectlombok:lombok:$lombok_version")) 68 | 69 | //modImplementation("de.siphalor:nmuk-${project.minecraft_major_version}:1.0.1+mc1.19.3") { 70 | // exclude module: "amecsapi-${project.minecraft_major_version}" 71 | //} 72 | 73 | modImplementation('dev.su5ed.sinytra.fabric-api:fabric-api-base:0.4.30+ef105b4977') 74 | modImplementation('dev.su5ed.sinytra.fabric-api:fabric-key-binding-api-v1:1.0.36+561530ec77') 75 | 76 | testmodImplementation sourceSets.main.output 77 | } 78 | 79 | license { 80 | header = project.file('LICENSE_HEADER') 81 | 82 | include '**/*.java' 83 | } 84 | 85 | processResources { 86 | inputs.property "version", project.version 87 | 88 | afterEvaluate { 89 | from(sourceSets.main.resources.srcDirs) { 90 | include "fabric.mod.json" 91 | expand "version": version 92 | duplicatesStrategy DuplicatesStrategy.INCLUDE 93 | } 94 | } 95 | } 96 | 97 | // ensure that the encoding is set to UTF-8, no matter what the system default is 98 | // this fixes some edge cases with special characters not displaying correctly 99 | // see http://yodaconditions.net/blog/fix-for-java-file-encoding-problems-with-gradle.html 100 | tasks.withType(JavaCompile).configureEach { 101 | options.encoding = "UTF-8" 102 | } 103 | 104 | jar { 105 | from "LICENSE" 106 | } 107 | 108 | // configure the maven publication 109 | publishing { 110 | publications { 111 | create("mavenJava", MavenPublication) { 112 | artifactId = "${project.archives_base_name}-${project.minecraft_major_version}".toString() 113 | 114 | from components.java 115 | java.withSourcesJar() 116 | } 117 | } 118 | 119 | // select the repositories you want to publish to 120 | repositories { 121 | if (project.hasProperty("siphalorMavenPassword")) { 122 | maven { 123 | name = "Siphalor" 124 | url = "https://maven.siphalor.de/upload.php" 125 | credentials { 126 | username = siphalorMavenUser 127 | password = siphalorMavenPassword 128 | } 129 | } 130 | } 131 | } 132 | } 133 | -------------------------------------------------------------------------------- /amecs-api/src/main/java/de/siphalor/amecs/api/AmecsKeyBinding.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2023 Siphalor 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package de.siphalor.amecs.api; 18 | 19 | import net.fabricmc.api.EnvType; 20 | import net.fabricmc.api.Environment; 21 | import net.minecraft.client.option.KeyBinding; 22 | import net.minecraft.client.util.InputUtil; 23 | import net.minecraft.util.Identifier; 24 | import net.minecraftforge.client.settings.KeyConflictContext; 25 | import net.minecraftforge.client.settings.KeyModifier; 26 | 27 | /** 28 | * A {@link net.minecraft.client.option.KeyBinding} base class to be used when you want to define modifiers keys as default 29 | */ 30 | @Environment(EnvType.CLIENT) 31 | public class AmecsKeyBinding extends KeyBinding { 32 | private final KeyModifiers defaultModifiers; 33 | 34 | /** 35 | * Constructs a new amecs keybinding. And because how the vanilla key binding works. It is automatically registered. 36 | *
37 | * See {@link KeyBindingUtils#unregisterKeyBinding(KeyBinding)} for how to unregister it 38 | * If you want to set the key's translationKey directly use {@link #AmecsKeyBinding(String, net.minecraft.client.util.InputUtil.Type, int, String, KeyModifiers)} instead 39 | * 40 | * @param id the id to use 41 | * @param type the input type which triggers this keybinding 42 | * @param code the default key code 43 | * @param category the id of the category which should include this keybinding 44 | * @param defaultModifiers the default modifiers 45 | */ 46 | public AmecsKeyBinding(Identifier id, InputUtil.Type type, int code, String category, KeyModifiers defaultModifiers) { 47 | this("key." + id.getNamespace() + "." + id.getPath(), type, code, category, defaultModifiers); 48 | } 49 | 50 | /** 51 | * Constructs a new amecs keybinding. And because how the vanilla key binding works. It is automatically registered. 52 | *
53 | * See {@link KeyBindingUtils#unregisterKeyBinding(KeyBinding)} for how to unregister it 54 | * 55 | * @param id the id to use 56 | * @param type the input type which triggers this keybinding 57 | * @param code the default key code 58 | * @param category the id of the category which should include this keybinding 59 | * @param defaultModifiers the default modifiers 60 | */ 61 | public AmecsKeyBinding(String id, InputUtil.Type type, int code, String category, KeyModifiers defaultModifiers) { 62 | super(id, KeyConflictContext.UNIVERSAL, defaultModifiers != null ? defaultModifiers.getFirst() : KeyModifier.NONE, type, code, category); 63 | if (defaultModifiers == null || defaultModifiers == KeyModifiers.NO_MODIFIERS) { 64 | defaultModifiers = new KeyModifiers(); // the modifiable version of: KeyModifiers.NO_MODIFIERS 65 | } 66 | this.defaultModifiers = defaultModifiers; 67 | } 68 | 69 | @Override 70 | public void setPressed(boolean pressed) { 71 | super.setPressed(pressed); 72 | if (pressed) { 73 | onPressed(); 74 | } else { 75 | onReleased(); 76 | } 77 | } 78 | 79 | /** 80 | * A convenience method which gets fired when the keybinding is used 81 | */ 82 | public void onPressed() { 83 | } 84 | 85 | /** 86 | * A convenience method which gets fired when the keybinding is stopped being used 87 | */ 88 | public void onReleased() { 89 | } 90 | 91 | /** 92 | * Resets this keybinding (triggered when the user clicks on the "Reset" button). 93 | */ 94 | public void resetKeyBinding() { 95 | setKeyModifierAndCode(getDefaultKeyModifier(), getKey()); 96 | } 97 | 98 | public KeyModifiers getDefaultModifiers() { 99 | return defaultModifiers; 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /energy-bridge/src/main/java/dev/su5ed/sinytra/connectorextras/energybridge/EnergyBridgeSetup.java: -------------------------------------------------------------------------------- 1 | package dev.su5ed.sinytra.connectorextras.energybridge; 2 | 3 | import net.fabricmc.fabric.api.transfer.v1.context.ContainerItemContext; 4 | import net.minecraft.core.registries.BuiltInRegistries; 5 | import net.minecraft.world.item.Item; 6 | import net.minecraft.world.level.block.Block; 7 | import net.neoforged.bus.api.IEventBus; 8 | import net.neoforged.neoforge.capabilities.Capabilities; 9 | import net.neoforged.neoforge.capabilities.RegisterCapabilitiesEvent; 10 | import net.neoforged.neoforge.energy.IEnergyStorage; 11 | import team.reborn.energy.api.EnergyStorage; 12 | 13 | import java.util.HashMap; 14 | import java.util.Map; 15 | import java.util.Optional; 16 | 17 | public class EnergyBridgeSetup { 18 | private static final ThreadLocal COMPUTING_CAPABILITY_LOCK = ThreadLocal.withInitial(() -> false); 19 | private static final Map CAPS = new HashMap<>(); 20 | 21 | public static void init(IEventBus bus) { 22 | EnergyStorage.SIDED.registerFallback((world, pos, state, blockEntity, context) -> { 23 | if (blockEntity != null && !COMPUTING_CAPABILITY_LOCK.get()) { 24 | COMPUTING_CAPABILITY_LOCK.set(true); 25 | EnergyStorage storage = Optional.ofNullable(world.getCapability(Capabilities.EnergyStorage.BLOCK, pos, state, blockEntity, context)) 26 | .map(ForgeEnergyStorageHandler::new) 27 | .orElse(null); 28 | COMPUTING_CAPABILITY_LOCK.set(false); 29 | return storage; 30 | } 31 | return null; 32 | }); 33 | EnergyStorage.ITEM.registerFallback((stack, context) -> { 34 | if (!stack.isEmpty() && !COMPUTING_CAPABILITY_LOCK.get()) { 35 | COMPUTING_CAPABILITY_LOCK.set(true); 36 | EnergyStorage storage = Optional.ofNullable(stack.getCapability(Capabilities.EnergyStorage.ITEM, null)) 37 | .map(s -> new ForgeEnergyStorageHandler(s, context, stack)) 38 | .orElse(null); 39 | COMPUTING_CAPABILITY_LOCK.set(false); 40 | return storage; 41 | } 42 | return null; 43 | }); 44 | 45 | bus.addListener(EnergyBridgeSetup::onRegisterCapabilities); 46 | } 47 | 48 | private static void onRegisterCapabilities(RegisterCapabilitiesEvent event) { 49 | for (Block block : BuiltInRegistries.BLOCK) { 50 | event.registerBlock( 51 | Capabilities.EnergyStorage.BLOCK, 52 | (level, pos, state, blockEntity, context) -> { 53 | if (!COMPUTING_CAPABILITY_LOCK.get() && (blockEntity == null || blockEntity.hasLevel())) { 54 | COMPUTING_CAPABILITY_LOCK.set(true); 55 | EnergyStorage storage = EnergyStorage.SIDED.find(level, pos, state, blockEntity, context); 56 | COMPUTING_CAPABILITY_LOCK.set(false); 57 | if (storage != null) { 58 | return (IEnergyStorage) CAPS.computeIfAbsent(storage, s -> new FabricEnergyStorageHandler(storage)); 59 | } 60 | } 61 | return null; 62 | }, 63 | block 64 | ); 65 | } 66 | for (Item item : BuiltInRegistries.ITEM) { 67 | event.registerItem( 68 | Capabilities.EnergyStorage.ITEM, 69 | (stack, context) -> { 70 | if (!COMPUTING_CAPABILITY_LOCK.get()) { 71 | COMPUTING_CAPABILITY_LOCK.set(true); 72 | FabricEnergySlotHandler handler = new FabricEnergySlotHandler(stack); 73 | EnergyStorage storage = EnergyStorage.ITEM.find(stack, ContainerItemContext.ofSingleSlot(handler)); 74 | COMPUTING_CAPABILITY_LOCK.set(false); 75 | if (storage != null) { 76 | return (IEnergyStorage) CAPS.computeIfAbsent(storage, b -> new FabricEnergyStorageHandler(storage, stack, handler)); 77 | } 78 | } 79 | return null; 80 | }, 81 | item 82 | ); 83 | } 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /extras-utils/src/main/java/dev/su5ed/sinytra/connectorextras/util/HackyModuleInjector.java: -------------------------------------------------------------------------------- 1 | package dev.su5ed.sinytra.connectorextras.util; 2 | 3 | import com.mojang.logging.LogUtils; 4 | import cpw.mods.jarhandling.SecureJar; 5 | import cpw.mods.modlauncher.Launcher; 6 | import cpw.mods.modlauncher.api.IModuleLayerManager; 7 | import org.slf4j.Logger; 8 | import sun.misc.Unsafe; 9 | 10 | import java.io.IOException; 11 | import java.io.InputStream; 12 | import java.lang.module.ModuleDescriptor; 13 | import java.lang.module.ModuleReference; 14 | import java.lang.module.ResolvedModule; 15 | import java.lang.reflect.Field; 16 | import java.net.URI; 17 | import java.net.URISyntaxException; 18 | import java.net.URL; 19 | import java.nio.file.FileSystem; 20 | import java.nio.file.FileSystems; 21 | import java.nio.file.Files; 22 | import java.nio.file.Path; 23 | import java.security.CodeSigner; 24 | import java.util.Map; 25 | import java.util.Optional; 26 | import java.util.jar.Manifest; 27 | 28 | import static cpw.mods.modlauncher.api.LambdaExceptionUtils.uncheck; 29 | 30 | public class HackyModuleInjector { 31 | private static final Logger LOGGER = LogUtils.getLogger(); 32 | public static final Unsafe UNSAFE = uncheck(() -> { 33 | Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe"); 34 | theUnsafe.setAccessible(true); 35 | return (Unsafe) theUnsafe.get(null); 36 | }); 37 | 38 | public static boolean injectModuleSources(String moduleName, URL source) { 39 | try { 40 | ModuleLayer layer = Launcher.INSTANCE.findLayerManager().orElseThrow().getLayer(IModuleLayerManager.Layer.GAME).orElseThrow(); 41 | ResolvedModule module = layer.configuration().findModule(moduleName).orElse(null); 42 | if (module == null) { 43 | LOGGER.warn("Module {} is not present, skipping class injection", moduleName); 44 | return false; 45 | } 46 | 47 | Class jarModuleReference = Class.forName("cpw.mods.cl.JarModuleFinder$JarModuleReference"); 48 | ModuleReference reference = module.reference(); 49 | if (!jarModuleReference.isInstance(reference)) { 50 | LOGGER.error("Module {} does not contain a jar module reference", moduleName); 51 | return false; 52 | } 53 | 54 | Field jarField = jarModuleReference.getDeclaredField("jar"); 55 | SecureJar.ModuleDataProvider originalProvider = (SecureJar.ModuleDataProvider) UNSAFE.getObject(reference, UNSAFE.objectFieldOffset(jarField)); 56 | Path relocatePath = getRelocatedClassesPath(source); 57 | if (relocatePath == null) { 58 | LOGGER.error("Source path for {} not found", moduleName); 59 | return false; 60 | } 61 | SecureJar.ModuleDataProvider wrappedProvider = new ModuleDataProviderWrapper(originalProvider, relocatePath); 62 | UNSAFE.putObject(reference, UNSAFE.objectFieldOffset(jarField), wrappedProvider); 63 | 64 | LOGGER.debug("Successfully injected source {} into module {}", source, moduleName); 65 | return true; 66 | } catch (Throwable t) { 67 | LOGGER.error("Error injecting classes into module {}", moduleName, t); 68 | return false; 69 | } 70 | } 71 | 72 | private static Path getRelocatedClassesPath(URL source) throws URISyntaxException, IOException { 73 | if (source != null) { 74 | Path sourcePath = Path.of(source.toURI()); 75 | URI pathFsUri = new URI("path://" + source.getPath()); 76 | FileSystem pathFS = FileSystems.newFileSystem(pathFsUri, Map.of("packagePath", sourcePath)); 77 | return pathFS.getPath("/"); 78 | } 79 | return null; 80 | } 81 | 82 | public record ModuleDataProviderWrapper(SecureJar.ModuleDataProvider provider, Path relocatePath) implements SecureJar.ModuleDataProvider { 83 | @Override 84 | public Optional open(String name) { 85 | return provider.open(name) 86 | .or(() -> { 87 | try { 88 | Path path = relocatePath.resolve(name); 89 | return Optional.of(Files.newInputStream(path)); 90 | } catch (Exception ignored) { 91 | } 92 | return Optional.empty(); 93 | }); 94 | } 95 | 96 | //@formatter:off 97 | @Override public String name() {return provider.name();} 98 | @Override public ModuleDescriptor descriptor() {return provider.descriptor();} 99 | @Override public URI uri() {return provider.uri();} 100 | @Override public Optional findFile(String name) {return provider.findFile(name);} 101 | @Override public Manifest getManifest() {return provider.getManifest();} 102 | @Override public CodeSigner[] verifyAndGetSigners(String cname, byte[] bytes) {return provider.verifyAndGetSigners(cname, bytes);} 103 | //@formatter:on 104 | } 105 | } 106 | -------------------------------------------------------------------------------- /amecs-api/src/main/java/de/siphalor/amecs/impl/KeyBindingManager.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2023 Siphalor 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package de.siphalor.amecs.impl; 18 | 19 | import de.siphalor.amecs.api.PriorityKeyBinding; 20 | import de.siphalor.amecs.impl.mixin.KeyMappingLookupAccessor; 21 | import net.fabricmc.api.EnvType; 22 | import net.fabricmc.api.Environment; 23 | import net.minecraft.client.option.KeyBinding; 24 | import net.minecraft.client.util.InputUtil; 25 | import net.minecraftforge.client.settings.KeyMappingLookup; 26 | import net.minecraftforge.client.settings.KeyModifier; 27 | import net.minecraftforge.fml.util.ObfuscationReflectionHelper; 28 | import org.jetbrains.annotations.ApiStatus; 29 | 30 | import java.util.*; 31 | import java.util.stream.Collectors; 32 | import java.util.stream.Stream; 33 | 34 | @Environment(EnvType.CLIENT) 35 | @ApiStatus.Internal 36 | public class KeyBindingManager { 37 | private static final Map> PRIORITY_KEY_BINDINGS = new HashMap<>(); 38 | 39 | private KeyBindingManager() { 40 | } 41 | 42 | /** 43 | * Registers a key binding to Amecs API 44 | * 45 | * @param keyBinding the key binding to register 46 | * @return whether the keyBinding was added. It is not added if it is already contained 47 | */ 48 | public static boolean register(KeyBinding keyBinding) { 49 | if (keyBinding instanceof PriorityKeyBinding) { 50 | PRIORITY_KEY_BINDINGS.computeIfAbsent(keyBinding.getKey(), k -> new ArrayList<>()).add(keyBinding); 51 | return true; 52 | } else { 53 | KeyMappingLookup lookup = getKeyMappingLookup(); 54 | EnumMap>> map = ((KeyMappingLookupAccessor) lookup).getMap(); 55 | if (!map.get(keyBinding.getKeyModifier()).containsKey(keyBinding.getKey())) { 56 | lookup.put(keyBinding.getKey(), keyBinding); 57 | return true; 58 | } 59 | return false; 60 | } 61 | } 62 | 63 | /** 64 | * Unregisters a key binding from Amecs API 65 | * 66 | * @param id the key binding to unregister 67 | * @return whether the keyBinding was removed. It is not removed if it was not contained 68 | */ 69 | public static boolean unregister(String id) { 70 | KeyMappingLookup lookup = getKeyMappingLookup(); 71 | EnumMap>> map = ((KeyMappingLookupAccessor) lookup).getMap(); 72 | for (Map> keyMap : map.values()) { 73 | for (Collection keys : keyMap.values()) { 74 | for (KeyBinding key : keys) { 75 | if (key.getTranslationKey().equals(id)) { 76 | keys.remove(key); 77 | return true; 78 | } 79 | } 80 | } 81 | } 82 | return false; 83 | } 84 | 85 | public static Stream getMatchingKeyBindings(InputUtil.Key keyCode) { 86 | List keyBindingList = PRIORITY_KEY_BINDINGS.get(keyCode); 87 | if (keyBindingList == null) 88 | return Stream.empty(); 89 | Stream result = keyBindingList.stream().filter(KeyBindingManager::areExactModifiersPressed); 90 | List keyBindings = result.collect(Collectors.toList()); 91 | if (keyBindings.isEmpty()) 92 | return keyBindingList.stream().filter(keyBinding -> keyBinding.getKeyModifier() == KeyModifier.NONE); 93 | return keyBindings.stream(); 94 | } 95 | 96 | private static boolean areExactModifiersPressed(KeyBinding keyBinding) { 97 | return keyBinding.getKeyModifier() == KeyModifier.getActiveModifier(); 98 | } 99 | 100 | public static boolean onKeyPressedPriority(InputUtil.Key keyCode) { 101 | // because streams are lazily evaluated, this code only calls onPressedPriority so often until one returns true 102 | Optional keyBindings = getMatchingKeyBindings(keyCode).filter(keyBinding -> ((PriorityKeyBinding) keyBinding).onPressedPriority()).findFirst(); 103 | return keyBindings.isPresent(); 104 | } 105 | 106 | public static boolean onKeyReleasedPriority(InputUtil.Key keyCode) { 107 | // because streams are lazily evaluated, this code only calls onPressedPriority so often until one returns true 108 | Optional keyBindings = getMatchingKeyBindings(keyCode).filter(keyBinding -> ((PriorityKeyBinding) keyBinding).onReleasedPriority()).findFirst(); 109 | return keyBindings.isPresent(); 110 | } 111 | 112 | public static KeyMappingLookup getKeyMappingLookup() { 113 | return ObfuscationReflectionHelper.getPrivateValue(KeyBinding.class, null, "MAP"); 114 | } 115 | } 116 | -------------------------------------------------------------------------------- /amecs-api/src/main/java/de/siphalor/amecs/impl/mixin/MixinMouse.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2023 Siphalor 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package de.siphalor.amecs.impl.mixin; 18 | 19 | import de.siphalor.amecs.api.KeyBindingUtils; 20 | import de.siphalor.amecs.api.KeyModifier; 21 | import de.siphalor.amecs.impl.AmecsAPI; 22 | import net.fabricmc.api.EnvType; 23 | import net.fabricmc.api.Environment; 24 | import net.minecraft.client.MinecraftClient; 25 | import net.minecraft.client.Mouse; 26 | import net.minecraft.client.gui.screen.option.KeybindsScreen; 27 | import net.minecraft.client.option.KeyBinding; 28 | import net.minecraft.client.util.InputUtil; 29 | import org.spongepowered.asm.mixin.Final; 30 | import org.spongepowered.asm.mixin.Mixin; 31 | import org.spongepowered.asm.mixin.Shadow; 32 | import org.spongepowered.asm.mixin.injection.At; 33 | import org.spongepowered.asm.mixin.injection.Inject; 34 | import org.spongepowered.asm.mixin.injection.Surrogate; 35 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; 36 | import org.spongepowered.asm.mixin.injection.callback.LocalCapture; 37 | 38 | // TODO: Fix the priority when Mixin 0.8 is a thing and try again (-> MaLiLib causes incompatibilities) 39 | @Environment(EnvType.CLIENT) 40 | @Mixin(value = Mouse.class, priority = -2000) 41 | public class MixinMouse { 42 | @Shadow 43 | @Final 44 | private MinecraftClient client; 45 | 46 | @Shadow 47 | private double eventDeltaWheel; 48 | 49 | // If this method changes make sure to also change the corresponding code in KTIG 50 | private void onScrollReceived(double deltaY, boolean manualDeltaWheel, int scrollAmount) { 51 | if (manualDeltaWheel) { 52 | // from minecraft but patched 53 | // this code might be wrong when the vanilla mc code changes 54 | if (eventDeltaWheel != 0.0D && Math.signum(deltaY) != Math.signum(eventDeltaWheel)) { 55 | eventDeltaWheel = 0.0D; 56 | } 57 | 58 | eventDeltaWheel += deltaY; 59 | scrollAmount = (int) eventDeltaWheel; 60 | if (scrollAmount == 0) { 61 | return; 62 | } 63 | 64 | eventDeltaWheel -= scrollAmount; 65 | // -from minecraft 66 | } 67 | 68 | InputUtil.Key keyCode = KeyBindingUtils.getKeyFromScroll(scrollAmount); 69 | 70 | KeyBinding.setKeyPressed(keyCode, true); 71 | scrollAmount = Math.abs(scrollAmount); 72 | 73 | while (scrollAmount > 0) { 74 | KeyBinding.onKeyPressed(keyCode); 75 | scrollAmount--; 76 | } 77 | KeyBinding.setKeyPressed(keyCode, false); 78 | 79 | // default minecraft scroll logic is in HotbarScrollKeyBinding in amecs 80 | } 81 | 82 | @SuppressWarnings("InvalidInjectorMethodSignature") 83 | @Inject(method = "onMouseScroll", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/network/ClientPlayerEntity;isSpectator()Z", ordinal = 0), locals = LocalCapture.CAPTURE_FAILHARD) 84 | private void isSpectator_onMouseScroll(long window, double rawX, double rawY, CallbackInfo callbackInfo, double offset, double deltaY, int scrollAmount) { 85 | if (AmecsAPI.TRIGGER_KEYBINDING_ON_SCROLL) { 86 | onScrollReceived(KeyBindingUtils.getLastScrollAmount(), false, scrollAmount); 87 | } 88 | } 89 | 90 | @Surrogate 91 | private void isSpectator_onMouseScroll(long window, double rawX, double rawY, CallbackInfo callbackInfo, double offset, double deltaY, float scrollAmount) { 92 | isSpectator_onMouseScroll(window, rawX, rawY, callbackInfo, offset, deltaY, (int) scrollAmount); 93 | } 94 | 95 | // Invoked from ASM coremod hook 96 | @SuppressWarnings("unused") 97 | private boolean amecs$onMouseScrolledScreen(boolean handled) { 98 | if (handled) { 99 | return true; 100 | } 101 | 102 | if (AmecsAPI.TRIGGER_KEYBINDING_ON_SCROLL) { 103 | this.onScrollReceived(KeyBindingUtils.getLastScrollAmount(), true, 0); 104 | } 105 | return false; 106 | } 107 | 108 | @Inject(method = "onMouseScroll", at = @At(value = "FIELD", target = "Lnet/minecraft/client/MinecraftClient;currentScreen:Lnet/minecraft/client/gui/screen/Screen;", ordinal = 0), locals = LocalCapture.CAPTURE_FAILHARD, cancellable = true) 109 | private void onMouseScroll(long window, double rawX, double rawY, CallbackInfo callbackInfo, double offset, double deltaY) { 110 | InputUtil.Key keyCode = KeyBindingUtils.getKeyFromScroll(deltaY); 111 | 112 | // check if we have scroll input for the options screen 113 | if (client.currentScreen instanceof KeybindsScreen) { 114 | KeyBinding focusedBinding = ((KeybindsScreen) client.currentScreen).selectedKeyBinding; 115 | if (focusedBinding != null) { 116 | if (!focusedBinding.isUnbound()) { 117 | focusedBinding.setKeyModifierAndCode(KeyModifier.fromKey(focusedBinding.getKey()).toForgeKeyModifier(), focusedBinding.getKey()); 118 | } 119 | // This is a bit hacky, but the easiest way out 120 | // If the selected binding != null, the mouse x and y will always be ignored - so no need to convert them 121 | // The key code that InputUtil.MOUSE.createFromCode chooses is always one bigger than the input 122 | client.currentScreen.mouseClicked(-1, -1, keyCode.getCode()); 123 | // if we do we cancel the method because we do not want the current screen to get the scroll event 124 | callbackInfo.cancel(); 125 | return; 126 | } 127 | } 128 | 129 | KeyBindingUtils.setLastScrollAmount(deltaY); 130 | } 131 | } 132 | --------------------------------------------------------------------------------