diff --git a/README.md b/README.md index b3c412b..fdde042 100644 --- a/README.md +++ b/README.md @@ -1,13 +1,8 @@ -# 自然之需:可抱起后代 -——三小时摸鱼作品 +# 自然之需:村民交易打折 +——花费一天半的摸鱼作 [English readme here](./README_en.md) -在使用 carryon 抱起生物的时候,默认是不能抱起敌对生物的——很合理,毕竟直觉上它们会反抗。 +玩家生下的村民给予对应玩家相应折扣,力度和一次[骨折](https://www.bilibili.com/video/av377809712)相当。 -但是,自然之需有一个选项“敌对后代不攻击玩家”,这意味着它们大概不会反抗你抱起来了。 - -因此,我们将此限制解除:如果是玩家产下的后代(无论谁生的,因为自然之需没有记录后代的母亲是哪个玩家),则无视敌对和体型限制,使其更符合直觉。 - -## todo -此 mod 没有读取自然之需的配置 `NeedsOfNature.getConfig().pregnancyFriendlyMobsIgnorePlayers()` 也没有新建一个配置,因为作为只有一个选项的 mod,关掉还不如直接卸了方便些。 \ No newline at end of file +图标是gpt画的 \ No newline at end of file diff --git a/README_en.md b/README_en.md index 8c0e760..5f09054 100644 --- a/README_en.md +++ b/README_en.md @@ -1,12 +1,7 @@ -# Needs of Nature: Picking Up Offspring +# Needs of Nature: Villager discount [中文文档](./README.md) -By default, the `carryon` mod prevents players from picking up hostile creatures—which makes sense, as one would intuitively expect them to resist. +Villagers offer corresponding discounts to the player parent, equivalent in magnitude to the discount granted upon curing a zombie villager. -However, the "Needs of Nature" mod includes an option called "Spawned hostiles ignore players," implying that such offspring likely wouldn't resist being picked up. - -Therefore, we have lifted this restriction: if the offspring was produced by a player (regardless of which specific player gave birth, as "Needs of Nature" does not track the mother's identity), the hostility and size constraints are ignored, making the behavior more intuitive. - -## TODO -This mod neither reads the "Needs of Nature" configuration setting `NeedsOfNature.getConfig().pregnancyFriendlyMobsIgnorePlayers()` nor introduces a new config option; since this mod has only a single function, simply uninstalling it is more convenient than toggling a setting off. \ No newline at end of file +icon powered by gpt cuz i'm lazy. \ No newline at end of file diff --git a/build.gradle b/build.gradle index 7612d36..75d1e34 100644 --- a/build.gradle +++ b/build.gradle @@ -20,7 +20,7 @@ loom { splitEnvironmentSourceSets() mods { - "non-carryon" { + "non-villager-discount" { sourceSet sourceSets.main sourceSet sourceSets.client } @@ -36,11 +36,7 @@ dependencies { // Fabric API. This is technically optional, but you probably want it anyway. modImplementation "net.fabricmc.fabric-api:fabric-api:${project.fabric_api_version}" - - modImplementation files("lib/needsofnature-1.5.1+1.21.11.jar") -// modImplementation files("lib/carryon-fabric-1.21.11-2.9.2.jar") - modImplementation "maven.modrinth:carry-on:2.9.2" } processResources { diff --git a/settings.gradle b/settings.gradle index a0f9673..ce4e698 100644 --- a/settings.gradle +++ b/settings.gradle @@ -10,4 +10,4 @@ pluginManagement { } // Should match your modid -rootProject.name = 'non-carryon' +rootProject.name = 'non-villager-discount' diff --git a/src/main/java/mystya/mixin/BirthMixin.java b/src/main/java/mystya/mixin/BirthMixin.java new file mode 100644 index 0000000..326df66 --- /dev/null +++ b/src/main/java/mystya/mixin/BirthMixin.java @@ -0,0 +1,25 @@ +package mystya.mixin; + +import com.nonid.NeedsOfNature; +import net.minecraft.core.component.DataComponents; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.entity.Mob; +import net.minecraft.world.entity.npc.villager.Villager; +import net.minecraft.world.item.component.CustomData; +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(NeedsOfNature.class) +public class BirthMixin { + @Inject(method = "applyPregnancyMobFlags", at = @At("RETURN")) + private static void addDataToVillager(Mob mob, ServerPlayer player, CallbackInfo ci) { + if (!(mob instanceof Villager villager)) return; + CustomData customData = villager.getOrDefault(DataComponents.CUSTOM_DATA, CustomData.EMPTY); + CompoundTag copyTag = customData.copyTag(); + copyTag.putString("non.villagerDiscont.bornFrom", player.getStringUUID()); + villager.setComponent(DataComponents.CUSTOM_DATA, CustomData.of(copyTag)); + } +} diff --git a/src/main/java/mystya/mixin/TradeMixin.java b/src/main/java/mystya/mixin/TradeMixin.java new file mode 100644 index 0000000..cf16e3e --- /dev/null +++ b/src/main/java/mystya/mixin/TradeMixin.java @@ -0,0 +1,47 @@ +package mystya.mixin; + +import net.minecraft.core.component.DataComponents; +import net.minecraft.world.entity.ai.gossip.GossipContainer; +import net.minecraft.world.entity.ai.gossip.GossipType; +import net.minecraft.world.entity.npc.villager.Villager; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.component.CustomData; +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.Redirect; + +import java.util.UUID; + +@Mixin(Villager.class) +public abstract class TradeMixin { + + + @Redirect( + method = "updateSpecialPrices", + at = @At( + value = "INVOKE", + target = "Lnet/minecraft/world/entity/npc/villager/Villager;getPlayerReputation(Lnet/minecraft/world/entity/player/Player;)I" + ) + ) + private int applyAdditionalPlayerReputation(Villager villager, Player player) { + var original = villager.getPlayerReputation(player); + CustomData customData = villager.getOrDefault(DataComponents.CUSTOM_DATA, CustomData.EMPTY); + var strUUID = customData.copyTag().getString("non.villagerDiscont.bornFrom").orElse(null); + return player.getStringUUID().equals(strUUID) ? original + defaultReputation : original; + } + + @Unique + private static final int defaultReputation = getDefaultReputation(); + + @Unique + private static int getDefaultReputation() { + UUID shadow = new UUID(0L, 0L); + GossipContainer gossip = new GossipContainer(); + + gossip.add(shadow, GossipType.MAJOR_POSITIVE, 20); + gossip.add(shadow, GossipType.MINOR_POSITIVE, 25); + + return gossip.getReputation(shadow, p -> true); + } +} diff --git a/src/main/java/mystya/mixin/carryon.java b/src/main/java/mystya/mixin/carryon.java deleted file mode 100644 index 188ae23..0000000 --- a/src/main/java/mystya/mixin/carryon.java +++ /dev/null @@ -1,61 +0,0 @@ -package mystya.mixin; - -import com.llamalad7.mixinextras.sugar.Local; -import net.minecraft.world.entity.Entity; -import net.minecraft.world.entity.EntityType; -import net.minecraft.world.entity.MobCategory; -import net.minecraft.world.entity.player.Player; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Redirect; -import tschipp.carryon.common.carry.PickupHandler; -import org.spongepowered.asm.mixin.Mixin; -import tschipp.carryon.utils.SizeHelper; - -@Mixin(PickupHandler.class) - -public class carryon { - private static boolean hasTag(Entity e) { - return e.getTags().contains("non.pregnancy_friendly"); - } - - @Redirect( - method = "tryPickupEntity", - at = @At( - value = "INVOKE", - target = "Lnet/minecraft/world/entity/EntityType;getCategory()Lnet/minecraft/world/entity/MobCategory;" - ) - ) - private static MobCategory skipMonsterCheck(EntityType instance, @Local(argsOnly = true) Entity entity) { - MobCategory category = entity.getType().getCategory(); - if (category == MobCategory.MONSTER && hasTag(entity)) - return MobCategory.CREATURE; - return category; - } - - - @Redirect( - method = "tryPickupEntity", - at = @At( - value = "INVOKE", - target = "Ltschipp/carryon/utils/SizeHelper;getRelativeEntityHeight(Lnet/minecraft/world/entity/player/Player;Lnet/minecraft/world/entity/Entity;)F" - ) - ) - private static float skipHeightCheck(Player player, Entity entity) { - if (hasTag(entity)) return 0; - return SizeHelper.getRelativeEntityHeight(player, entity); - } - - - @Redirect( - method = "tryPickupEntity", - at = @At( - value = "INVOKE", - target = "Ltschipp/carryon/utils/SizeHelper;getRelativeEntityWidth(Lnet/minecraft/world/entity/player/Player;Lnet/minecraft/world/entity/Entity;)F" - ) - ) - private static float skipWidthCheck(Player player, Entity entity) { - if (hasTag(entity)) return 0; - return SizeHelper.getRelativeEntityWidth(player, entity); - } - -} \ No newline at end of file diff --git a/src/main/resources/assets/non-carryon/icon.png b/src/main/resources/assets/non-carryon/icon.png deleted file mode 100644 index 79158aa..0000000 Binary files a/src/main/resources/assets/non-carryon/icon.png and /dev/null differ diff --git a/src/main/resources/assets/non-carryon/lang/en_us.json b/src/main/resources/assets/non-carryon/lang/en_us.json deleted file mode 100644 index 503601f..0000000 --- a/src/main/resources/assets/non-carryon/lang/en_us.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "mystya.non-carryon.name": "non: allow carry on pickup hostile offspring", - "mystya.non-carryon.description": "skip carry on mob type check & size check for needs of nature pregnancy offspring" -} \ No newline at end of file diff --git a/src/main/resources/assets/non-carryon/lang/zh_cn.json b/src/main/resources/assets/non-carryon/lang/zh_cn.json deleted file mode 100644 index 27cbf5b..0000000 --- a/src/main/resources/assets/non-carryon/lang/zh_cn.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "mystya.non-carryon.name": "自然之需:可抱起后代", - "mystya.non-carryon.description": "自然之需产下的后代可以被玩家 carryon 抱起,无论是敌对生物还是大体积生物。" -} \ No newline at end of file diff --git a/src/main/resources/assets/non-villager-discount/icon.png b/src/main/resources/assets/non-villager-discount/icon.png new file mode 100644 index 0000000..1fbaf2f Binary files /dev/null and b/src/main/resources/assets/non-villager-discount/icon.png differ diff --git a/src/main/resources/assets/non-villager-discount/lang/en_us.json b/src/main/resources/assets/non-villager-discount/lang/en_us.json new file mode 100644 index 0000000..7c5b0b9 --- /dev/null +++ b/src/main/resources/assets/non-villager-discount/lang/en_us.json @@ -0,0 +1,4 @@ +{ + "mystya.non-villager-discount.name": "NoN: Villager discount", + "mystya.non-villager-discount.description": "Villagers offer discounts to the player parent, equivalent in magnitude to the discount granted upon curing a zombie villager." +} \ No newline at end of file diff --git a/src/main/resources/assets/non-villager-discount/lang/zh_cn.json b/src/main/resources/assets/non-villager-discount/lang/zh_cn.json new file mode 100644 index 0000000..7a90361 --- /dev/null +++ b/src/main/resources/assets/non-villager-discount/lang/zh_cn.json @@ -0,0 +1,4 @@ +{ + "mystya.non-villager-discount.name": "自然之需:村民打折", + "mystya.non-villager-discount.description": "玩家生下的村民给予对应玩家相应折扣,力度和一次骨折相当。" +} \ No newline at end of file diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json index 8221f19..9e71ab4 100644 --- a/src/main/resources/fabric.mod.json +++ b/src/main/resources/fabric.mod.json @@ -1,12 +1,12 @@ { "schemaVersion": 1, - "id": "non-carryon", + "id": "non-villager-discount", "version": "${version}", - "name": "allow carry on pickup hostile offspring", - "description": "skip carry on mob type check & size check for needs of nature pregnancy offspring", + "name": "NoN: Villager discount", + "description": "Villagers offer discounts to the player parent, equivalent in magnitude to the discount granted upon curing a zombie villager.", "modmenu": { - "nameTranslation": "mystya.non-carryon.name", - "descriptionTranslation": "mystya.non-carryon.description" + "nameTranslation": "mystya.non-villager-discount.name", + "descriptionTranslation": "mystya.non-villager-discount.description" }, "authors": [ "mystya" @@ -15,18 +15,17 @@ "sources": "example.com" }, "license": "CC BY-NC 4.0", - "icon": "assets/non-carryon/icon.png", + "icon": "assets/non-villager-discount/icon.png", "environment": "*", "entrypoints": { }, "mixins": [ - "non-carryon.mixins.json" + "non-villager-discount.mixins.json" ], "depends": { "fabricloader": ">=0.19.5", "minecraft": "~1.21.11", "java": ">=21", - "carryon": ">=2.9.2", "needsofnature": ">=1.5.1" } } \ No newline at end of file diff --git a/src/main/resources/non-carryon.mixins.json b/src/main/resources/non-carryon.mixins.json deleted file mode 100644 index ea67c2f..0000000 --- a/src/main/resources/non-carryon.mixins.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "required": true, - "package": "mystya.mixin", - "compatibilityLevel": "JAVA_21", - "mixins": [ - "carryon" - ], - "injectors": { - "defaultRequire": 1 - }, - "overwrites": { - "requireAnnotations": true - } -} \ No newline at end of file diff --git a/src/main/resources/non-villager-discount.mixins.json b/src/main/resources/non-villager-discount.mixins.json new file mode 100644 index 0000000..0735349 --- /dev/null +++ b/src/main/resources/non-villager-discount.mixins.json @@ -0,0 +1,12 @@ +{ + "required": true, + "package": "mystya.mixin", + "compatibilityLevel": "JAVA_21", + "mixins": ["BirthMixin", "TradeMixin"], + "injectors": { + "defaultRequire": 1 + }, + "overwrites": { + "requireAnnotations": true + } +} \ No newline at end of file