@@ -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
@@ -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
@@ -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
@@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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": "玩家生下的村民给予对应玩家相应折扣,力度和一次骨折相当。"
|
||||||
|
}
|
||||||
@@ -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
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user