diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..a4c8fa1 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,6 @@ +[*] +end_of_line = lf + +[{*.json,*.toml}] +indent_style = tab +indent_size = 4 \ No newline at end of file diff --git a/.gitignore b/.gitignore index 823aca8..c476faf 100644 --- a/.gitignore +++ b/.gitignore @@ -1,9 +1,13 @@ # gradle .gradle/ +build/ out/ classes/ -build/ + +# eclipse + +*.launch # idea @@ -20,6 +24,17 @@ bin/ .classpath .project +# macos + +*.DS_Store + # fabric -run/ \ No newline at end of file +run/ + +# java + +hs_err_*.log +replay_*.log +*.hprof +*.jfr diff --git a/README.md b/README.md index e47b6c6..405e0e8 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,3 @@ # Sword Blocking -A minecraft fabric clientside mod to restore sword blocking, you just need a shield in your offhand. +A minecraft fabric clientside mod to restore sword blocking, you just need a shield in your offhand. Works especially well if you want to use 1.16 on an 1.8 server which is running ViaVersion. diff --git a/build.gradle b/build.gradle deleted file mode 100644 index b9c6de2..0000000 --- a/build.gradle +++ /dev/null @@ -1,80 +0,0 @@ -plugins { - id "architectury-plugin" version "3.4-SNAPSHOT" - id "dev.architectury.loom" version "1.10-SNAPSHOT" apply false - id "me.shedaniel.unified-publishing" version "0.1.+" apply false - id 'com.github.johnrengelman.shadow' version '8.1.1' apply false -} - -architectury { - minecraft = rootProject.minecraft_version -} - -repositories { - maven { - url = "https://api.modrinth.com/maven" - } -} - -subprojects { - apply plugin: "dev.architectury.loom" - repositories { - maven { - url = "https://api.modrinth.com/maven" - } - maven { url 'https://jitpack.io' } - } - - dependencies { - minecraft "com.mojang:minecraft:${rootProject.minecraft_version}" - // The following line declares the mojmap mappings, you may use other mappings as well - //mappings loom.officialMojangMappings() - // The following line declares the yarn mappings you may select this one as well. - mappings loom.layered { - it.mappings("net.fabricmc:yarn:$rootProject.yarn_mappings:v2") - it.mappings("dev.architectury:yarn-mappings-patch-neoforge:$rootProject.yarn_mappings_patch_neoforge_version") - } - } -} - - -allprojects { - apply plugin: "java" - apply plugin: "architectury-plugin" - apply plugin: "maven-publish" - - archivesBaseName = rootProject.archives_base_name - version = rootProject.mod_version - group = rootProject.maven_group - - repositories { - // Add repositories to retrieve artifacts from in here. - // You should only use this when depending on other mods because - // Loom adds the essential maven repositories to download Minecraft and libraries from automatically. - // See https://docs.gradle.org/current/userguide/declaring_repositories.html - // for more information about repositories. - } - - tasks.withType(JavaCompile) { - options.encoding = "UTF-8" - options.release = 21 - } - ext { - releaseChangelog = { - def changes = new StringBuilder() - changes << "## SwordBlocking v$project.version for $project.minecraft_version\n[View the changelog](https://www.github.com/TeamMidnightDust/SwordBlocking/commits/)" - def proc = "git log --max-count=1 --pretty=format:%s".execute() - proc.in.eachLine { line -> - def processedLine = line.toString() - if (!processedLine.contains("New translations") && !processedLine.contains("Merge") && !processedLine.contains("branch")) { - changes << "\n- ${processedLine.capitalize()}" - } - } - proc.waitFor() - return changes.toString() - } - } - - java { - withSourcesJar() - } -} \ No newline at end of file diff --git a/build.gradle.kts b/build.gradle.kts new file mode 100644 index 0000000..fc609b1 --- /dev/null +++ b/build.gradle.kts @@ -0,0 +1,226 @@ +plugins { + alias(libs.plugins.kotlin.jvm) + alias(libs.plugins.loom) + alias(libs.plugins.publishing) + alias(libs.plugins.blossom) + alias(libs.plugins.ksp) + alias(libs.plugins.fletchingtable.fabric) +} + +repositories { + maven("https://pkgs.dev.azure.com/djtheredstoner/DevAuth/_packaging/public/maven/v1") // DevAuth + maven("https://maven.parchmentmc.org") // Parchment + maven("https://maven.neoforged.net/releases") // NeoForge + maven("https://maven.bawnorton.com/releases") // MixinSquared + maven("https://maven.terraformersmc.com/") // Mod Menu + maven("https://api.modrinth.com/maven") // MidnightLib +} + +class ModData { + val id = property("mod.id") as String + val name = property("mod.name") as String + val version = property("mod.version") as String + val group = property("mod.group") as String + val description = property("mod.description") as String + val source = property("mod.source") as String + val issues = property("mod.issues") as String + val license = property("mod.license") as String + val modrinth = property("mod.modrinth") as String + val curseforge = property("mod.curseforge") as String + val discord = property("mod.discord") as String + + val minecraftVersion = property("mod.minecraft_version") as String + val minecraftVersionRange = property("mod.minecraft_version_range") as String +} + +class Dependencies { + val fabricLoaderVersion = property("deps.fabric_loader_version") as String? + val midnightLibVersion = property("deps.midnightlib_version") as String? + + val devAuthVersion = property("deps.devauth_version") as String? + val lombokVersion = property("deps.lombok_version") as String? + val mixinConstraintsVersion = property("deps.mixinconstraints_version") as String? + val mixinSquaredVersion = property("deps.mixinsquared_version") as String? + + // Versioned + val neoForgeVersion = property("deps.neoforge_version") as String? + val fabricApiVersion = property("deps.fabric_api_version") as String? +} + +class LoaderData { + val name = loom.platform.get().name.lowercase() + val isFabric = name == "fabric" + val isNeoForge = name == "neoforge" +} + +val mod = ModData() +val deps = Dependencies() +val loader = LoaderData() + +group = mod.group +base { + archivesName.set("${mod.id}-${mod.version}+${mod.minecraftVersion}-${loader.name}") +} + +java { + val requiredJava = when { + stonecutter.eval(stonecutter.current.version, ">=1.20.6") -> JavaVersion.VERSION_21 + stonecutter.eval(stonecutter.current.version, ">=1.18") -> JavaVersion.VERSION_17 + stonecutter.eval(stonecutter.current.version, ">=1.17") -> JavaVersion.VERSION_16 + else -> JavaVersion.VERSION_1_8 + } + + sourceCompatibility = requiredJava + targetCompatibility = requiredJava +} + +stonecutter { + replacements.string { + direction = eval(current.version, ">=1.21.11") + replace("ResourceLocation", "Identifier") + } +} + +val currentCommitHash: String by lazy { + Runtime.getRuntime() + .exec("git rev-parse --verify --short HEAD", null, rootDir) + .inputStream.bufferedReader().readText().trim() +} + +blossom { + replaceToken("@MODID@", mod.id) + replaceToken("@VERSION@", mod.version) + replaceToken("@COMMIT@", currentCommitHash) +} + +loom { + silentMojangMappingsLicense() + runConfigs.all { + ideConfigGenerated(stonecutter.current.isActive) + runDir = "../../run" + } + + runConfigs.remove(runConfigs["server"]) // Removes server run configs +} + +loom.runs { + afterEvaluate { + val mixinJarFile = configurations.runtimeClasspath.get().incoming.artifactView { + componentFilter { + it is ModuleComponentIdentifier && it.group == "net.fabricmc" && it.module == "sponge-mixin" + } + }.files.first() + configureEach { + vmArg("-javaagent:$mixinJarFile") + property("mixin.hotSwap", "true") + property("mixin.debug.export", "true") // Puts mixin outputs in /run/.mixin.out + property("devauth.enabled", "true") + property("devauth.account", "main") + } + } +} + +fletchingTable { + mixins.create("main") { + mixin("default", "${mod.id}.mixins.json") + } + + lang.create("main") { + patterns.add("assets/${mod.id}/lang/**") + } +} + +dependencies { + minecraft("com.mojang:minecraft:${mod.minecraftVersion}") + + @Suppress("UnstableApiUsage") + mappings(loom.layered { + officialMojangMappings() + + // Parchment mappings (it adds parameter mappings & javadoc) + optionalProp("deps.parchment_version") { + parchment("org.parchmentmc.data:parchment-${mod.minecraftVersion}:$it@zip") + } + }) + + modImplementation("maven.modrinth:midnightlib:${deps.midnightLibVersion}+${mod.minecraftVersion}-${loader.name}") + + compileOnly("org.projectlombok:lombok:${deps.lombokVersion}") + annotationProcessor("org.projectlombok:lombok:${deps.lombokVersion}") + modRuntimeOnly("me.djtheredstoner:DevAuth-${loader.name}:${deps.devAuthVersion}") + + include(implementation("com.moulberry:mixinconstraints:${deps.mixinConstraintsVersion}")!!)!! + include(implementation(annotationProcessor("com.github.bawnorton.mixinsquared:mixinsquared-${loader.name}:${deps.mixinSquaredVersion}")!!)!!) + if (loader.isFabric) { + modImplementation("net.fabricmc:fabric-loader:${deps.fabricLoaderVersion}")!! + modImplementation("net.fabricmc.fabric-api:fabric-api:${deps.fabricApiVersion}") + optionalProp("deps.modmenu_version") { prop -> + modImplementation("com.terraformersmc:modmenu:$prop") { + exclude(group, "net.fabricmc.fabric-api") + } + } + } else if (loader.isNeoForge) { + "neoForge"("net.neoforged:neoforge:${deps.neoForgeVersion}") + } +} + +publishMods { +} + +tasks { + processResources { + val props = buildMap { + put("id", mod.id) + put("name", mod.name) + put("version", mod.version) + put("description", mod.description) + put("source", mod.source) + put("issues", mod.issues) + put("license", mod.license) + put("modrinth", mod.modrinth) + put("curseforge", mod.curseforge) + put("discord", mod.discord) + put("minecraft_version_range", mod.minecraftVersionRange) + if (loader.isFabric) { + put("fabric_api_version", deps.fabricApiVersion?.trim()) + put("fabric_loader_version", deps.fabricLoaderVersion?.trim()) + } else if (loader.isNeoForge) { + put("neoforge_version", deps.neoForgeVersion?.trim()) + } + } + + props.forEach(inputs::property) + filesMatching("**/lang/en_us.json") { // Defaults description to English translation + expand(props) + filteringCharset = "UTF-8" + } + + if (loader.isFabric) { + filesMatching("fabric.mod.json") { expand(props) } + exclude(listOf("META-INF/neoforge.mods.toml")) + } + + if (loader.isNeoForge) { + filesMatching("META-INF/neoforge.mods.toml") { expand(props) } + exclude(listOf("fabric.mod.json")) + } + } + + // Builds the version into a shared folder in `build/libs/${mod version}/` + register("buildAndCollect") { + group = "build" + from(remapJar.map { it.archiveFile }, remapSourcesJar.map { it.archiveFile }) + into(rootProject.layout.buildDirectory.file("libs/${project.property("mod.version")}")) + dependsOn("build") + } +} + +if (stonecutter.current.isActive) { + rootProject.tasks.register("buildActive") { + group = "project" + dependsOn(tasks.named("build")) + } +} + +fun optionalProp(property: String, block: (String) -> T?): T? = + findProperty(property)?.toString()?.takeUnless { it.isBlank() }?.let(block) \ No newline at end of file diff --git a/common/build.gradle b/common/build.gradle deleted file mode 100644 index 8852913..0000000 --- a/common/build.gradle +++ /dev/null @@ -1,24 +0,0 @@ -architectury { - common(rootProject.enabled_platforms.split(",")) -} - -dependencies { - // We depend on fabric loader here to use the fabric @Environment annotations and get the mixin dependencies - // Do NOT use other classes from fabric loader - modImplementation "net.fabricmc:fabric-loader:${rootProject.fabric_loader_version}" - modCompileOnlyApi "maven.modrinth:midnightlib:${rootProject.midnightlib_version}-fabric" -} - -publishing { - publications { - mavenCommon(MavenPublication) { - artifactId = rootProject.archives_base_name - from components.java - } - } - - // See https://docs.gradle.org/current/userguide/publishing_maven.html for information on how to set up publishing. - repositories { - // Add repositories to publish to here. - } -} diff --git a/common/src/main/java/eu/midnightdust/swordblocking/SwordBlockingClient.java b/common/src/main/java/eu/midnightdust/swordblocking/SwordBlockingClient.java deleted file mode 100644 index a70678f..0000000 --- a/common/src/main/java/eu/midnightdust/swordblocking/SwordBlockingClient.java +++ /dev/null @@ -1,37 +0,0 @@ -package eu.midnightdust.swordblocking; - -import eu.midnightdust.swordblocking.config.SwordBlockingConfig; -import net.minecraft.client.render.entity.state.BipedEntityRenderState; -import net.minecraft.component.DataComponentTypes; -import net.minecraft.entity.LivingEntity; -import net.minecraft.item.*; - -import java.util.HashMap; -import java.util.Map; - -public class SwordBlockingClient { - public static final String MOD_ID = "swordblocking"; - public static Map RENDER_STATE_TO_ENTITY_MAP = new HashMap<>(); - - public static void init() { - SwordBlockingConfig.init(MOD_ID, SwordBlockingConfig.class); - } - - public static boolean isEntityBlocking(LivingEntity entity) { - return SwordBlockingConfig.enabled && entity.isUsingItem() && canShieldSwordBlock(entity); - } - - public static boolean canShieldSwordBlock(LivingEntity entity) { - if (SwordBlockingConfig.enabled && (entity.getOffHandStack().getItem() instanceof ShieldItem || entity.getMainHandStack().getItem() instanceof ShieldItem)) { - Item weaponItem = entity.getOffHandStack().getItem() instanceof ShieldItem ? entity.getMainHandStack().getItem() : entity.getOffHandStack().getItem(); - return weaponItem.getComponents().contains(DataComponentTypes.DAMAGE); - } else { - return false; - } - } - - public static boolean shouldHideShield(LivingEntity entity, ItemStack stack) { - return SwordBlockingConfig.enabled && (SwordBlockingConfig.alwaysHideShield && SwordBlockingConfig.hideShield && stack.getItem() instanceof ShieldItem) - || (SwordBlockingConfig.hideShield && stack.getItem() instanceof ShieldItem && SwordBlockingClient.canShieldSwordBlock(entity)); - } -} diff --git a/common/src/main/java/eu/midnightdust/swordblocking/config/SwordBlockingConfig.java b/common/src/main/java/eu/midnightdust/swordblocking/config/SwordBlockingConfig.java deleted file mode 100644 index 6a0b128..0000000 --- a/common/src/main/java/eu/midnightdust/swordblocking/config/SwordBlockingConfig.java +++ /dev/null @@ -1,13 +0,0 @@ -package eu.midnightdust.swordblocking.config; - -import eu.midnightdust.lib.config.MidnightConfig; - -public class SwordBlockingConfig extends MidnightConfig { - @Entry public static boolean enabled = true; - @Entry public static boolean hideShield = true; - @Entry public static boolean alwaysHideShield = true; - @Entry public static boolean hideOffhandSlot = false; - @Entry public static boolean disableUseEquipAnimation = false; - @Entry public static boolean lockBlockingArmPosition = false; - @Entry public static boolean blockHitAnimation = false; -} diff --git a/common/src/main/java/eu/midnightdust/swordblocking/mixin/MixinBipedEntityModel.java b/common/src/main/java/eu/midnightdust/swordblocking/mixin/MixinBipedEntityModel.java deleted file mode 100644 index aa60de0..0000000 --- a/common/src/main/java/eu/midnightdust/swordblocking/mixin/MixinBipedEntityModel.java +++ /dev/null @@ -1,43 +0,0 @@ -package eu.midnightdust.swordblocking.mixin; - -import eu.midnightdust.swordblocking.SwordBlockingClient; -import eu.midnightdust.swordblocking.config.SwordBlockingConfig; -import net.minecraft.client.render.entity.model.BipedEntityModel; -import net.minecraft.client.render.entity.state.BipedEntityRenderState; -import net.minecraft.entity.LivingEntity; -import net.minecraft.item.ShieldItem; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.Redirect; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; - -@Mixin(BipedEntityModel.class) -public abstract class MixinBipedEntityModel { - @Shadow - protected abstract void positionRightArm(T entityRenderState, BipedEntityModel.ArmPose armPose); - - @Shadow - protected abstract void positionLeftArm(T entityRenderState, BipedEntityModel.ArmPose armPose); - - @Inject(method = "setAngles(Lnet/minecraft/client/render/entity/state/BipedEntityRenderState;)V", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/render/entity/model/BipedEntityModel;animateArms(Lnet/minecraft/client/render/entity/state/BipedEntityRenderState;F)V", shift = At.Shift.BEFORE)) - private void swordBlocking$setBlockingAngles(T bipedEntityRenderState, CallbackInfo ci) { - LivingEntity livingEntity = SwordBlockingClient.RENDER_STATE_TO_ENTITY_MAP.get(bipedEntityRenderState); - if (livingEntity == null || !SwordBlockingClient.isEntityBlocking(livingEntity)) - return; - if (livingEntity.getOffHandStack().getItem() instanceof ShieldItem) - this.positionRightArm(bipedEntityRenderState, BipedEntityModel.ArmPose.BLOCK); - else - this.positionLeftArm(bipedEntityRenderState, BipedEntityModel.ArmPose.BLOCK); - } - - @Redirect(method = "positionBlockingArm", at = @At(value = "INVOKE", target = "Lnet/minecraft/util/math/MathHelper;clamp(FFF)F")) - private float swordBlocking$lockArmPosition(float value, float min, float max) { - if (SwordBlockingConfig.enabled && SwordBlockingConfig.lockBlockingArmPosition) { - return 0F; - } else { - return value; - } - } -} diff --git a/common/src/main/java/eu/midnightdust/swordblocking/mixin/MixinBipedEntityRenderer.java b/common/src/main/java/eu/midnightdust/swordblocking/mixin/MixinBipedEntityRenderer.java deleted file mode 100644 index 2972bc3..0000000 --- a/common/src/main/java/eu/midnightdust/swordblocking/mixin/MixinBipedEntityRenderer.java +++ /dev/null @@ -1,21 +0,0 @@ -package eu.midnightdust.swordblocking.mixin; - -import eu.midnightdust.swordblocking.SwordBlockingClient; -import net.minecraft.client.item.ItemModelManager; -import net.minecraft.client.render.entity.BipedEntityRenderer; -import net.minecraft.client.render.entity.model.BipedEntityModel; -import net.minecraft.client.render.entity.state.BipedEntityRenderState; -import net.minecraft.entity.LivingEntity; -import net.minecraft.entity.mob.MobEntity; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; - -@Mixin(BipedEntityRenderer.class) -public abstract class MixinBipedEntityRenderer> { - @Inject(method = "updateBipedRenderState", at = @At("TAIL")) - private static void swordBlocking$storeEntity(LivingEntity entity, BipedEntityRenderState state, float tickDelta, ItemModelManager itemModelResolver, CallbackInfo ci) { - SwordBlockingClient.RENDER_STATE_TO_ENTITY_MAP.put(state, entity); - } -} diff --git a/common/src/main/java/eu/midnightdust/swordblocking/mixin/MixinHeldItemFeatureRenderer.java b/common/src/main/java/eu/midnightdust/swordblocking/mixin/MixinHeldItemFeatureRenderer.java deleted file mode 100644 index d97bf0c..0000000 --- a/common/src/main/java/eu/midnightdust/swordblocking/mixin/MixinHeldItemFeatureRenderer.java +++ /dev/null @@ -1,31 +0,0 @@ -package eu.midnightdust.swordblocking.mixin; - -import com.llamalad7.mixinextras.sugar.Local; -import eu.midnightdust.swordblocking.SwordBlockingClient; -import eu.midnightdust.swordblocking.config.SwordBlockingConfig; -import net.minecraft.client.render.entity.feature.HeldItemFeatureRenderer; -import net.minecraft.client.render.entity.model.EntityModel; -import net.minecraft.client.render.entity.model.ModelWithArms; -import net.minecraft.client.render.entity.state.ArmedEntityRenderState; -import net.minecraft.client.render.item.ItemRenderState; -import net.minecraft.entity.LivingEntity; -import net.minecraft.item.ItemStack; -import net.minecraft.util.Arm; -import net.minecraft.util.Hand; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Redirect; - -@Mixin(HeldItemFeatureRenderer.class) -public abstract class MixinHeldItemFeatureRenderer & ModelWithArms> { - @Redirect(method = "renderItem", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/render/item/ItemRenderState;isEmpty()Z")) - private boolean swordBlocking$hideShield(ItemRenderState instance, @Local(argsOnly = true) Arm arm, @Local(argsOnly = true) S entityState) { - LivingEntity livingEntity = SwordBlockingClient.RENDER_STATE_TO_ENTITY_MAP.get(entityState); - if (SwordBlockingConfig.enabled && livingEntity != null) { - ItemStack itemStack = livingEntity.getStackInHand(arm == Arm.LEFT ? Hand.OFF_HAND : Hand.MAIN_HAND); - return SwordBlockingClient.shouldHideShield(livingEntity, itemStack); - } - - return instance.isEmpty(); - } -} diff --git a/common/src/main/java/eu/midnightdust/swordblocking/mixin/MixinHeldItemRenderer.java b/common/src/main/java/eu/midnightdust/swordblocking/mixin/MixinHeldItemRenderer.java deleted file mode 100644 index 5a032fa..0000000 --- a/common/src/main/java/eu/midnightdust/swordblocking/mixin/MixinHeldItemRenderer.java +++ /dev/null @@ -1,80 +0,0 @@ -package eu.midnightdust.swordblocking.mixin; - -import com.llamalad7.mixinextras.sugar.Local; -import eu.midnightdust.swordblocking.SwordBlockingClient; -import eu.midnightdust.swordblocking.config.SwordBlockingConfig; -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.network.AbstractClientPlayerEntity; -import net.minecraft.client.render.VertexConsumerProvider; -import net.minecraft.client.render.item.HeldItemRenderer; -import net.minecraft.client.util.math.MatrixStack; -import net.minecraft.entity.LivingEntity; -import net.minecraft.item.ItemDisplayContext; -import net.minecraft.item.ItemStack; -import net.minecraft.item.consume.UseAction; -import net.minecraft.util.Arm; -import net.minecraft.util.Hand; -import org.spongepowered.asm.mixin.Final; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.asm.mixin.Unique; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.Redirect; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; - -@Mixin(HeldItemRenderer.class) -public abstract class MixinHeldItemRenderer { - @Shadow - @Final - private MinecraftClient client; - - @Shadow - protected abstract void applySwingOffset(MatrixStack matrices, Arm arm, float swingProgress); - - @Inject(method = "renderItem(Lnet/minecraft/entity/LivingEntity;Lnet/minecraft/item/ItemStack;Lnet/minecraft/item/ItemDisplayContext;Lnet/minecraft/client/util/math/MatrixStack;Lnet/minecraft/client/render/VertexConsumerProvider;I)V", at = @At("HEAD"), cancellable = true) - public void swordBlocking$hideShield(LivingEntity entity, ItemStack stack, ItemDisplayContext renderMode, MatrixStack matrices, VertexConsumerProvider vertexConsumer, int light, CallbackInfo ci) { - if (SwordBlockingClient.shouldHideShield(entity, stack)) { - ci.cancel(); - } - } - - @Redirect(method = "renderFirstPersonItem", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/network/AbstractClientPlayerEntity;getActiveHand()Lnet/minecraft/util/Hand;", ordinal = 1)) - private Hand swordBlocking$changeActiveHand(AbstractClientPlayerEntity player) { - Hand activeHand = player.getActiveHand(); - if (SwordBlockingClient.isEntityBlocking(player)) { - return swordBlocking$getBlockingHand(activeHand); - } else { - return activeHand; - } - } - - @Redirect(method = "renderFirstPersonItem", at = @At(value = "INVOKE", target = "Lnet/minecraft/item/ItemStack;getUseAction()Lnet/minecraft/item/consume/UseAction;")) - private UseAction swordBlocking$changeItemAction(ItemStack stack, @Local(argsOnly = true) AbstractClientPlayerEntity player, @Local(argsOnly = true) Hand hand) { - UseAction defaultUseAction = stack.getUseAction(); - if (SwordBlockingClient.isEntityBlocking(player)) { - return swordBlocking$getBlockingHand(player.getActiveHand()) == hand ? UseAction.BLOCK : defaultUseAction; - } else { - return defaultUseAction; - } - } - - @Inject(method = "renderFirstPersonItem", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/render/item/HeldItemRenderer;applyEquipOffset(Lnet/minecraft/client/util/math/MatrixStack;Lnet/minecraft/util/Arm;F)V", ordinal = 3, shift = At.Shift.AFTER)) - private void swordBlocking$applySwingOffset(AbstractClientPlayerEntity player, float tickDelta, float pitch, Hand hand, float swingProgress, ItemStack item, float equipProgress, MatrixStack matrices, VertexConsumerProvider vertexConsumers, int light, CallbackInfo ci, @Local Arm arm) { - if (SwordBlockingConfig.enabled && SwordBlockingConfig.blockHitAnimation) { - applySwingOffset(matrices, arm, swingProgress); - } - } - - @Inject(method = "resetEquipProgress", at = @At("HEAD"), cancellable = true) - private void swordBlocking$disableEquipAnimation(Hand hand, CallbackInfo ci) { - if (SwordBlockingConfig.disableUseEquipAnimation && this.client.player != null && this.client.player.isUsingItem()) { - ci.cancel(); - } - } - - @Unique - private Hand swordBlocking$getBlockingHand(Hand activeHand) { - return activeHand == Hand.MAIN_HAND ? Hand.OFF_HAND : Hand.MAIN_HAND; - } -} diff --git a/common/src/main/java/eu/midnightdust/swordblocking/mixin/MixinPlayerEntityRenderer.java b/common/src/main/java/eu/midnightdust/swordblocking/mixin/MixinPlayerEntityRenderer.java deleted file mode 100644 index 62997cb..0000000 --- a/common/src/main/java/eu/midnightdust/swordblocking/mixin/MixinPlayerEntityRenderer.java +++ /dev/null @@ -1,35 +0,0 @@ -package eu.midnightdust.swordblocking.mixin; - -import eu.midnightdust.swordblocking.SwordBlockingClient; -import eu.midnightdust.swordblocking.config.SwordBlockingConfig; -import net.fabricmc.api.EnvType; -import net.fabricmc.api.Environment; -import net.minecraft.client.render.entity.PlayerEntityRenderer; -import net.minecraft.client.render.entity.model.BipedEntityModel; -import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.item.ItemStack; -import net.minecraft.item.ShieldItem; -import net.minecraft.util.Hand; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; - -@Mixin(PlayerEntityRenderer.class) -public abstract class MixinPlayerEntityRenderer { - @Environment(EnvType.CLIENT) - @Inject(method = "getArmPose(Lnet/minecraft/entity/player/PlayerEntity;Lnet/minecraft/item/ItemStack;Lnet/minecraft/util/Hand;)Lnet/minecraft/client/render/entity/model/BipedEntityModel$ArmPose;", at = @At(value = "RETURN"), cancellable = true) - private static void swordBlocking$getArmPose(PlayerEntity player, ItemStack stack, Hand hand, CallbackInfoReturnable cir) { - if (SwordBlockingConfig.enabled) { - ItemStack handStack = player.getStackInHand(hand); - ItemStack offStack = player.getStackInHand(hand.equals(Hand.MAIN_HAND) ? Hand.OFF_HAND : Hand.MAIN_HAND); - if (!SwordBlockingConfig.alwaysHideShield && (handStack.getItem() instanceof ShieldItem) && !SwordBlockingClient.canShieldSwordBlock(player)) - return; - if (offStack.getItem() instanceof ShieldItem && SwordBlockingClient.isEntityBlocking(player)) { - cir.setReturnValue(BipedEntityModel.ArmPose.BLOCK); - } else if (handStack.getItem() instanceof ShieldItem && SwordBlockingConfig.hideShield && (cir.getReturnValue() == BipedEntityModel.ArmPose.ITEM || cir.getReturnValue() == BipedEntityModel.ArmPose.BLOCK)) { - cir.setReturnValue(BipedEntityModel.ArmPose.EMPTY); - } - } - } -} diff --git a/common/src/main/resources/swordblocking.mixins.json b/common/src/main/resources/swordblocking.mixins.json deleted file mode 100644 index f50d341..0000000 --- a/common/src/main/resources/swordblocking.mixins.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "required": true, - "minVersion": "0.8", - "package": "eu.midnightdust.swordblocking.mixin", - "compatibilityLevel": "JAVA_17", - "client": [ - "MixinBipedEntityModel", - "MixinBipedEntityRenderer", - "MixinHeldItemFeatureRenderer", - "MixinHeldItemRenderer", - "MixinInGameHud", - "MixinPlayerEntityRenderer" - ], - "injectors": { - "defaultRequire": 1 - } -} diff --git a/fabric/build.gradle b/fabric/build.gradle deleted file mode 100644 index 0587754..0000000 --- a/fabric/build.gradle +++ /dev/null @@ -1,102 +0,0 @@ -plugins { - id 'com.github.johnrengelman.shadow' - id "me.shedaniel.unified-publishing" -} - -architectury { - platformSetupLoomIde() - fabric() -} - -loom { -} - -configurations { - common - shadowCommon // Don't use shadow from the shadow plugin since it *excludes* files. - compileClasspath.extendsFrom common - runtimeClasspath.extendsFrom common - developmentFabric.extendsFrom common - archivesBaseName = rootProject.archives_base_name + "-fabric" -} - -dependencies { - modImplementation "net.fabricmc:fabric-loader:${rootProject.fabric_loader_version}" - modApi "net.fabricmc.fabric-api:fabric-api:${rootProject.fabric_api_version}" - modImplementation include ("maven.modrinth:midnightlib:${rootProject.midnightlib_version}-fabric") - - common(project(path: ":common", configuration: "namedElements")) { transitive false } - shadowCommon(project(path: ":common", configuration: "transformProductionFabric")) { transitive false } -} - -processResources { - inputs.property "version", project.version - - filesMatching("fabric.mod.json") { - expand "version": project.version - } -} - -shadowJar { - exclude "architectury.common.json" - - configurations = [project.configurations.shadowCommon] - archiveClassifier = "dev-shadow" -} - -remapJar { - input.set shadowJar.archiveFile - dependsOn shadowJar -} - -sourcesJar { - def commonSources = project(":common").sourcesJar - dependsOn commonSources - from commonSources.archiveFile.map { zipTree(it) } -} - -components.java { - withVariantsFromConfiguration(project.configurations.shadowRuntimeElements) { - skip() - } -} - -unifiedPublishing { - project { - displayName = "SwordBlocking $project.version - Fabric $project.minecraft_version" - releaseType = "$project.release_type" - changelog = releaseChangelog() - gameVersions = [] - gameLoaders = ["fabric","quilt"] - mainPublication remapJar - relations { - depends { - curseforge = "fabric-api" - modrinth = "fabric-api" - } - includes { - curseforge = "midnightlib" - modrinth = "midnightlib" - } - } - - var CURSEFORGE_TOKEN = project.findProperty("CURSEFORGE_TOKEN") ?: System.getenv("CURSEFORGE_TOKEN") - if (CURSEFORGE_TOKEN != null) { - curseforge { - token = CURSEFORGE_TOKEN - id = rootProject.curseforge_id - gameVersions.addAll "Java 21", project.minecraft_version - } - } - - var MODRINTH_TOKEN = project.findProperty("MODRINTH_TOKEN") ?: System.getenv("MODRINTH_TOKEN") - if (MODRINTH_TOKEN != null) { - modrinth { - token = MODRINTH_TOKEN - id = rootProject.modrinth_id - version = "$project.version-$project.name" - gameVersions.addAll project.minecraft_version - } - } - } -} \ No newline at end of file diff --git a/fabric/src/main/java/eu/midnightdust/swordblocking/fabric/SwordBlockingClientFabric.java b/fabric/src/main/java/eu/midnightdust/swordblocking/fabric/SwordBlockingClientFabric.java deleted file mode 100755 index 9fd97c8..0000000 --- a/fabric/src/main/java/eu/midnightdust/swordblocking/fabric/SwordBlockingClientFabric.java +++ /dev/null @@ -1,11 +0,0 @@ -package eu.midnightdust.swordblocking.fabric; - -import eu.midnightdust.swordblocking.SwordBlockingClient; -import net.fabricmc.api.ClientModInitializer; - -public class SwordBlockingClientFabric implements ClientModInitializer { - @Override - public void onInitializeClient() { - SwordBlockingClient.init(); - } -} diff --git a/fabric/src/main/resources/fabric.mod.json b/fabric/src/main/resources/fabric.mod.json deleted file mode 100644 index 145d357..0000000 --- a/fabric/src/main/resources/fabric.mod.json +++ /dev/null @@ -1,32 +0,0 @@ -{ - "schemaVersion": 1, - "id": "swordblocking", - "version": "${version}", - "name": "Sword Blocking", - "description": "Adds sword blocking to new versions, you just need a shield in your offhand (or ViaVersion)!", - "authors": [ - "Motschen", - "TeamMidnightDust", - "lowercasebtw" - ], - "contact": { - "homepage": "https://www.midnightdust.eu/", - "sources": "https://github.com/TeamMidnightDust/SwordBlocking", - "issues": "https://github.com/TeamMidnightDust/SwordBlocking/issues" - }, - "license": "MIT", - "icon": "assets/swordblocking/icon.png", - "environment": "client", - "entrypoints": { - "client": [ - "eu.midnightdust.swordblocking.fabric.SwordBlockingClientFabric" - ] - }, - "mixins": [ - "swordblocking.mixins.json" - ], - "depends": { - "fabric-api": "*", - "midnightlib": "*" - } -} diff --git a/gradle.properties b/gradle.properties index 17d155e..bc545c4 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,24 +1,44 @@ -org.gradle.jvmargs=-Xmx3G +# Done to increase the memory available to Gradle. +org.gradle.jvmargs=-Xmx4G org.gradle.parallel=true -# Game Version -minecraft_version=1.21.6 -yarn_mappings=1.21.6+build.1 -yarn_mappings_patch_neoforge_version=1.21+build.4 -enabled_platforms=fabric,neoforge +# IntelliJ IDEA is not yet fully compatible with configuration cache, see: https://github.com/FabricMC/fabric-loom/issues/1349 +org.gradle.configuration-cache=false + +# Mod properties +mod.name=SwordBlocking +mod.id=swordblocking +mod.version=1.0 +mod.group=eu.midnightdust.swordblocking +mod.description=Adds sword blocking to new versions, you just need a shield in your offhand (or ViaVersion)! +mod.source=https://github.com/TeamMidnightDust/SwordBlocking +mod.issues=https://github.com/TeamMidnightDust/SwordBlocking/issues +mod.license=MIT +mod.modrinth=https://modrinth.com/mod/sword-blocking +mod.curseforge=http://curseforge.com/minecraft/mc-mods/sword-blocking +mod.discord=https://discord.gg/jAGnWYHm3r + +# Publishing +publish.modrinth= +publish.curseforge= # Dependencies -midnightlib_version=1.7.5+1.21.6 +deps.fabric_loader_version=0.17.3 +deps.midnightlib_version=1.9.1 -fabric_loader_version=0.16.14 -fabric_api_version=0.127.1+1.21.6 +deps.devauth_version=1.2.1 +deps.lombok_version=1.18.42 +deps.mixinconstraints_version=1.1.0 +deps.mixinsquared_version=0.2.0 -neoforge_version=21.6.0-beta +# Build Plugins +# in libs.versions.toml -# Information -archives_base_name=swordblocking -mod_version=2.2.2 -maven_group=eu.midnightdust -release_type=release -curseforge_id=427738 -modrinth_id=4q52b4lD \ No newline at end of file +# Minecraft properties +mod.mc_dep=[VERSIONED] +mod.mc_version=[VERSIONED] + +# Versioned +deps.parchment_version=[VERSIONED] +deps.fabric_api_version=[VERSIONED] +deps.neoforge_version=[VERSIONED] diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml new file mode 100644 index 0000000..e8a3204 --- /dev/null +++ b/gradle/libs.versions.toml @@ -0,0 +1,16 @@ +[versions] +kotlin-jvm = "2.2.0" +loom = "1.13-SNAPSHOT" +publishing = "0.8.4" +blossom = "1.3.2" +ksp = "2.2.0-2.0.2" +fletchingtable = "0.1.0-alpha.13" + +[plugins] +kotlin-jvm = { id = "org.jetbrains.kotlin.jvm", version.ref = "kotlin-jvm" } +loom = { id = "dev.architectury.loom", version.ref = "loom" } +publishing = { id = "me.modmuss50.mod-publish-plugin", version.ref = "publishing" } +blossom = { id = "net.kyori.blossom", version.ref = "blossom" } +ksp = { id = "com.google.devtools.ksp", version.ref = "ksp" } +fletchingtable-fabric = { id = "dev.kikugie.fletching-table.fabric", version.ref = "fletchingtable" } +fletchingtable-neoforge = { id = "dev.kikugie.fletching-table.neoforge", version.ref = "fletchingtable" } \ No newline at end of file diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index d64cd49..a4b76b9 100644 Binary files a/gradle/wrapper/gradle-wrapper.jar and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index ff23a68..2a84e18 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.2-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-9.0.0-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/gradlew b/gradlew index 1aa94a4..2225efb 100755 --- a/gradlew +++ b/gradlew @@ -1,7 +1,7 @@ #!/bin/sh # -# Copyright © 2015-2021 the original authors. +# Copyright © 2015 the original authors. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/gradlew.bat b/gradlew.bat index 7101f8e..6689b85 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -43,11 +43,11 @@ set JAVA_EXE=java.exe %JAVA_EXE% -version >NUL 2>&1 if %ERRORLEVEL% equ 0 goto execute -echo. 1>&2 -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 -echo. 1>&2 -echo Please set the JAVA_HOME variable in your environment to match the 1>&2 -echo location of your Java installation. 1>&2 +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. goto fail @@ -57,11 +57,11 @@ set JAVA_EXE=%JAVA_HOME%/bin/java.exe if exist "%JAVA_EXE%" goto execute -echo. 1>&2 -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 -echo. 1>&2 -echo Please set the JAVA_HOME variable in your environment to match the 1>&2 -echo location of your Java installation. 1>&2 +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. goto fail diff --git a/neoforge/build.gradle b/neoforge/build.gradle deleted file mode 100644 index 9974ade..0000000 --- a/neoforge/build.gradle +++ /dev/null @@ -1,111 +0,0 @@ -plugins { - id 'com.github.johnrengelman.shadow' - id "me.shedaniel.unified-publishing" -} - -repositories { - maven { - name = 'NeoForged' - url = 'https://maven.neoforged.net/releases' - } -} - -architectury { - platformSetupLoomIde() - neoForge() -} - -loom { - accessWidenerPath = project(":common").loom.accessWidenerPath -} - -configurations { - common { - canBeResolved = true - canBeConsumed = false - } - compileClasspath.extendsFrom common - runtimeClasspath.extendsFrom common - developmentNeoForge.extendsFrom common - - // Files in this configuration will be bundled into your mod using the Shadow plugin. - // Don't use the `shadow` configuration from the plugin itself as it's meant for excluding files. - shadowBundle { - canBeResolved = true - canBeConsumed = false - } - archivesBaseName = rootProject.archives_base_name + "-neoforge" -} - -dependencies { - neoForge "net.neoforged:neoforge:$rootProject.neoforge_version" - modImplementation include ("maven.modrinth:midnightlib:${rootProject.midnightlib_version}-neoforge") - - common(project(path: ':common', configuration: 'namedElements')) { transitive false } - shadowBundle project(path: ':common', configuration: 'transformProductionNeoForge') -} - -processResources { - inputs.property 'version', project.version - - filesMatching('META-INF/neoforge.mods.toml') { - expand version: project.version - } -} - -shadowJar { - configurations = [project.configurations.shadowBundle] - archiveClassifier = 'dev-shadow' -} - -remapJar { - input.set shadowJar.archiveFile -} - -sourcesJar { - def commonSources = project(":common").sourcesJar - dependsOn commonSources - from commonSources.archiveFile.map { zipTree(it) } -} - -components.java { - withVariantsFromConfiguration(project.configurations.shadowRuntimeElements) { - skip() - } -} - -unifiedPublishing { - project { - displayName = "SwordBlocking $project.version - NeoForge $project.minecraft_version" - releaseType = "$project.release_type" - changelog = releaseChangelog() - gameVersions = [] - gameLoaders = ["neoforge"] - mainPublication remapJar - relations { - includes { - curseforge = "midnightlib" - modrinth = "midnightlib" - } - } - - var CURSEFORGE_TOKEN = project.findProperty("CURSEFORGE_TOKEN") ?: System.getenv("CURSEFORGE_TOKEN") - if (CURSEFORGE_TOKEN != null) { - curseforge { - token = CURSEFORGE_TOKEN - id = rootProject.curseforge_id - gameVersions.addAll "Java 21", project.minecraft_version - } - } - - var MODRINTH_TOKEN = project.findProperty("MODRINTH_TOKEN") ?: System.getenv("MODRINTH_TOKEN") - if (MODRINTH_TOKEN != null) { - modrinth { - token = MODRINTH_TOKEN - id = rootProject.modrinth_id - version = "$project.version-$project.name" - gameVersions.addAll project.minecraft_version - } - } - } -} diff --git a/neoforge/gradle.properties b/neoforge/gradle.properties deleted file mode 100644 index 2914393..0000000 --- a/neoforge/gradle.properties +++ /dev/null @@ -1 +0,0 @@ -loom.platform=neoforge \ No newline at end of file diff --git a/neoforge/src/main/java/eu/midnightdust/swordblocking/neoforge/SwordBlockingClientNeoForge.java b/neoforge/src/main/java/eu/midnightdust/swordblocking/neoforge/SwordBlockingClientNeoForge.java deleted file mode 100644 index 61688d2..0000000 --- a/neoforge/src/main/java/eu/midnightdust/swordblocking/neoforge/SwordBlockingClientNeoForge.java +++ /dev/null @@ -1,15 +0,0 @@ -package eu.midnightdust.swordblocking.neoforge; - -import eu.midnightdust.swordblocking.SwordBlockingClient; -import net.neoforged.api.distmarker.Dist; -import net.neoforged.fml.common.Mod; - -import static eu.midnightdust.swordblocking.SwordBlockingClient.MOD_ID; - -@SuppressWarnings("all") -@Mod(value = MOD_ID, dist = Dist.CLIENT) -public class SwordBlockingClientNeoForge { - public SwordBlockingClientNeoForge() { - SwordBlockingClient.init(); - } -} \ No newline at end of file diff --git a/neoforge/src/main/resources/META-INF/neoforge.mods.toml b/neoforge/src/main/resources/META-INF/neoforge.mods.toml deleted file mode 100644 index 21baefd..0000000 --- a/neoforge/src/main/resources/META-INF/neoforge.mods.toml +++ /dev/null @@ -1,38 +0,0 @@ -modLoader = "javafml" -loaderVersion = "[2,)" -#issueTrackerURL = "" -license = "MIT License" - -[[mods]] -modId = "swordblocking" -version = "${version}" -displayName = "Sword Blocking" -logoFile = "icon.png" -authors = "Motschen, TeamMidnightDust, lowercasebtw" -description = ''' -Adds sword blocking to new versions, you just need a shield in your offhand (or ViaVersion)! -''' - -[[mixins]] -config = "swordblocking.mixins.json" - -[[dependencies.visualoverhaul]] -modId = "neoforge" -mandatory = true -versionRange = "[21.0,)" -ordering = "NONE" -side = "BOTH" - -[[dependencies.visualoverhaul]] -modId = "minecraft" -mandatory = true -versionRange = "[1.21,)" -ordering = "NONE" -side = "BOTH" - -[[dependencies.visualoverhaul]] -modId = "picturesign" -mandatory = true -versionRange = "[1.0,)" -ordering = "AFTER" -side = "BOTH" diff --git a/neoforge/src/main/resources/icon.png b/neoforge/src/main/resources/icon.png deleted file mode 100644 index b0fdd2b..0000000 Binary files a/neoforge/src/main/resources/icon.png and /dev/null differ diff --git a/settings.gradle b/settings.gradle deleted file mode 100644 index 2804f9f..0000000 --- a/settings.gradle +++ /dev/null @@ -1,15 +0,0 @@ -pluginManagement { - repositories { - maven { url "https://maven.fabricmc.net/" } - maven { url "https://maven.architectury.dev/" } - maven { url "https://maven.neoforged.net/releases" } - gradlePluginPortal() - } -} - -include("common") -include("fabric") -//include("quilt") -include("neoforge") - -rootProject.name = "swordblocking" diff --git a/settings.gradle.kts b/settings.gradle.kts new file mode 100644 index 0000000..823445a --- /dev/null +++ b/settings.gradle.kts @@ -0,0 +1,39 @@ +pluginManagement { + repositories { + mavenCentral() + gradlePluginPortal() + maven("https://maven.fabricmc.net") + maven("https://maven.architectury.dev") + maven("https://maven.kikugie.dev/snapshots") + maven("https://maven.kikugie.dev/releases") + maven("https://repo.polyfrost.cc/releases") + } +} + +plugins { + id("dev.kikugie.stonecutter") version "0.7.10" +} + +stonecutter { + kotlinController = true + centralScript = "build.gradle.kts" + create(rootProject) { + fun mc(mcVersion: String, loaders: Iterable) { + for (loader in loaders) { + version("$mcVersion-$loader", mcVersion) + } + } + + mc("1.21.8", listOf("fabric", "neoforge")) + + vcsVersion = "1.21.8-fabric" + } +} + +dependencyResolutionManagement { + versionCatalogs { + create("libs") + } +} + +rootProject.name = "SwordBlocking" diff --git a/src/main/java/eu/midnightdust/swordblocking/SwordBlockingClient.java b/src/main/java/eu/midnightdust/swordblocking/SwordBlockingClient.java new file mode 100644 index 0000000..abe461a --- /dev/null +++ b/src/main/java/eu/midnightdust/swordblocking/SwordBlockingClient.java @@ -0,0 +1,66 @@ +package eu.midnightdust.swordblocking; + +import eu.midnightdust.swordblocking.config.SwordBlockingConfig; +import net.minecraft.core.component.DataComponents; +import net.minecraft.world.item.Item; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.ShieldItem; + +//? fabric { +/*import dev.kikugie.fletching_table.annotation.fabric.Entrypoint; +import net.fabricmc.api.ClientModInitializer; +*///?} else { +import net.neoforged.api.distmarker.Dist; +import net.neoforged.fml.common.Mod; +//?} + +//? fabric +/*@Entrypoint*/ +//? neoforge +@Mod(value = SwordBlockingClient.MOD_ID, dist = Dist.CLIENT) +public final class SwordBlockingClient + //? fabric + /*implements ClientModInitializer*/ +{ + public static final String MOD_ID = "@MODID@"; + + // TODO/NOTE: I know this can be condensed more but i'm tired so will recheck later + public static boolean canEntityBlock(ItemStack mainHandStack, ItemStack offHandStack) { + return SwordBlockingConfig.enabled && canShieldSwordBlock(mainHandStack, offHandStack); + } + + // TODO/NOTE: I know this can be condensed more but i'm tired so will recheck later + public static boolean canShieldSwordBlock(ItemStack mainHandStack, ItemStack offHandStack) { + if (SwordBlockingConfig.enabled && (offHandStack.getItem() instanceof ShieldItem || mainHandStack.getItem() instanceof ShieldItem)) { + final Item weaponItem = offHandStack.getItem() instanceof ShieldItem ? mainHandStack.getItem() : offHandStack.getItem(); + return weaponItem.components().has(DataComponents.DAMAGE); + } else { + return false; + } + } + + // TODO/NOTE: I know this can be condensed more but i'm tired so will recheck later + public static boolean shouldHideShield(ItemStack mainHandStack, ItemStack offHandStack, ItemStack stack) { + if (SwordBlockingConfig.enabled && stack.getItem() instanceof ShieldItem) { + return (SwordBlockingConfig.alwaysHideShield && SwordBlockingConfig.hideShield) || + (SwordBlockingConfig.hideShield && SwordBlockingClient.canShieldSwordBlock(mainHandStack, offHandStack)); + } else { + return false; + } + } + + private void initialize() { + SwordBlockingConfig.init(MOD_ID, SwordBlockingConfig.class); + } + + //? neoforge { + public SwordBlockingClient() { + initialize(); + } + //?} else { + /*@Override + public void onInitializeClient() { + initialize(); + } + *///?} +} \ No newline at end of file diff --git a/src/main/java/eu/midnightdust/swordblocking/config/SwordBlockingConfig.java b/src/main/java/eu/midnightdust/swordblocking/config/SwordBlockingConfig.java new file mode 100644 index 0000000..8220914 --- /dev/null +++ b/src/main/java/eu/midnightdust/swordblocking/config/SwordBlockingConfig.java @@ -0,0 +1,26 @@ +package eu.midnightdust.swordblocking.config; + +import eu.midnightdust.lib.config.MidnightConfig; + +public class SwordBlockingConfig extends MidnightConfig { + @Entry + public static boolean enabled = true; + + @Entry + public static boolean hideShield = true; + + @Entry + public static boolean alwaysHideShield = true; + + @Entry + public static boolean hideOffhandSlot = false; + + @Entry + public static boolean disableUseEquipAnimation = false; + + @Entry + public static boolean lockBlockingArmPosition = false; + + @Entry + public static boolean blockHitAnimation = false; +} diff --git a/src/main/java/eu/midnightdust/swordblocking/ducks/ArmedItemStackData.java b/src/main/java/eu/midnightdust/swordblocking/ducks/ArmedItemStackData.java new file mode 100644 index 0000000..17e71ec --- /dev/null +++ b/src/main/java/eu/midnightdust/swordblocking/ducks/ArmedItemStackData.java @@ -0,0 +1,10 @@ +package eu.midnightdust.swordblocking.ducks; + +import net.minecraft.world.entity.HumanoidArm; +import net.minecraft.world.item.ItemStack; + +public interface ArmedItemStackData { + ItemStack swordblocking$getItemHeldByArm(HumanoidArm humanoidArm); + + void swordblocking$setItemHeldByArm(HumanoidArm arm, ItemStack itemStack); +} diff --git a/src/main/java/eu/midnightdust/swordblocking/mixins/MixinArmedEntityRenderState.java b/src/main/java/eu/midnightdust/swordblocking/mixins/MixinArmedEntityRenderState.java new file mode 100644 index 0000000..7f1b8c9 --- /dev/null +++ b/src/main/java/eu/midnightdust/swordblocking/mixins/MixinArmedEntityRenderState.java @@ -0,0 +1,51 @@ +package eu.midnightdust.swordblocking.mixins; + +import eu.midnightdust.swordblocking.ducks.ArmedItemStackData; +import net.minecraft.client.renderer.entity.state.ArmedEntityRenderState; +import net.minecraft.client.renderer.item.ItemModelResolver; +import net.minecraft.world.entity.HumanoidArm; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.item.ItemStack; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Unique; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(ArmedEntityRenderState.class) +public abstract class MixinArmedEntityRenderState implements ArmedItemStackData { + @Unique + private ItemStack swordblocking$leftStack = ItemStack.EMPTY; + + @Unique + private ItemStack swordblocking$rightStack = ItemStack.EMPTY; + + @Inject(method = "extractArmedEntityRenderState", at = @At("TAIL")) + private static void swordBlocking$storeRequiredData(LivingEntity livingEntity, ArmedEntityRenderState armedEntityRenderState, ItemModelResolver itemModelResolver, CallbackInfo ci) { + ArmedItemStackData armedItemStackData = (ArmedItemStackData) armedEntityRenderState; + armedItemStackData.swordblocking$setItemHeldByArm(HumanoidArm.LEFT, livingEntity.getItemHeldByArm(HumanoidArm.LEFT)); + armedItemStackData.swordblocking$setItemHeldByArm(HumanoidArm.RIGHT, livingEntity.getItemHeldByArm(HumanoidArm.RIGHT)); + } + + @Override + public ItemStack swordblocking$getItemHeldByArm(HumanoidArm arm) { + if (arm == HumanoidArm.LEFT) { + return swordblocking$leftStack; + } else if (arm == HumanoidArm.RIGHT) { + return swordblocking$rightStack; + } else { + throw new UnsupportedOperationException(); + } + } + + @Override + public void swordblocking$setItemHeldByArm(HumanoidArm arm, ItemStack itemStack) { + if (arm == HumanoidArm.LEFT) { + swordblocking$leftStack = itemStack; + } else if (arm == HumanoidArm.RIGHT) { + swordblocking$rightStack = itemStack; + } else { + throw new UnsupportedOperationException(); + } + } +} diff --git a/common/src/main/java/eu/midnightdust/swordblocking/mixin/MixinInGameHud.java b/src/main/java/eu/midnightdust/swordblocking/mixins/MixinGui.java similarity index 55% rename from common/src/main/java/eu/midnightdust/swordblocking/mixin/MixinInGameHud.java rename to src/main/java/eu/midnightdust/swordblocking/mixins/MixinGui.java index a254e79..44e2f0f 100644 --- a/common/src/main/java/eu/midnightdust/swordblocking/mixin/MixinInGameHud.java +++ b/src/main/java/eu/midnightdust/swordblocking/mixins/MixinGui.java @@ -1,16 +1,16 @@ -package eu.midnightdust.swordblocking.mixin; +package eu.midnightdust.swordblocking.mixins; import com.llamalad7.mixinextras.injector.ModifyExpressionValue; import eu.midnightdust.swordblocking.config.SwordBlockingConfig; -import net.minecraft.client.gui.hud.InGameHud; -import net.minecraft.item.ItemStack; -import net.minecraft.item.ShieldItem; +import net.minecraft.client.gui.Gui; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.ShieldItem; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; -@Mixin(InGameHud.class) -public abstract class MixinInGameHud { - @ModifyExpressionValue(at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/player/PlayerEntity;getOffHandStack()Lnet/minecraft/item/ItemStack;"), method = "renderHotbarVanilla") +@Mixin(Gui.class) +public abstract class MixinGui { + @ModifyExpressionValue(method = "renderItemHotbar", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/player/Player;getOffhandItem()Lnet/minecraft/world/item/ItemStack;")) public ItemStack swordBlocking$hideOffHandSlot(ItemStack original) { if (SwordBlockingConfig.enabled && SwordBlockingConfig.hideOffhandSlot && original.getItem() instanceof ShieldItem) { return ItemStack.EMPTY; diff --git a/src/main/java/eu/midnightdust/swordblocking/mixins/MixinHumanoidModel.java b/src/main/java/eu/midnightdust/swordblocking/mixins/MixinHumanoidModel.java new file mode 100644 index 0000000..1004b09 --- /dev/null +++ b/src/main/java/eu/midnightdust/swordblocking/mixins/MixinHumanoidModel.java @@ -0,0 +1,48 @@ +package eu.midnightdust.swordblocking.mixins; + +import eu.midnightdust.swordblocking.SwordBlockingClient; +import eu.midnightdust.swordblocking.config.SwordBlockingConfig; +import eu.midnightdust.swordblocking.ducks.ArmedItemStackData; +import net.minecraft.client.model.HumanoidModel; +import net.minecraft.client.renderer.entity.state.HumanoidRenderState; +import net.minecraft.world.entity.HumanoidArm; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.ShieldItem; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.Redirect; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(HumanoidModel.class) +public abstract class MixinHumanoidModel { + @Shadow + protected abstract void poseLeftArm(HumanoidRenderState renderState, HumanoidModel.ArmPose pose); + + @Shadow + protected abstract void poseRightArm(HumanoidRenderState renderState, HumanoidModel.ArmPose pose); + + @Inject(method = "setupAnim(Lnet/minecraft/client/renderer/entity/state/HumanoidRenderState;)V", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/model/HumanoidModel;setupAttackAnimation(Lnet/minecraft/client/renderer/entity/state/HumanoidRenderState;F)V", shift = At.Shift.BEFORE)) + private void swordBlocking$setBlockingAngles(HumanoidRenderState renderState, CallbackInfo ci) { + final ArmedItemStackData armedItemStackData = (ArmedItemStackData) renderState; + final ItemStack offHandStack = armedItemStackData.swordblocking$getItemHeldByArm(HumanoidArm.LEFT); + final ItemStack mainHandStack = armedItemStackData.swordblocking$getItemHeldByArm(HumanoidArm.RIGHT); + if (renderState.isUsingItem && SwordBlockingClient.canEntityBlock(mainHandStack, offHandStack)) { + if (offHandStack.getItem() instanceof ShieldItem) { + this.poseRightArm(renderState, HumanoidModel.ArmPose.BLOCK); + } else { + this.poseLeftArm(renderState, HumanoidModel.ArmPose.BLOCK); + } + } + } + + @Redirect(method = "poseBlockingArm", at = @At(value = "INVOKE", target = "Lnet/minecraft/util/Mth;clamp(FFF)F")) + private float swordBlocking$lockArmPosition(float value, float min, float max) { + if (SwordBlockingConfig.enabled && SwordBlockingConfig.lockBlockingArmPosition) { + return 0F; + } else { + return value; + } + } +} diff --git a/src/main/java/eu/midnightdust/swordblocking/mixins/MixinItemInHandLayer.java b/src/main/java/eu/midnightdust/swordblocking/mixins/MixinItemInHandLayer.java new file mode 100644 index 0000000..2c2262e --- /dev/null +++ b/src/main/java/eu/midnightdust/swordblocking/mixins/MixinItemInHandLayer.java @@ -0,0 +1,28 @@ +package eu.midnightdust.swordblocking.mixins; + +import com.llamalad7.mixinextras.sugar.Local; +import eu.midnightdust.swordblocking.SwordBlockingClient; +import eu.midnightdust.swordblocking.config.SwordBlockingConfig; +import eu.midnightdust.swordblocking.ducks.ArmedItemStackData; +import net.minecraft.client.model.ArmedModel; +import net.minecraft.client.model.EntityModel; +import net.minecraft.client.renderer.entity.layers.ItemInHandLayer; +import net.minecraft.client.renderer.entity.state.ArmedEntityRenderState; +import net.minecraft.client.renderer.item.ItemStackRenderState; +import net.minecraft.world.entity.HumanoidArm; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Redirect; + +@Mixin(ItemInHandLayer.class) +public abstract class MixinItemInHandLayer & ArmedModel> { + @Redirect(method = "renderArmWithItem", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/item/ItemStackRenderState;isEmpty()Z")) + private boolean swordBlocking$hideShield(ItemStackRenderState instance, @Local(argsOnly = true) S renderState, @Local(argsOnly = true) HumanoidArm arm) { + if (SwordBlockingConfig.enabled) { + final ArmedItemStackData armedItemStackData = (ArmedItemStackData) renderState; + return SwordBlockingClient.shouldHideShield(armedItemStackData.swordblocking$getItemHeldByArm(HumanoidArm.RIGHT), armedItemStackData.swordblocking$getItemHeldByArm(HumanoidArm.LEFT), armedItemStackData.swordblocking$getItemHeldByArm(arm)); + } + + return instance.isEmpty(); + } +} diff --git a/src/main/java/eu/midnightdust/swordblocking/mixins/MixinItemInHandRenderer.java b/src/main/java/eu/midnightdust/swordblocking/mixins/MixinItemInHandRenderer.java new file mode 100644 index 0000000..ca2d88c --- /dev/null +++ b/src/main/java/eu/midnightdust/swordblocking/mixins/MixinItemInHandRenderer.java @@ -0,0 +1,82 @@ +package eu.midnightdust.swordblocking.mixins; + +import com.llamalad7.mixinextras.injector.wrapmethod.WrapMethod; +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; +import com.llamalad7.mixinextras.sugar.Local; +import com.mojang.blaze3d.vertex.PoseStack; +import eu.midnightdust.swordblocking.SwordBlockingClient; +import eu.midnightdust.swordblocking.config.SwordBlockingConfig; +import net.minecraft.client.Minecraft; +import net.minecraft.client.player.AbstractClientPlayer; +import net.minecraft.client.renderer.ItemInHandRenderer; +import net.minecraft.client.renderer.MultiBufferSource; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.entity.HumanoidArm; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.item.ItemDisplayContext; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.ItemUseAnimation; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.Unique; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.Redirect; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(ItemInHandRenderer.class) +public abstract class MixinItemInHandRenderer { + @Shadow + @Final + private Minecraft minecraft; + + @Shadow + protected abstract void applyItemArmAttackTransform(PoseStack poseStack, HumanoidArm hand, float swingProgress); + + @WrapMethod(method = "renderItem") + public void swordBlocking$hideShield(LivingEntity entity, ItemStack stack, ItemDisplayContext displayContext, PoseStack poseStack, MultiBufferSource bufferSource, int packedLight, Operation original) { + if (!SwordBlockingClient.shouldHideShield(entity.getMainHandItem(), entity.getOffhandItem(), stack)) { + original.call(entity, stack, displayContext, poseStack, bufferSource, packedLight); + } + } + + @Redirect(method = "renderArmWithItem", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/player/AbstractClientPlayer;getUsedItemHand()Lnet/minecraft/world/InteractionHand;", ordinal = 1)) + private InteractionHand swordBlocking$changeActiveHand(AbstractClientPlayer instance) { + final InteractionHand activeHand = instance.getUsedItemHand(); + if (SwordBlockingClient.canEntityBlock(instance.getMainHandItem(), instance.getOffhandItem())) { + return swordBlocking$getBlockingHand(activeHand); + } else { + return activeHand; + } + } + + @Redirect(method = "renderArmWithItem", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/item/ItemStack;getUseAnimation()Lnet/minecraft/world/item/ItemUseAnimation;")) + private ItemUseAnimation swordBlocking$changeItemAction(ItemStack stack, @Local(argsOnly = true) AbstractClientPlayer player, @Local(argsOnly = true) InteractionHand interactionHand) { + final ItemUseAnimation defaultUseAction = stack.getUseAnimation(); + if (SwordBlockingClient.canEntityBlock(player.getMainHandItem(), player.getOffhandItem())) { + return swordBlocking$getBlockingHand(player.getUsedItemHand()) == interactionHand ? ItemUseAnimation.BLOCK : defaultUseAction; + } else { + return defaultUseAction; + } + } + + @Inject(method = "renderArmWithItem", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/ItemInHandRenderer;applyItemArmTransform(Lcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/world/entity/HumanoidArm;F)V", ordinal = 3, shift = At.Shift.AFTER)) + private void swordBlocking$applySwingOffset(AbstractClientPlayer player, float partialTicks, float pitch, InteractionHand hand, float swingProgress, ItemStack stack, float equippedProgress, PoseStack poseStack, MultiBufferSource buffer, int combinedLight, CallbackInfo ci, @Local HumanoidArm arm) { + if (SwordBlockingConfig.enabled && SwordBlockingConfig.blockHitAnimation) { + this.applyItemArmAttackTransform(poseStack, arm, swingProgress); + } + } + + @WrapMethod(method = "itemUsed") + private void swordBlocking$disableEquipAnimation(InteractionHand hand, Operation original) { + if (!SwordBlockingConfig.disableUseEquipAnimation || this.minecraft.player == null || !this.minecraft.player.isUsingItem()) { + original.call(hand); + } + } + + @Unique + private InteractionHand swordBlocking$getBlockingHand(InteractionHand interactionHand) { + return interactionHand == InteractionHand.MAIN_HAND ? InteractionHand.OFF_HAND : InteractionHand.MAIN_HAND; + } +} diff --git a/src/main/java/eu/midnightdust/swordblocking/mixins/MixinPlayerRenderer.java b/src/main/java/eu/midnightdust/swordblocking/mixins/MixinPlayerRenderer.java new file mode 100644 index 0000000..0c93221 --- /dev/null +++ b/src/main/java/eu/midnightdust/swordblocking/mixins/MixinPlayerRenderer.java @@ -0,0 +1,41 @@ +package eu.midnightdust.swordblocking.mixins; + +import eu.midnightdust.swordblocking.SwordBlockingClient; +import eu.midnightdust.swordblocking.config.SwordBlockingConfig; +import net.minecraft.client.model.HumanoidModel; +import net.minecraft.client.renderer.entity.player.PlayerRenderer; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.ShieldItem; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +//? fabric { +/*import net.fabricmc.api.Environment; +import net.fabricmc.api.EnvType; +*///? } + +@Mixin(PlayerRenderer.class) +public abstract class MixinPlayerRenderer { + //? fabric + /*@Environment(EnvType.CLIENT)*/ + @Inject(method = "getArmPose(Lnet/minecraft/world/entity/player/Player;Lnet/minecraft/world/item/ItemStack;Lnet/minecraft/world/InteractionHand;)Lnet/minecraft/client/model/HumanoidModel$ArmPose;", at = @At(value = "RETURN"), cancellable = true) + private static void swordBlocking$getArmPose(Player player, ItemStack stack, InteractionHand hand, CallbackInfoReturnable cir) { + if (SwordBlockingConfig.enabled) { + final ItemStack handStack = player.getItemInHand(hand); + final ItemStack offStack = player.getItemInHand(hand.equals(InteractionHand.MAIN_HAND) ? InteractionHand.OFF_HAND : InteractionHand.MAIN_HAND); + if (!SwordBlockingConfig.alwaysHideShield && (handStack.getItem() instanceof ShieldItem) && !SwordBlockingClient.canShieldSwordBlock(player.getMainHandItem(), player.getOffhandItem())) { + return; + } + + if (offStack.getItem() instanceof ShieldItem && SwordBlockingClient.canEntityBlock(player.getMainHandItem(), player.getOffhandItem())) { + cir.setReturnValue(HumanoidModel.ArmPose.BLOCK); + } else if (handStack.getItem() instanceof ShieldItem && SwordBlockingConfig.hideShield && (cir.getReturnValue() == HumanoidModel.ArmPose.ITEM || cir.getReturnValue() == HumanoidModel.ArmPose.BLOCK)) { + cir.setReturnValue(HumanoidModel.ArmPose.EMPTY); + } + } + } +} diff --git a/src/main/resources/META-INF/neoforge.mods.toml b/src/main/resources/META-INF/neoforge.mods.toml new file mode 100644 index 0000000..81b9dc8 --- /dev/null +++ b/src/main/resources/META-INF/neoforge.mods.toml @@ -0,0 +1,30 @@ +modLoader = "javafml" +loaderVersion = "[1,)" +license = "${license}" +issueTrackerURL = "${issues}" + +[[mods]] +modId = "${id}" +version = "${version}" +displayName = "${name}" +description = "${description}" +logoFile = "assets/${id}/icon.png" +authors = ["Motschen", "TeamMidnightDust", "lowercasebtw"] +displayURL = "${modrinth}" + +[[mixins]] +config = "${id}.mixins.json" + +[[dependencies.${id}]] +modId = "neoforge" +mandatory = true +versionRange = "[${neoforge_version},)" +ordering = "NONE" +side = "CLIENT" + +[[dependencies.${id}]] +modId = "minecraft" +mandatory = true +versionRange = "${minecraft_version_range}" +ordering = "NONE" +side = "CLIENT" \ No newline at end of file diff --git a/common/src/main/resources/assets/swordblocking/icon.png b/src/main/resources/assets/swordblocking/icon.png similarity index 100% rename from common/src/main/resources/assets/swordblocking/icon.png rename to src/main/resources/assets/swordblocking/icon.png diff --git a/common/src/main/resources/assets/swordblocking/lang/en_us.json b/src/main/resources/assets/swordblocking/lang/en_us.json similarity index 100% rename from common/src/main/resources/assets/swordblocking/lang/en_us.json rename to src/main/resources/assets/swordblocking/lang/en_us.json diff --git a/common/src/main/resources/assets/swordblocking/lang/ru_ru.json b/src/main/resources/assets/swordblocking/lang/ru_ru.json similarity index 98% rename from common/src/main/resources/assets/swordblocking/lang/ru_ru.json rename to src/main/resources/assets/swordblocking/lang/ru_ru.json index 726a24f..2ad1c78 100644 --- a/common/src/main/resources/assets/swordblocking/lang/ru_ru.json +++ b/src/main/resources/assets/swordblocking/lang/ru_ru.json @@ -1,11 +1,11 @@ -{ - "swordblocking.midnightconfig.title": "Конфигурация Sword Blocking", - "swordblocking.midnightconfig.enabled": "Включено", - "swordblocking.midnightconfig.hideShield": "Спрятать щит", - "swordblocking.midnightconfig.alwaysHideShield": "Всегда прятать щит", - "swordblocking.midnightconfig.hideOffhandSlot": "Скрывать слот второй руки", - "swordblocking.midnightconfig.hideOffhandSlot.tooltip": "Скрывает слот второй руки, если в ней находится щит.", - "swordblocking.midnightconfig.disableUseEquipAnimation": "Удалять анимацию оснащения при блокировании.", - "swordblocking.midnightconfig.lockBlockingArmPosition": "Отключить движение руки при блокировании.", - "swordblocking.midnightconfig.blockHitAnimation": "Включить анимацию удара по блоку." +{ + "swordblocking.midnightconfig.title": "Конфигурация Sword Blocking", + "swordblocking.midnightconfig.enabled": "Включено", + "swordblocking.midnightconfig.hideShield": "Спрятать щит", + "swordblocking.midnightconfig.alwaysHideShield": "Всегда прятать щит", + "swordblocking.midnightconfig.hideOffhandSlot": "Скрывать слот второй руки", + "swordblocking.midnightconfig.hideOffhandSlot.tooltip": "Скрывает слот второй руки, если в ней находится щит.", + "swordblocking.midnightconfig.disableUseEquipAnimation": "Удалять анимацию оснащения при блокировании.", + "swordblocking.midnightconfig.lockBlockingArmPosition": "Отключить движение руки при блокировании.", + "swordblocking.midnightconfig.blockHitAnimation": "Включить анимацию удара по блоку." } \ No newline at end of file diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json new file mode 100644 index 0000000..e67afd6 --- /dev/null +++ b/src/main/resources/fabric.mod.json @@ -0,0 +1,35 @@ +{ + "schemaVersion": 1, + "id": "${id}", + "version": "${version}", + "name": "${name}", + "description": "${description}", + "authors": [ + "Motschen", + "TeamMidnightDust", + "lowercasebtw" + ], + "contact": { + "sources": "${source}", + "issues": "${issues}" + }, + "license": "${license}", + "icon": "assets/${id}/icon.png", + "environment": "client", + "depends": { + "fabricloader": ">=${fabric_loader_version}", + "minecraft": "${minecraft_version_range}", + "fabric-api": "*", + "midnightlib": "*" + }, + "custom": { + "modmenu": { + "links": { + "modmenu.discord": "${discord}", + "modmenu.modrinth": "${modrinth}", + "modmenu.curseforge": "${curseforge}" + }, + "update_checker": true + } + } +} diff --git a/src/main/resources/swordblocking.mixins.json b/src/main/resources/swordblocking.mixins.json new file mode 100644 index 0000000..1206c77 --- /dev/null +++ b/src/main/resources/swordblocking.mixins.json @@ -0,0 +1,19 @@ +{ + "required": true, + "package": "eu.midnightdust.swordblocking.mixins", + "compatibilityLevel": "JAVA_17", + "client": [ + "MixinGui", + "MixinArmedEntityRenderState", + "MixinHumanoidModel", + "MixinItemInHandLayer", + "MixinItemInHandRenderer", + "MixinPlayerRenderer" + ], + "injectors": { + "defaultRequire": 1 + }, + "mixinextras": { + "minVersion": "0.5.0" + } +} \ No newline at end of file diff --git a/stonecutter.gradle.kts b/stonecutter.gradle.kts new file mode 100644 index 0000000..3abcf2f --- /dev/null +++ b/stonecutter.gradle.kts @@ -0,0 +1,25 @@ +import dev.kikugie.stonecutter.data.tree.struct.ProjectNode + +plugins { + id("dev.kikugie.stonecutter") + alias(libs.plugins.publishing) +} + +stonecutter active "1.21.8-neoforge" /* [SC] DO NOT EDIT */ + +stonecutter tasks { + val ordering = Comparator + .comparing { stonecutter.parse(it.metadata.version) } + .thenComparingInt { if (it.metadata.project.endsWith("fabric")) 1 else 0 } + order("publishMods", ordering) +} + +stonecutter parameters { + val loader = node.project.property("loom.platform") + constants["fabric"] = loader == "fabric" + constants["neoforge"] = loader == "neoforge" +} + +tasks.named("publishMods") { + group = "build" +} \ No newline at end of file diff --git a/versions/1.21.8-fabric/gradle.properties b/versions/1.21.8-fabric/gradle.properties new file mode 100644 index 0000000..5bcf22f --- /dev/null +++ b/versions/1.21.8-fabric/gradle.properties @@ -0,0 +1,8 @@ +loom.platform=fabric + +deps.parchment_version=2025.09.14 +deps.fabric_api_version=0.136.1+1.21.8 +deps.modmenu_version=15.0.0 + +mod.minecraft_version=1.21.8 +mod.minecraft_version_range=>=1.21.6 <=1.21.8 \ No newline at end of file diff --git a/versions/1.21.8-neoforge/gradle.properties b/versions/1.21.8-neoforge/gradle.properties new file mode 100644 index 0000000..ee979bd --- /dev/null +++ b/versions/1.21.8-neoforge/gradle.properties @@ -0,0 +1,7 @@ +loom.platform=neoforge + +deps.parchment_version=2025.09.14 +deps.neoforge_version=21.8.51 + +mod.minecraft_version=1.21.8 +mod.minecraft_version_range=[1.21.6, 1.21.7, 1.21.8] \ No newline at end of file