Skip to content

Commit

Permalink
收割附魔
Browse files Browse the repository at this point in the history
  • Loading branch information
ZhuRuoLing committed Sep 28, 2024
1 parent 64a1cb5 commit 5406d6e
Show file tree
Hide file tree
Showing 13 changed files with 400 additions and 70 deletions.
16 changes: 16 additions & 0 deletions src/generated/resources/data/anvilcraft/enchantment/harvest.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,22 @@
"description": {
"translate": "enchantment.anvilcraft.harvest"
},
"effects": {
"anvilcraft:use_on_block": [
{
"effect": {
"type": "anvilcraft:harvest",
"range": 5
},
"requirements": {
"condition": "minecraft:match_tool",
"predicate": {
"items": "#minecraft:hoes"
}
}
}
]
},
"max_cost": {
"base": 15,
"per_level_above_first": 10
Expand Down
7 changes: 7 additions & 0 deletions src/main/java/dev/dubhe/anvilcraft/AnvilCraft.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,13 @@
import dev.dubhe.anvilcraft.init.ModCommands;
import dev.dubhe.anvilcraft.init.ModComponents;
import dev.dubhe.anvilcraft.init.ModDispenserBehavior;
import dev.dubhe.anvilcraft.init.ModEnchantmentEffectComponents;
import dev.dubhe.anvilcraft.init.ModEnchantmentEffects;
import dev.dubhe.anvilcraft.init.ModEntities;
import dev.dubhe.anvilcraft.init.ModEvents;
import dev.dubhe.anvilcraft.init.ModItemGroups;
import dev.dubhe.anvilcraft.init.ModItems;
import dev.dubhe.anvilcraft.init.ModLootContextParamSets;
import dev.dubhe.anvilcraft.init.ModMenuTypes;
import dev.dubhe.anvilcraft.init.ModNetworks;
import dev.dubhe.anvilcraft.init.ModRecipeTypes;
Expand Down Expand Up @@ -72,6 +75,10 @@ public AnvilCraft(IEventBus modEventBus, ModContainer container) {
ModComponents.register(modEventBus);
ModVillagers.register(modEventBus);
ModRecipeTypes.register(modEventBus);

ModLootContextParamSets.registerAll();
ModEnchantmentEffectComponents.register(modEventBus);
ModEnchantmentEffects.register(modEventBus);
// datagen
AnvilCraftDatagen.init();

Expand Down
33 changes: 33 additions & 0 deletions src/main/java/dev/dubhe/anvilcraft/enchantment/FellingEffect.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package dev.dubhe.anvilcraft.enchantment;

import com.mojang.serialization.Codec;
import com.mojang.serialization.MapCodec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import net.minecraft.MethodsReturnNonnullByDefault;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.item.enchantment.EnchantedItemInUse;
import net.minecraft.world.item.enchantment.effects.EnchantmentEntityEffect;
import net.minecraft.world.phys.Vec3;

import javax.annotation.ParametersAreNonnullByDefault;

@ParametersAreNonnullByDefault
@MethodsReturnNonnullByDefault
public record FellingEffect(int range) implements EnchantmentEntityEffect {
public static final MapCodec<FellingEffect> CODEC = RecordCodecBuilder.mapCodec(it ->
it.group(
Codec.INT.optionalFieldOf("range", 3).forGetter(FellingEffect::range)
).apply(it, FellingEffect::new)
);

@Override
public void apply(ServerLevel serverLevel, int i, EnchantedItemInUse enchantedItemInUse, Entity entity, Vec3 vec3) {
System.out.println("FELLING!!!");
}

@Override
public MapCodec<? extends EnchantmentEntityEffect> codec() {
return CODEC;
}
}
91 changes: 91 additions & 0 deletions src/main/java/dev/dubhe/anvilcraft/enchantment/HarvestEffect.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
package dev.dubhe.anvilcraft.enchantment;

import com.mojang.serialization.Codec;
import com.mojang.serialization.MapCodec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import net.minecraft.MethodsReturnNonnullByDefault;
import net.minecraft.core.BlockPos;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.enchantment.EnchantedItemInUse;
import net.minecraft.world.item.enchantment.effects.EnchantmentEntityEffect;
import net.minecraft.world.level.block.CropBlock;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.phys.Vec3;

import javax.annotation.ParametersAreNonnullByDefault;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;

@ParametersAreNonnullByDefault
@MethodsReturnNonnullByDefault
public record HarvestEffect(int range) implements EnchantmentEntityEffect {
private static final List<BlockPos> ITERATING_OFFSET = new ArrayList<>();

static {
for (int dx = -1; dx <= 1; dx++) {
for (int dz = -1; dz <= 1; dz++) {
ITERATING_OFFSET.add(new BlockPos(dx, 0, dz));
}
}
}

public static final MapCodec<HarvestEffect> CODEC = RecordCodecBuilder.mapCodec(it ->
it.group(
Codec.INT.optionalFieldOf("range", 3)
.forGetter(HarvestEffect::range)
).apply(it, HarvestEffect::new)
);

@Override
public void apply(ServerLevel level, int enchantmentLevel, EnchantedItemInUse enchantedItemInUse, Entity owner, Vec3 vec3) {
ItemStack tool = enchantedItemInUse.itemStack();
BlockPos pos = BlockPos.containing(vec3);
if (!(owner instanceof Player player)) return;
BlockState targetBlockState = level.getBlockState(pos);
boolean hasValidCropBlock = false;
if (targetBlockState.getBlock() instanceof CropBlock cropBlock) {
if (cropBlock.isMaxAge(targetBlockState)) {
hasValidCropBlock = true;
BlockEntity entity = level.getBlockEntity(pos);
cropBlock.playerWillDestroy(level, pos, targetBlockState, player);
cropBlock.playerDestroy(level, player, pos, targetBlockState, entity, tool);
level.setBlockAndUpdate(pos, cropBlock.getStateForAge(0));
}
} else return;
int max = enchantmentLevel * 2 + 1;
max *= max;
if (hasValidCropBlock) max -= 1;
Deque<BlockPos> iteratingPos = new ArrayDeque<>();
iteratingPos.push(pos);
List<BlockPos> vis = new ArrayList<>();
while (!iteratingPos.isEmpty() && max >= 0) {
BlockPos currentIterating = iteratingPos.pop();
if (vis.contains(currentIterating)) continue;
vis.add(currentIterating);
max--;
for (BlockPos offset : ITERATING_OFFSET) {
BlockPos currentPos = currentIterating.offset(offset);
iteratingPos.add(currentPos);
}
BlockState state = level.getBlockState(currentIterating);
if (!(state.getBlock() instanceof CropBlock block)) continue;
if (!block.isMaxAge(state)) continue;
BlockState newState = block.getStateForAge(0);
cropBlock.playerWillDestroy(level, pos, targetBlockState, player);
cropBlock.playerDestroy(level, player, pos, targetBlockState, level.getBlockEntity(currentIterating), tool);
level.setBlockAndUpdate(currentIterating, newState);
}
}

@Override
public MapCodec<? extends EnchantmentEntityEffect> codec() {
return CODEC;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package dev.dubhe.anvilcraft.init;

import dev.dubhe.anvilcraft.AnvilCraft;
import net.minecraft.core.component.DataComponentType;
import net.minecraft.core.registries.Registries;
import net.minecraft.world.item.enchantment.ConditionalEffect;
import net.minecraft.world.item.enchantment.effects.EnchantmentEntityEffect;
import net.neoforged.bus.api.IEventBus;
import net.neoforged.neoforge.registries.DeferredRegister;

import java.util.List;
import java.util.function.UnaryOperator;

public class ModEnchantmentEffectComponents {

private static final DeferredRegister<DataComponentType<?>> REGISTER =
DeferredRegister.create(Registries.ENCHANTMENT_EFFECT_COMPONENT_TYPE, AnvilCraft.MOD_ID);

public static final DataComponentType<List<ConditionalEffect<EnchantmentEntityEffect>>> USE_ON_BLOCK = register(
"use_on_block",
(it) -> it.persistent(
ConditionalEffect.codec(
EnchantmentEntityEffect.CODEC,
ModLootContextParamSets.USE_ON_ITEM
).listOf()
)
);

private static <T> DataComponentType<T> register(String name, UnaryOperator<DataComponentType.Builder<T>> operator) {
DataComponentType<T> dct = operator.apply(DataComponentType.builder()).build();
REGISTER.register(name, () -> dct);
return dct;
}

public static void register(IEventBus bus) {
REGISTER.register(bus);
}
}
29 changes: 29 additions & 0 deletions src/main/java/dev/dubhe/anvilcraft/init/ModEnchantmentEffects.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package dev.dubhe.anvilcraft.init;

import com.mojang.serialization.MapCodec;
import dev.dubhe.anvilcraft.AnvilCraft;
import dev.dubhe.anvilcraft.enchantment.FellingEffect;
import dev.dubhe.anvilcraft.enchantment.HarvestEffect;
import net.minecraft.core.registries.Registries;
import net.minecraft.world.item.enchantment.effects.EnchantmentEntityEffect;
import net.neoforged.bus.api.IEventBus;
import net.neoforged.neoforge.registries.DeferredRegister;

public class ModEnchantmentEffects {
public static final DeferredRegister<MapCodec<? extends EnchantmentEntityEffect>> REGISTER =
DeferredRegister.create(Registries.ENCHANTMENT_ENTITY_EFFECT_TYPE, AnvilCraft.MOD_ID);
static {
REGISTER.register(
"harvest",
() -> HarvestEffect.CODEC
);
REGISTER.register(
"felling",
() -> FellingEffect.CODEC
);
}

public static void register(IEventBus eventBus){
REGISTER.register(eventBus);
}
}
107 changes: 54 additions & 53 deletions src/main/java/dev/dubhe/anvilcraft/init/ModEnchantments.java
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
package dev.dubhe.anvilcraft.init;

import dev.dubhe.anvilcraft.AnvilCraft;
import dev.dubhe.anvilcraft.util.Lazy;
import dev.dubhe.anvilcraft.enchantment.HarvestEffect;

import net.minecraft.core.Holder;
import net.minecraft.advancements.critereon.ItemPredicate;
import net.minecraft.core.HolderGetter;
import net.minecraft.core.Registry;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.core.registries.Registries;
import net.minecraft.data.worldgen.BootstrapContext;
import net.minecraft.resources.ResourceKey;
Expand All @@ -16,6 +14,7 @@
import net.minecraft.world.item.Item;
import net.minecraft.world.item.enchantment.Enchantment;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.storage.loot.predicates.MatchTool;

@SuppressWarnings("unchecked")
public class ModEnchantments {
Expand All @@ -24,24 +23,6 @@ public class ModEnchantments {
public static final ResourceKey<Enchantment> HARVEST_KEY = key("harvest");
public static final ResourceKey<Enchantment> BEHEADING_KEY = key("beheading");

public static final Lazy<Holder<Enchantment>> FELLING = new Lazy<>(() -> {
Registry<Enchantment> enchantmentRegistry =
(Registry<Enchantment>) BuiltInRegistries.REGISTRY.get(Registries.ENCHANTMENT.location());
return enchantmentRegistry.getHolderOrThrow(FELLING_KEY).getDelegate();
});

public static Lazy<Holder<Enchantment>> HARVEST = new Lazy<>(() -> {
Registry<Enchantment> enchantmentRegistry =
(Registry<Enchantment>) BuiltInRegistries.REGISTRY.get(Registries.ENCHANTMENT.location());
return enchantmentRegistry.getHolderOrThrow(HARVEST_KEY).getDelegate();
});

public static final Lazy<Holder<Enchantment>> BEHEADING = new Lazy<>(() -> {
Registry<Enchantment> enchantmentRegistry =
(Registry<Enchantment>) BuiltInRegistries.REGISTRY.get(Registries.ENCHANTMENT.location());
return enchantmentRegistry.getHolderOrThrow(BEHEADING_KEY).getDelegate();
});

public static ResourceKey<Enchantment> key(String name) {
return ResourceKey.create(Registries.ENCHANTMENT, AnvilCraft.of(name));
}
Expand All @@ -55,42 +36,62 @@ public static void bootstrap(BootstrapContext<Enchantment> context) {
HolderGetter<Item> itemHolderGetter = context.lookup(Registries.ITEM);
HolderGetter<Block> blockHolderGetter = context.lookup(Registries.BLOCK);
register(
context,
FELLING_KEY,
Enchantment.enchantment(Enchantment.definition(
itemHolderGetter.getOrThrow(ItemTags.AXES),
5,
3,
Enchantment.dynamicCost(1, 10),
Enchantment.dynamicCost(15, 10),
2,
EquipmentSlotGroup.MAINHAND)));
context,
FELLING_KEY,
Enchantment.enchantment(
Enchantment.definition(
itemHolderGetter.getOrThrow(ItemTags.AXES),
5,
3,
Enchantment.dynamicCost(1, 10),
Enchantment.dynamicCost(15, 10),
2,
EquipmentSlotGroup.MAINHAND
)
)
);
register(
context,
HARVEST_KEY,
Enchantment.enchantment(Enchantment.definition(
itemHolderGetter.getOrThrow(ItemTags.HOES),
5,
3,
Enchantment.dynamicCost(1, 10),
Enchantment.dynamicCost(15, 10),
2,
EquipmentSlotGroup.MAINHAND)));
context,
HARVEST_KEY,
Enchantment.enchantment(
Enchantment.definition(
itemHolderGetter.getOrThrow(ItemTags.HOES),
5,
3,
Enchantment.dynamicCost(1, 10),
Enchantment.dynamicCost(15, 10),
2,
EquipmentSlotGroup.MAINHAND
)
).withEffect(
ModEnchantmentEffectComponents.USE_ON_BLOCK,
new HarvestEffect(5),
MatchTool.toolMatches(
ItemPredicate.Builder.item()
.of(ItemTags.HOES)
)

)
);
register(
context,
BEHEADING_KEY,
Enchantment.enchantment(Enchantment.definition(
itemHolderGetter.getOrThrow(ItemTags.SWORDS),
5,
3,
Enchantment.dynamicCost(1, 10),
Enchantment.dynamicCost(15, 10),
2,
EquipmentSlotGroup.MAINHAND)));
context,
BEHEADING_KEY,
Enchantment.enchantment(
Enchantment.definition(
itemHolderGetter.getOrThrow(ItemTags.SWORDS),
5,
3,
Enchantment.dynamicCost(1, 10),
Enchantment.dynamicCost(15, 10),
2,
EquipmentSlotGroup.MAINHAND
)
)
);
}

public static void register(
BootstrapContext<Enchantment> context, ResourceKey<Enchantment> key, Enchantment.Builder builder) {
BootstrapContext<Enchantment> context, ResourceKey<Enchantment> key, Enchantment.Builder builder) {
context.register(key, builder.build(key.location()));
}
}
Loading

0 comments on commit 5406d6e

Please sign in to comment.