1.0.0
build / build (push) Canceled after 0s

This commit is contained in:
2026-09-20 20:16:15 +08:00
parent 5f442f2b8e
commit 725ed0f0fb
16 changed files with 108 additions and 114 deletions
+4 -9
View File
@@ -1,13 +1,8 @@
# 自然之需:可抱起后代 # 自然之需:村民交易打折
——三小时摸鱼作品 ——花费一天半的摸鱼作
[English readme here](./README_en.md) [English readme here](./README_en.md)
在使用 carryon 抱起生物的时候,默认是不能抱起敌对生物的——很合理,毕竟直觉上它们会反抗。 玩家生下的村民给予对应玩家相应折扣,力度和一次[骨折](https://www.bilibili.com/video/av377809712)相当。
但是,自然之需有一个选项“敌对后代不攻击玩家”,这意味着它们大概不会反抗你抱起来了。 图标是gpt画的
因此,我们将此限制解除:如果是玩家产下的后代(无论谁生的,因为自然之需没有记录后代的母亲是哪个玩家),则无视敌对和体型限制,使其更符合直觉。
## todo
此 mod 没有读取自然之需的配置 `NeedsOfNature.getConfig().pregnancyFriendlyMobsIgnorePlayers()` 也没有新建一个配置,因为作为只有一个选项的 mod,关掉还不如直接卸了方便些。
+3 -8
View File
@@ -1,12 +1,7 @@
# Needs of Nature: Picking Up Offspring # Needs of Nature: Villager discount
[中文文档](./README.md) [中文文档](./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. icon powered by gpt cuz i'm lazy.
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.
+1 -5
View File
@@ -20,7 +20,7 @@ loom {
splitEnvironmentSourceSets() splitEnvironmentSourceSets()
mods { mods {
"non-carryon" { "non-villager-discount" {
sourceSet sourceSets.main sourceSet sourceSets.main
sourceSet sourceSets.client sourceSet sourceSets.client
} }
@@ -36,11 +36,7 @@ dependencies {
// Fabric API. This is technically optional, but you probably want it anyway. // Fabric API. This is technically optional, but you probably want it anyway.
modImplementation "net.fabricmc.fabric-api:fabric-api:${project.fabric_api_version}" 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/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 { processResources {
+1 -1
View File
@@ -10,4 +10,4 @@ pluginManagement {
} }
// Should match your modid // Should match your modid
rootProject.name = 'non-carryon' rootProject.name = 'non-villager-discount'
@@ -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));
}
}
@@ -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);
}
}
-61
View File
@@ -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);
}
}
Binary file not shown.

Before

Width:  |  Height:  |  Size: 995 B

@@ -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"
}
@@ -1,4 +0,0 @@
{
"mystya.non-carryon.name": "自然之需:可抱起后代",
"mystya.non-carryon.description": "自然之需产下的后代可以被玩家 carryon 抱起,无论是敌对生物还是大体积生物。"
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

@@ -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."
}
@@ -0,0 +1,4 @@
{
"mystya.non-villager-discount.name": "自然之需:村民打折",
"mystya.non-villager-discount.description": "玩家生下的村民给予对应玩家相应折扣,力度和一次骨折相当。"
}
+7 -8
View File
@@ -1,12 +1,12 @@
{ {
"schemaVersion": 1, "schemaVersion": 1,
"id": "non-carryon", "id": "non-villager-discount",
"version": "${version}", "version": "${version}",
"name": "allow carry on pickup hostile offspring", "name": "NoN: Villager discount",
"description": "skip carry on mob type check & size check for needs of nature pregnancy offspring", "description": "Villagers offer discounts to the player parent, equivalent in magnitude to the discount granted upon curing a zombie villager.",
"modmenu": { "modmenu": {
"nameTranslation": "mystya.non-carryon.name", "nameTranslation": "mystya.non-villager-discount.name",
"descriptionTranslation": "mystya.non-carryon.description" "descriptionTranslation": "mystya.non-villager-discount.description"
}, },
"authors": [ "authors": [
"mystya" "mystya"
@@ -15,18 +15,17 @@
"sources": "example.com" "sources": "example.com"
}, },
"license": "CC BY-NC 4.0", "license": "CC BY-NC 4.0",
"icon": "assets/non-carryon/icon.png", "icon": "assets/non-villager-discount/icon.png",
"environment": "*", "environment": "*",
"entrypoints": { "entrypoints": {
}, },
"mixins": [ "mixins": [
"non-carryon.mixins.json" "non-villager-discount.mixins.json"
], ],
"depends": { "depends": {
"fabricloader": ">=0.19.5", "fabricloader": ">=0.19.5",
"minecraft": "~1.21.11", "minecraft": "~1.21.11",
"java": ">=21", "java": ">=21",
"carryon": ">=2.9.2",
"needsofnature": ">=1.5.1" "needsofnature": ">=1.5.1"
} }
} }
@@ -1,14 +0,0 @@
{
"required": true,
"package": "mystya.mixin",
"compatibilityLevel": "JAVA_21",
"mixins": [
"carryon"
],
"injectors": {
"defaultRequire": 1
},
"overwrites": {
"requireAnnotations": true
}
}
@@ -0,0 +1,12 @@
{
"required": true,
"package": "mystya.mixin",
"compatibilityLevel": "JAVA_21",
"mixins": ["BirthMixin", "TradeMixin"],
"injectors": {
"defaultRequire": 1
},
"overwrites": {
"requireAnnotations": true
}
}