legacy ench

This commit is contained in:
lcy0x1
2024-07-12 19:10:34 +08:00
parent c879440d94
commit ee7d9ccee9
9 changed files with 332 additions and 34 deletions

View File

@@ -18,7 +18,7 @@ loader_version_range=[2,)
mod_id=l2core
mod_name=L2Core
mod_license=LGPL-2.1
mod_version=3.0.5-pre6
mod_version=3.0.5-pre13
mod_group_id=dev.xkmc
mod_authors=lcy0x1
mod_description=Core Library mod for all L2 mods

View File

@@ -6,6 +6,10 @@ import dev.xkmc.l2core.capability.conditionals.ConditionalData;
import dev.xkmc.l2core.capability.conditionals.PlayerFlagData;
import dev.xkmc.l2core.capability.player.PlayerCapabilityNetworkHandler;
import dev.xkmc.l2core.init.reg.datapack.DatapackReg;
import dev.xkmc.l2core.init.reg.ench.EECVal;
import dev.xkmc.l2core.init.reg.ench.EnchReg;
import dev.xkmc.l2core.init.reg.ench.LegacyEnchantment;
import dev.xkmc.l2core.init.reg.registrate.L2Registrate;
import dev.xkmc.l2core.init.reg.simple.*;
import dev.xkmc.l2core.serial.configval.*;
import dev.xkmc.l2core.serial.ingredients.EnchantmentIngredient;
@@ -42,11 +46,11 @@ public class L2LibReg {
public static final AttReg ATTACHMENT = AttReg.of(REG);
public static final AttVal.CapVal<LivingEntity, ClientEffectCap> EFFECT = ATTACHMENT.entity("effect",
ClientEffectCap.class, ClientEffectCap::new, LivingEntity.class, e -> e.level().isClientSide());
ClientEffectCap.class, ClientEffectCap::new, LivingEntity.class, e -> e.level().isClientSide());
public static final AttVal.PlayerVal<ConditionalData> CONDITIONAL = ATTACHMENT.player("conditionals",
ConditionalData.class, ConditionalData::new, PlayerCapabilityNetworkHandler::new);
ConditionalData.class, ConditionalData::new, PlayerCapabilityNetworkHandler::new);
public static final AttVal.PlayerVal<PlayerFlagData> FLAGS = ATTACHMENT.player("flags",
PlayerFlagData.class, PlayerFlagData::new, PlayerCapabilityNetworkHandler::new);
PlayerFlagData.class, PlayerFlagData::new, PlayerCapabilityNetworkHandler::new);
// loot modifiers
public static final CdcReg<IGlobalLootModifier> GLM = CdcReg.of(REG, NeoForgeRegistries.GLOBAL_LOOT_MODIFIER_SERIALIZERS);
@@ -55,11 +59,18 @@ public class L2LibReg {
// loot conditions
public static final SR<LootItemConditionType> LIC = SR.of(REG, BuiltInRegistries.LOOT_CONDITION_TYPE);
public static final Val<LootItemConditionType> LIC_FLAG = LIC.reg("player_flag", () -> new LootItemConditionType(MapCodecAdaptor.of(PlayerFlagCondition.class)));
public static final Val<LootItemConditionType> LIC_FLAG = LIC.reg("player_flag",
() -> new LootItemConditionType(MapCodecAdaptor.of(PlayerFlagCondition.class)));
// datapack
public static final DatapackReg<MenuLayoutConfig> MENU_LAYOUT = REG.dataReg("menu_layout", MenuLayoutConfig.class);
// enchantment
public static final L2Registrate.RegistryInstance<LegacyEnchantment> ENCH =
L2Core.REGISTRATE.newRegistry("legacy_enchantment", LegacyEnchantment.class, e -> e.sync(true));
public static final EECVal.Special<LegacyEnchantment> LEGACY =
EnchReg.of(REG, L2Core.REGISTRATE).special("legacy", ENCH.reg().byNameCodec());
public static void register() {
}

View File

@@ -0,0 +1,123 @@
package dev.xkmc.l2core.init.reg.ench;
import dev.xkmc.l2core.init.reg.simple.Val;
import net.minecraft.core.Holder;
import net.minecraft.core.component.DataComponentType;
import net.minecraft.core.component.DataComponents;
import net.minecraft.core.registries.Registries;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.util.Unit;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.enchantment.ConditionalEffect;
import net.minecraft.world.item.enchantment.Enchantment;
import net.minecraft.world.item.enchantment.EnchantmentHelper;
import net.minecraft.world.item.enchantment.ItemEnchantments;
import net.minecraft.world.item.enchantment.effects.EnchantmentValueEffect;
import net.minecraft.world.level.storage.loot.LootContext;
import net.minecraft.world.level.storage.loot.LootParams;
import net.minecraft.world.level.storage.loot.parameters.LootContextParamSets;
import net.minecraft.world.level.storage.loot.parameters.LootContextParams;
import net.neoforged.neoforge.common.CommonHooks;
import net.neoforged.neoforge.registries.DeferredHolder;
import org.apache.commons.lang3.mutable.MutableFloat;
import java.util.List;
import java.util.Optional;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
public interface EECVal<T> extends Val<DataComponentType<List<ConditionalEffect<T>>>> {
static <T> void apply(List<ConditionalEffect<T>> list, LootContext ctx, Consumer<T> cons) {
for (ConditionalEffect<T> e : list) {
if (e.matches(ctx)) {
cons.accept(e.effect());
}
}
}
static void iterateItem(ItemStack stack, BiConsumer<Holder<Enchantment>, Integer> cons) {
ItemEnchantments enchs = stack.getOrDefault(DataComponents.ENCHANTMENTS, ItemEnchantments.EMPTY);
var lookup = CommonHooks.resolveLookup(Registries.ENCHANTMENT);
if (lookup != null) enchs = stack.getAllEnchantments(lookup);
for (var entry : enchs.entrySet()) {
cons.accept(entry.getKey(), entry.getIntValue());
}
}
static LootContext itemContext(ServerLevel level, int lv, ItemStack stack) {
LootParams lootparams = new LootParams.Builder(level)
.withParameter(LootContextParams.TOOL, stack)
.withParameter(LootContextParams.ENCHANTMENT_LEVEL, lv)
.create(LootContextParamSets.ENCHANTED_ITEM);
return new LootContext.Builder(lootparams).create(Optional.empty());
}
record Impl<T>(
DeferredHolder<DataComponentType<?>, DataComponentType<List<ConditionalEffect<T>>>> val
) implements EECVal<T> {
@Override
public DataComponentType<List<ConditionalEffect<T>>> get() {
return val.get();
}
}
interface Num extends EECVal<EnchantmentValueEffect> {
default float modify(ServerLevel level, ItemStack stack, float f) {
MutableFloat val = new MutableFloat(f);
EECVal.iterateItem(stack, (ench, lv) ->
apply(ench.value().getEffects(get()), itemContext(level, lv, stack),
eff -> val.setValue(eff.process(lv, level.getRandom(), val.getValue()))));
return val.getValue();
}
record Impl(
DeferredHolder<DataComponentType<?>, DataComponentType<List<ConditionalEffect<EnchantmentValueEffect>>>> val
) implements Num {
@Override
public DataComponentType<List<ConditionalEffect<EnchantmentValueEffect>>> get() {
return val.get();
}
}
}
interface Flag extends Val<DataComponentType<Unit>> {
default boolean isOn(ItemStack stack) {
return EnchantmentHelper.has(stack, get());
}
record Impl<T>(
DeferredHolder<DataComponentType<?>, DataComponentType<Unit>> val
) implements Flag {
@Override
public DataComponentType<Unit> get() {
return val.get();
}
}
}
interface Special<T> extends Val<DataComponentType<T>> {
record Impl<T>(
DeferredHolder<DataComponentType<?>, DataComponentType<T>> val
) implements Special<T> {
@Override
public DataComponentType<T> get() {
return val.get();
}
}
}
}

View File

@@ -1,10 +1,8 @@
package dev.xkmc.l2core.init.reg.datapack;
package dev.xkmc.l2core.init.reg.ench;
import com.mojang.serialization.Codec;
import cpw.mods.util.Lazy;
import dev.xkmc.l2core.init.reg.registrate.L2Registrate;
import dev.xkmc.l2core.init.reg.simple.DCReg;
import dev.xkmc.l2core.init.reg.simple.DCVal;
import dev.xkmc.l2core.init.reg.simple.Reg;
import net.minecraft.core.HolderLookup;
import net.minecraft.core.component.DataComponentType;
@@ -15,8 +13,12 @@ import net.minecraft.data.worldgen.BootstrapContext;
import net.minecraft.resources.ResourceKey;
import net.minecraft.tags.TagKey;
import net.minecraft.util.Unit;
import net.minecraft.world.item.enchantment.ConditionalEffect;
import net.minecraft.world.item.enchantment.Enchantment;
import net.minecraft.world.item.enchantment.effects.EnchantmentValueEffect;
import net.minecraft.world.level.storage.loot.parameters.LootContextParamSet;
import net.minecraft.world.level.storage.loot.parameters.LootContextParamSets;
import net.neoforged.neoforge.registries.DeferredHolder;
import net.neoforged.neoforge.registries.DeferredRegister;
import java.util.ArrayList;
@@ -40,23 +42,34 @@ public class EnchReg {
this.pvd = pvd;
}
public <T> DCVal<T> reg(String id, Codec<T> codec) {
return new DCReg.DCValImpl<>(reg.register(id, () -> DataComponentType.<T>builder().persistent(codec).build()));
private <T> DeferredHolder<DataComponentType<?>, DataComponentType<T>> reg(String id, Codec<T> codec) {
return reg.register(id, () -> DataComponentType.<T>builder().persistent(codec).build());
}
public DCVal<Unit> unit(String id) {
return reg(id, Unit.CODEC);
public EECVal.Flag unit(String id) {
return new EECVal.Flag.Impl<>(reg(id, Unit.CODEC));
}
public DCVal<EnchantmentValueEffect> val(String id) {
return reg(id, EnchantmentValueEffect.CODEC);
public <T> EECVal.Special<T> special(String id, Codec<T> codec) {
return new EECVal.Special.Impl<>(reg(id, codec));
}
public <T> EECVal<T> eff(String id, Codec<T> codec, LootContextParamSet loot) {
return new EECVal.Impl<>(reg(id, ConditionalEffect.codec(codec, loot).listOf()));
}
public EECVal.Num val(String id) {
return new EECVal.Num.Impl(reg(id, ConditionalEffect.codec(
EnchantmentValueEffect.CODEC,
LootContextParamSets.ENCHANTED_ITEM
).listOf()));
}
public EnchVal ench(String id, String name, String desc, UnaryOperator<EnchVal.Builder> cons) {
var key = ResourceKey.create(Registries.ENCHANTMENT, pvd.loc(id));
pvd.addRawLang("enchantment." + pvd.getModid() + "." + id, name);
pvd.addRawLang("enchantment." + pvd.getModid() + "." + id + ".desc", desc);
var ans = new EnchVal.Simple(key, Lazy.of(() -> cons.apply(new EnchVal.Builder())));
var ans = new EnchVal.Simple(key, Lazy.of(() -> cons.apply(new EnchVal.Builder(key.location()))));
list.add(ans);
return ans;
}
@@ -66,7 +79,7 @@ public class EnchReg {
pvd.addRawLang("enchantment." + pvd.getModid() + "." + id, name);
pvd.addRawLang("enchantment." + pvd.getModid() + "." + id + ".desc", desc);
var unit = unit(id);
var ans = new EnchVal.FlagImpl(unit, key, Lazy.of(() -> cons.apply(new EnchVal.Builder().effect(e -> e.withEffect(unit.get())))));
var ans = new EnchVal.FlagImpl(unit, key, Lazy.of(() -> cons.apply(new EnchVal.Builder(key.location()).effect(e -> e.withEffect(unit.get())))));
list.add(ans);
return ans;
}

View File

@@ -1,60 +1,81 @@
package dev.xkmc.l2core.init.reg.datapack;
package dev.xkmc.l2core.init.reg.ench;
import cpw.mods.util.Lazy;
import dev.xkmc.l2core.init.reg.simple.DCVal;
import net.minecraft.core.Holder;
import net.minecraft.core.component.DataComponents;
import net.minecraft.core.registries.Registries;
import net.minecraft.data.worldgen.BootstrapContext;
import net.minecraft.resources.ResourceKey;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.tags.TagKey;
import net.minecraft.util.Unit;
import net.minecraft.world.entity.EquipmentSlotGroup;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.enchantment.Enchantment;
import net.minecraft.world.item.enchantment.ItemEnchantments;
import net.neoforged.neoforge.common.CommonHooks;
import net.neoforged.neoforge.common.Tags;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.function.Consumer;
import java.util.function.UnaryOperator;
@SuppressWarnings("unused")
public interface EnchVal {
ResourceKey<Enchantment> id();
default Holder<Enchantment> holder() {
return Optional.ofNullable(CommonHooks.resolveLookup(Registries.ENCHANTMENT)).orElseThrow().getOrThrow(id());
}
default int getLv(ItemStack stack) {
return stack.getEnchantmentLevel(holder());
}
default int getLvIntrinsic(ItemStack stack) {
return stack.getOrDefault(DataComponents.ENCHANTMENTS, ItemEnchantments.EMPTY).getLevel(holder());
}
interface Impl extends EnchVal {
Lazy<Builder> builder();
}
interface Flag extends EnchVal {
DCVal<Unit> unit();
EECVal.Flag unit();
}
record Simple(ResourceKey<Enchantment> id, Lazy<Builder> builder) implements Impl {
}
record FlagImpl(DCVal<Unit> unit, ResourceKey<Enchantment> id, Lazy<Builder> builder) implements Flag, Impl {
record FlagImpl(EECVal.Flag unit, ResourceKey<Enchantment> id, Lazy<Builder> builder) implements Flag, Impl {
}
class Builder {
private TagKey<Item> supported, primary;
private HolderSetBuilder<Item> supported, primary;
private Enchantment.Cost min, max;
@Nullable
private EquipmentSlotGroup group;
private int weight = 1, maxLevel = 1, anvilCost = 1;
@Nullable
private TagKey<Enchantment> exclude;
private HolderSetBuilder<Enchantment> exclude;
private final List<Consumer<Enchantment.Builder>> effects = new ArrayList<>();
public final ResourceLocation id;
final List<TagKey<Enchantment>> tags = new ArrayList<>();
Builder() {
supported = primary = Tags.Items.ENCHANTABLES;
Builder(ResourceLocation id) {
this.id = id;
supported = primary = new HolderSetBuilder.Simple<>(Tags.Items.ENCHANTABLES);
min = max = new Enchantment.Cost(10, 5);
group = EquipmentSlotGroup.ANY;
group = null;
}
public Builder transform(UnaryOperator<Builder> func) {
@@ -66,6 +87,16 @@ public interface EnchVal {
}
public Builder items(TagKey<Item> supported, TagKey<Item> primary) {
this.supported = new HolderSetBuilder.Simple<>(supported);
this.primary = new HolderSetBuilder.Simple<>(primary);
return this;
}
public Builder items(HolderSetBuilder<Item> items) {
return items(items, items);
}
public Builder items(HolderSetBuilder<Item> supported, HolderSetBuilder<Item> primary) {
this.supported = supported;
this.primary = primary;
return this;
@@ -98,7 +129,17 @@ public interface EnchVal {
}
public Builder exclusive(TagKey<Enchantment> tag) {
this.exclude = tag;
this.exclude = HolderSetBuilder.tag(tag);
return this;
}
public Builder exclusive(ResourceKey<Enchantment> key) {
this.exclude = HolderSetBuilder.direct(key);
return this;
}
public Builder exclusive(HolderSetBuilder<Enchantment> set) {
this.exclude = set;
return this;
}
@@ -116,12 +157,11 @@ public interface EnchVal {
Enchantment build(BootstrapContext<Enchantment> ctx, ResourceLocation id) {
var items = ctx.registryLookup(Registries.ITEM).orElseThrow();
var enchs = ctx.registryLookup(Registries.ENCHANTMENT).orElseThrow();
var ans = Enchantment.enchantment(Enchantment.definition(
items.getOrThrow(supported),
items.getOrThrow(primary),
weight, maxLevel,
min, max, anvilCost, group));
if (exclude != null) ans.exclusiveWith(enchs.getOrThrow(exclude));
var ans = Enchantment.enchantment(new Enchantment.EnchantmentDefinition(
supported.build(items), Optional.of(primary.build(items)),
weight, maxLevel, min, max, anvilCost,
group == null ? List.of() : List.of(group)));
if (exclude != null) ans.exclusiveWith(exclude.build(enchs));
for (var e : effects) e.accept(ans);
return ans.build(id);
}

View File

@@ -0,0 +1,96 @@
package dev.xkmc.l2core.init.reg.ench;
import net.minecraft.core.HolderLookup;
import net.minecraft.core.HolderSet;
import net.minecraft.resources.ResourceKey;
import net.minecraft.tags.TagKey;
import net.neoforged.neoforge.registries.holdersets.AndHolderSet;
import net.neoforged.neoforge.registries.holdersets.AnyHolderSet;
import net.neoforged.neoforge.registries.holdersets.NotHolderSet;
import net.neoforged.neoforge.registries.holdersets.OrHolderSet;
import java.util.List;
public interface HolderSetBuilder<T> {
static <T> HolderSetBuilder<T> tag(TagKey<T> tag) {
return new Simple<>(tag);
}
static <T> HolderSetBuilder<T> direct(ResourceKey<T> tag) {
return new Direct<>(tag);
}
static <T> HolderSetBuilder<T> or(List<HolderSetBuilder<T>> tag) {
return new Or<>(tag);
}
static <T> HolderSetBuilder<T> and(List<HolderSetBuilder<T>> tag) {
return new And<>(tag);
}
static <T> HolderSetBuilder<T> not(HolderSetBuilder<T> tag) {
return new Not<>(tag);
}
static <T> HolderSetBuilder<T> any() {
return new Any<>();
}
HolderSet<T> build(HolderLookup.RegistryLookup<T> pvd);
record Simple<T>(TagKey<T> tag) implements HolderSetBuilder<T> {
@Override
public HolderSet<T> build(HolderLookup.RegistryLookup<T> pvd) {
return pvd.getOrThrow(tag);
}
}
record Direct<T>(ResourceKey<T> key) implements HolderSetBuilder<T> {
@Override
public HolderSet<T> build(HolderLookup.RegistryLookup<T> pvd) {
return HolderSet.direct(pvd.getOrThrow(key));
}
}
record Or<T>(List<HolderSetBuilder<T>> list) implements HolderSetBuilder<T> {
@Override
public HolderSet<T> build(HolderLookup.RegistryLookup<T> pvd) {
return new OrHolderSet<>(list.stream().map(e -> e.build(pvd)).toList());
}
}
record And<T>(List<HolderSetBuilder<T>> list) implements HolderSetBuilder<T> {
@Override
public HolderSet<T> build(HolderLookup.RegistryLookup<T> pvd) {
return new AndHolderSet<>(list.stream().map(e -> e.build(pvd)).toList());
}
}
record Not<T>(HolderSetBuilder<T> val) implements HolderSetBuilder<T> {
@Override
public HolderSet<T> build(HolderLookup.RegistryLookup<T> pvd) {
return new NotHolderSet<>(pvd, val.build(pvd));
}
}
record Any<T>() implements HolderSetBuilder<T> {
@Override
public HolderSet<T> build(HolderLookup.RegistryLookup<T> pvd) {
return new AnyHolderSet<>(pvd);
}
}
}

View File

@@ -0,0 +1,7 @@
package dev.xkmc.l2core.init.reg.ench;
public class LegacyEnchantment {
}

View File

@@ -0,0 +1,8 @@
@MethodsReturnNonnullByDefault
@ParametersAreNonnullByDefault
package dev.xkmc.l2core.init.reg.ench;
import net.minecraft.MethodsReturnNonnullByDefault;
import javax.annotation.ParametersAreNonnullByDefault;

View File

@@ -64,7 +64,7 @@ public record DCReg(DeferredRegister<DataComponentType<?>> reg) {
return reg(id, ComponentSerialization.CODEC, ComponentSerialization.STREAM_CODEC, true);
}
public record DCValImpl<T>(DeferredHolder<DataComponentType<?>, DataComponentType<T>> val) implements DCVal<T> {
private record DCValImpl<T>(DeferredHolder<DataComponentType<?>, DataComponentType<T>> val) implements DCVal<T> {
@Override
public DataComponentType<T> get() {