From 759246396007c92527a8cce257bd627020ea9c3d Mon Sep 17 00:00:00 2001 From: lcy0x1 Date: Thu, 27 Jun 2024 19:08:12 +0800 Subject: [PATCH] configs --- .../attachment/GeneralCapabilityHolder.java | 47 ++-- .../conditionals/ClientDataHandler.java | 2 +- .../conditionals/PlayerFlagData.java | 52 ++-- .../PlayerCapabilityNetworkHandler.java | 29 ++- .../l2core/events/BaseCapabilityEvents.java | 6 +- .../events/ClientEffectRenderEvents.java | 246 +++++++++--------- .../java/dev/xkmc/l2core/init/L2LibReg.java | 67 +++-- .../conditions/BooleanValueCondition.java | 31 --- .../conditions/DoubleValueCondition.java | 31 --- .../conditions/ListStringValueCondition.java | 32 --- .../conditions/StringValueCondition.java | 31 --- .../configval/AbstractConfigParser.java | 15 ++ .../serial/configval/BooleanConfigValue.java | 45 ++++ .../configval/BooleanValueCondition.java | 27 ++ .../serial/configval/DoubleConfigValue.java | 46 ++++ .../configval/DoubleValueCondition.java | 27 ++ .../serial/configval/IntConfigValue.java | 45 ++++ .../IntValueCondition.java | 12 +- .../configval/ListStringValueCondition.java | 28 ++ .../configval/StringValueCondition.java | 27 ++ .../package-info.java | 2 +- .../l2core/serial/loot/AddItemModifier.java | 74 ++++++ .../serial/loot/AddLootTableModifier.java | 52 ++++ .../serial/loot/PlayerFlagCondition.java | 38 +++ .../xkmc/l2core/serial/loot/package-info.java | 8 + 25 files changed, 672 insertions(+), 348 deletions(-) delete mode 100644 src/main/java/dev/xkmc/l2core/serial/conditions/BooleanValueCondition.java delete mode 100644 src/main/java/dev/xkmc/l2core/serial/conditions/DoubleValueCondition.java delete mode 100644 src/main/java/dev/xkmc/l2core/serial/conditions/ListStringValueCondition.java delete mode 100644 src/main/java/dev/xkmc/l2core/serial/conditions/StringValueCondition.java create mode 100644 src/main/java/dev/xkmc/l2core/serial/configval/AbstractConfigParser.java create mode 100644 src/main/java/dev/xkmc/l2core/serial/configval/BooleanConfigValue.java create mode 100644 src/main/java/dev/xkmc/l2core/serial/configval/BooleanValueCondition.java create mode 100644 src/main/java/dev/xkmc/l2core/serial/configval/DoubleConfigValue.java create mode 100644 src/main/java/dev/xkmc/l2core/serial/configval/DoubleValueCondition.java create mode 100644 src/main/java/dev/xkmc/l2core/serial/configval/IntConfigValue.java rename src/main/java/dev/xkmc/l2core/serial/{conditions => configval}/IntValueCondition.java (62%) create mode 100644 src/main/java/dev/xkmc/l2core/serial/configval/ListStringValueCondition.java create mode 100644 src/main/java/dev/xkmc/l2core/serial/configval/StringValueCondition.java rename src/main/java/dev/xkmc/l2core/serial/{conditions => configval}/package-info.java (79%) create mode 100644 src/main/java/dev/xkmc/l2core/serial/loot/AddItemModifier.java create mode 100644 src/main/java/dev/xkmc/l2core/serial/loot/AddLootTableModifier.java create mode 100644 src/main/java/dev/xkmc/l2core/serial/loot/PlayerFlagCondition.java create mode 100644 src/main/java/dev/xkmc/l2core/serial/loot/package-info.java diff --git a/src/main/java/dev/xkmc/l2core/capability/attachment/GeneralCapabilityHolder.java b/src/main/java/dev/xkmc/l2core/capability/attachment/GeneralCapabilityHolder.java index b206ca8..61a0888 100644 --- a/src/main/java/dev/xkmc/l2core/capability/attachment/GeneralCapabilityHolder.java +++ b/src/main/java/dev/xkmc/l2core/capability/attachment/GeneralCapabilityHolder.java @@ -5,6 +5,7 @@ import net.minecraft.resources.ResourceLocation; import net.neoforged.neoforge.attachment.IAttachmentHolder; import java.util.Map; +import java.util.Optional; import java.util.concurrent.ConcurrentHashMap; import java.util.function.Predicate; import java.util.function.Supplier; @@ -14,32 +15,36 @@ import java.util.function.Supplier; */ public class GeneralCapabilityHolder> extends AttachmentDef { - public static final Map> INTERNAL_MAP = new ConcurrentHashMap<>(); + public static final Map> INTERNAL_MAP = new ConcurrentHashMap<>(); - public final ResourceLocation id; - public final Class entity_class; - private final Predicate pred; + public final ResourceLocation id; + public final Class entity_class; + private final Predicate pred; - public GeneralCapabilityHolder(ResourceLocation id, Class holder_class, Supplier sup, - Class entity_class, Predicate pred) { - super(holder_class, sup); - this.id = id; - this.entity_class = entity_class; - this.pred = pred; - INTERNAL_MAP.put(id, this); - } + public GeneralCapabilityHolder(ResourceLocation id, Class holder_class, Supplier sup, + Class entity_class, Predicate pred) { + super(holder_class, sup); + this.id = id; + this.entity_class = entity_class; + this.pred = pred; + INTERNAL_MAP.put(id, this); + } - public T get(E e) { - return e.getData(type()); - } + public T getOrCreate(E e) { + return e.getData(type()); + } - public boolean isFor(IAttachmentHolder holder) { - return entity_class.isInstance(holder) && isProper(Wrappers.cast(holder)); - } + public Optional getExisting(E e) { + return e.getExistingData(type()); + } - public boolean isProper(E entity) { - return pred.test(entity); - } + public boolean isFor(IAttachmentHolder holder) { + return entity_class.isInstance(holder) && isProper(Wrappers.cast(holder)); + } + + public boolean isProper(E entity) { + return pred.test(entity); + } } diff --git a/src/main/java/dev/xkmc/l2core/capability/conditionals/ClientDataHandler.java b/src/main/java/dev/xkmc/l2core/capability/conditionals/ClientDataHandler.java index 9858000..aeab3b9 100644 --- a/src/main/java/dev/xkmc/l2core/capability/conditionals/ClientDataHandler.java +++ b/src/main/java/dev/xkmc/l2core/capability/conditionals/ClientDataHandler.java @@ -10,7 +10,7 @@ public class ClientDataHandler { public static void handle(TokenKey key, T token) { Player player = Proxy.getClientPlayer(); if (player == null) return; - ConditionalToken old = L2LibReg.CONDITIONAL.type().get(player).data.put(key, token); + ConditionalToken old = L2LibReg.CONDITIONAL.type().getOrCreate(player).data.put(key, token); if (token instanceof NetworkSensitiveToken t) { t.onSync(Wrappers.cast(old), player); } diff --git a/src/main/java/dev/xkmc/l2core/capability/conditionals/PlayerFlagData.java b/src/main/java/dev/xkmc/l2core/capability/conditionals/PlayerFlagData.java index 8220f26..ddd0909 100644 --- a/src/main/java/dev/xkmc/l2core/capability/conditionals/PlayerFlagData.java +++ b/src/main/java/dev/xkmc/l2core/capability/conditionals/PlayerFlagData.java @@ -13,37 +13,37 @@ import java.util.TreeSet; @SerialClass public class PlayerFlagData extends PlayerCapabilityTemplate { - public static void addFlag(LivingEntity entity, String str) { - if (entity instanceof Player player) { - L2LibReg.FLAGS.type().get(player).addFlag(str); - if (player instanceof ServerPlayer sp) - L2LibReg.FLAGS.type().network.toClient(sp); - } else { - entity.addTag(str); - } - } + public static void addFlag(LivingEntity entity, String str) { + if (entity instanceof Player player) { + L2LibReg.FLAGS.type().getOrCreate(player).addFlag(str); + if (player instanceof ServerPlayer sp) + L2LibReg.FLAGS.type().network.toClient(sp); + } else { + entity.addTag(str); + } + } - public static boolean hasFlag(LivingEntity entity, String str) { - if (entity instanceof Player player) { - return L2LibReg.FLAGS.type().get(player).hasFlag(str); - } else { - return entity.getTags().contains(str); - } - } + public static boolean hasFlag(LivingEntity entity, String str) { + if (entity instanceof Player player) { + return L2LibReg.FLAGS.type().getExisting(player).map(e -> e.hasFlag(str)).orElse(false); + } else { + return entity.getTags().contains(str); + } + } - @SerialField - private final TreeSet flags = new TreeSet<>(); + @SerialField + private final TreeSet flags = new TreeSet<>(); - public void addFlag(String str) { - flags.add(str); - } + public void addFlag(String str) { + flags.add(str); + } - public boolean hasFlag(String flag) { - return flags.contains(flag); - } + public boolean hasFlag(String flag) { + return flags.contains(flag); + } - public static void register() { + public static void register() { - } + } } diff --git a/src/main/java/dev/xkmc/l2core/capability/player/PlayerCapabilityNetworkHandler.java b/src/main/java/dev/xkmc/l2core/capability/player/PlayerCapabilityNetworkHandler.java index dd972d9..cd41289 100644 --- a/src/main/java/dev/xkmc/l2core/capability/player/PlayerCapabilityNetworkHandler.java +++ b/src/main/java/dev/xkmc/l2core/capability/player/PlayerCapabilityNetworkHandler.java @@ -5,22 +5,25 @@ import net.minecraft.server.level.ServerPlayer; public class PlayerCapabilityNetworkHandler> { - public final PlayerCapabilityHolder holder; + public final PlayerCapabilityHolder holder; - public PlayerCapabilityNetworkHandler(PlayerCapabilityHolder holder) { - this.holder = holder; - } + public PlayerCapabilityNetworkHandler(PlayerCapabilityHolder holder) { + this.holder = holder; + } - public void toClient(ServerPlayer e) { - L2Core.PACKET_HANDLER.toClientPlayer(PlayerCapToClient.of(e, PlayerCapToClient.Action.CLIENT, holder, holder.get(e)), e); - } + public void toClient(ServerPlayer e) { + holder.getExisting(e).ifPresent(x -> L2Core.PACKET_HANDLER.toClientPlayer( + PlayerCapToClient.of(e, PlayerCapToClient.Action.CLIENT, holder, x), e)); + } - public void toTracking(ServerPlayer e) { - L2Core.PACKET_HANDLER.toTrackingOnly(PlayerCapToClient.of(e, PlayerCapToClient.Action.TRACK, holder, holder.get(e)), e); - } + public void toTracking(ServerPlayer e) { + holder.getExisting(e).ifPresent(x -> L2Core.PACKET_HANDLER.toTrackingOnly( + PlayerCapToClient.of(e, PlayerCapToClient.Action.TRACK, holder, x), e)); + } - public void startTracking(ServerPlayer tracker, ServerPlayer target) { - L2Core.PACKET_HANDLER.toClientPlayer(PlayerCapToClient.of(target, PlayerCapToClient.Action.TRACK, holder, holder.get(target)), tracker); - } + public void startTracking(ServerPlayer tracker, ServerPlayer target) { + holder.getExisting(target).ifPresent(x -> L2Core.PACKET_HANDLER.toClientPlayer( + PlayerCapToClient.of(target, PlayerCapToClient.Action.TRACK, holder, x), tracker)); + } } diff --git a/src/main/java/dev/xkmc/l2core/events/BaseCapabilityEvents.java b/src/main/java/dev/xkmc/l2core/events/BaseCapabilityEvents.java index 869828a..86244af 100644 --- a/src/main/java/dev/xkmc/l2core/events/BaseCapabilityEvents.java +++ b/src/main/java/dev/xkmc/l2core/events/BaseCapabilityEvents.java @@ -20,7 +20,7 @@ public class BaseCapabilityEvents { if (event.getEntity() instanceof LivingEntity le && le.isAlive()) { for (GeneralCapabilityHolder holder : GeneralCapabilityHolder.INTERNAL_MAP.values()) { if (holder.isFor(event.getEntity())) - holder.get(Wrappers.cast(event.getEntity())).tick(Wrappers.cast(event.getEntity())); + holder.getOrCreate(Wrappers.cast(event.getEntity())).tick(Wrappers.cast(event.getEntity())); } } } @@ -29,7 +29,7 @@ public class BaseCapabilityEvents { public static void onPlayerClone(PlayerEvent.Clone event) { for (PlayerCapabilityHolder holder : PlayerCapabilityHolder.INTERNAL_MAP.values()) { ServerPlayer e = (ServerPlayer) event.getEntity(); - holder.get(e).onClone(e, event.isWasDeath()); + holder.getOrCreate(e).onClone(e, event.isWasDeath()); holder.network.toClient(e); holder.network.toTracking(e); } @@ -40,7 +40,7 @@ public class BaseCapabilityEvents { ServerPlayer e = (ServerPlayer) event.getEntity(); if (e == null) return; for (PlayerCapabilityHolder holder : PlayerCapabilityHolder.INTERNAL_MAP.values()) { - holder.get(e).init(e); + holder.getOrCreate(e).init(e); holder.network.toClient(e); holder.network.toTracking(e); } diff --git a/src/main/java/dev/xkmc/l2core/events/ClientEffectRenderEvents.java b/src/main/java/dev/xkmc/l2core/events/ClientEffectRenderEvents.java index a7d2ffa..703c480 100644 --- a/src/main/java/dev/xkmc/l2core/events/ClientEffectRenderEvents.java +++ b/src/main/java/dev/xkmc/l2core/events/ClientEffectRenderEvents.java @@ -24,7 +24,6 @@ import net.minecraft.client.renderer.RenderType; import net.minecraft.client.renderer.entity.EntityRenderDispatcher; import net.minecraft.resources.ResourceLocation; import net.minecraft.util.Mth; -import net.minecraft.world.effect.MobEffect; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.phys.Vec3; @@ -37,149 +36,148 @@ import net.neoforged.neoforge.client.event.RenderLivingEvent; import java.util.ArrayList; import java.util.List; -import java.util.Map; @EventBusSubscriber(value = Dist.CLIENT, modid = L2Core.MODID, bus = EventBusSubscriber.Bus.GAME) public class ClientEffectRenderEvents { - private static final ArrayList ICONS = new ArrayList<>(); + private static final ArrayList ICONS = new ArrayList<>(); - @SubscribeEvent - public static void clientTick(ClientTickEvent.Post event) { - AbstractClientPlayer player = Proxy.getClientPlayer(); - if (player != null) { - for (var entry : player.getActiveEffectsMap().entrySet()) { - if (entry.getKey() instanceof FirstPlayerRenderEffect effect) { - effect.onClientLevelRender(player, entry.getValue()); - } - } - } - } + @SubscribeEvent + public static void clientTick(ClientTickEvent.Post event) { + AbstractClientPlayer player = Proxy.getClientPlayer(); + if (player != null) { + for (var entry : player.getActiveEffectsMap().entrySet()) { + if (entry.getKey() instanceof FirstPlayerRenderEffect effect) { + effect.onClientLevelRender(player, entry.getValue()); + } + } + } + } - @SubscribeEvent - public static void levelRenderLast(RenderLevelStageEvent event) { - if (event.getStage() != RenderLevelStageEvent.Stage.AFTER_WEATHER) return; - LevelRenderer renderer = event.getLevelRenderer(); - MultiBufferSource.BufferSource buffers = Minecraft.getInstance().renderBuffers().bufferSource(); - Camera camera = Minecraft.getInstance().gameRenderer.getMainCamera(); - PoseStack stack = event.getPoseStack(); + @SubscribeEvent + public static void levelRenderLast(RenderLevelStageEvent event) { + if (event.getStage() != RenderLevelStageEvent.Stage.AFTER_WEATHER) return; + LevelRenderer renderer = event.getLevelRenderer(); + MultiBufferSource.BufferSource buffers = Minecraft.getInstance().renderBuffers().bufferSource(); + Camera camera = Minecraft.getInstance().gameRenderer.getMainCamera(); + PoseStack stack = event.getPoseStack(); - // cache the previous handler - for (DelayedEntityRender icon : ICONS) { - renderIcon(stack, buffers, icon, event.getPartialTick().getGameTimeDeltaTicks(), camera, renderer.entityRenderDispatcher); - } - buffers.endBatch(); + // cache the previous handler + for (DelayedEntityRender icon : ICONS) { + renderIcon(stack, buffers, icon, event.getPartialTick().getGameTimeDeltaTicks(), camera, renderer.entityRenderDispatcher); + } + buffers.endBatch(); - ICONS.clear(); - } + ICONS.clear(); + } - @SubscribeEvent - public static void onLivingEntityRender(RenderLivingEvent.Post event) { - LivingEntity entity = event.getEntity(); - if (!L2LibReg.EFFECT.type().isProper(entity)) return; - if (entity.getTags().contains("ClientOnly")) return;//TODO - ClientEffectCap cap = L2LibReg.EFFECT.type().get(entity); - List> l0 = new ArrayList<>(); - for (var entry : cap.map.entrySet()) { - if (entry.getKey().value() instanceof ClientRenderEffect effect) { - l0.add(Pair.of(effect, entry.getValue())); - } - } - if (l0.isEmpty()) return; - List> l1 = new ArrayList<>(); - int index = 0; + @SubscribeEvent + public static void onLivingEntityRender(RenderLivingEvent.Post event) { + LivingEntity entity = event.getEntity(); + if (!L2LibReg.EFFECT.type().isProper(entity)) return; + if (entity.getTags().contains("ClientOnly")) return;//TODO + ClientEffectCap cap = L2LibReg.EFFECT.type().getOrCreate(entity); + List> l0 = new ArrayList<>(); + for (var entry : cap.map.entrySet()) { + if (entry.getKey().value() instanceof ClientRenderEffect effect) { + l0.add(Pair.of(effect, entry.getValue())); + } + } + if (l0.isEmpty()) return; + List> l1 = new ArrayList<>(); + int index = 0; - for (var e : l0) { - int lv = e.getSecond(); - int size = l1.size(); - int I = index; - e.getFirst().render(entity, lv, x -> l1.add(Pair.of(I, x))); - if (l1.size() > size) { - index++; - } - } + for (var e : l0) { + int lv = e.getSecond(); + int size = l1.size(); + int I = index; + e.getFirst().render(entity, lv, x -> l1.add(Pair.of(I, x))); + if (l1.size() > size) { + index++; + } + } - int n = index; - int w = (int) Math.ceil(Math.sqrt(n)); - int h = (int) Math.ceil(n * 1d / w); + int n = index; + int w = (int) Math.ceil(Math.sqrt(n)); + int h = (int) Math.ceil(n * 1d / w); - for (var e : l1) { - int i = e.getFirst(); - int iy = i / w; - int iw = Math.min(w, n - iy * w); - int ix = i - iy * w; - ICONS.add(e.getSecond().resize(IconRenderRegion.of(w, ix, iy, iw, h))); - } + for (var e : l1) { + int i = e.getFirst(); + int iy = i / w; + int iw = Math.min(w, n - iy * w); + int ix = i - iy * w; + ICONS.add(e.getSecond().resize(IconRenderRegion.of(w, ix, iy, iw, h))); + } - } + } - private static void renderIcon(PoseStack pose, MultiBufferSource buffer, DelayedEntityRender icon, - float partial, Camera camera, EntityRenderDispatcher dispatcher) { - LivingEntity entity = icon.entity(); - float f = entity.getBbHeight() / 2; + private static void renderIcon(PoseStack pose, MultiBufferSource buffer, DelayedEntityRender icon, + float partial, Camera camera, EntityRenderDispatcher dispatcher) { + LivingEntity entity = icon.entity(); + float f = entity.getBbHeight() / 2; - double x0 = Mth.lerp(partial, entity.xOld, entity.getX()); - double y0 = Mth.lerp(partial, entity.yOld, entity.getY()); - double z0 = Mth.lerp(partial, entity.zOld, entity.getZ()); - Vec3 offset = dispatcher.getRenderer(entity).getRenderOffset(entity, partial); - Vec3 cam_pos = camera.getPosition(); - double d2 = x0 - cam_pos.x + offset.x(); - double d3 = y0 - cam_pos.y + offset.y(); - double d0 = z0 - cam_pos.z + offset.z(); + double x0 = Mth.lerp(partial, entity.xOld, entity.getX()); + double y0 = Mth.lerp(partial, entity.yOld, entity.getY()); + double z0 = Mth.lerp(partial, entity.zOld, entity.getZ()); + Vec3 offset = dispatcher.getRenderer(entity).getRenderOffset(entity, partial); + Vec3 cam_pos = camera.getPosition(); + double d2 = x0 - cam_pos.x + offset.x(); + double d3 = y0 - cam_pos.y + offset.y(); + double d0 = z0 - cam_pos.z + offset.z(); - pose.pushPose(); - pose.translate(d2, d3 + f, d0); - pose.mulPose(camera.rotation()); - PoseStack.Pose entry = pose.last(); - VertexConsumer ivertexbuilder = buffer.getBuffer(get2DIcon(icon.rl())); + pose.pushPose(); + pose.translate(d2, d3 + f, d0); + pose.mulPose(camera.rotation()); + PoseStack.Pose entry = pose.last(); + VertexConsumer ivertexbuilder = buffer.getBuffer(get2DIcon(icon.rl())); - float ix0 = -0.5f + icon.region().x(); - float ix1 = ix0 + icon.region().scale(); - float iy0 = -0.5f + icon.region().y(); - float iy1 = iy0 + icon.region().scale(); - float u0 = icon.tx(); - float v0 = icon.ty(); - float u1 = icon.tx() + icon.tw(); - float v1 = icon.ty() + icon.th(); + float ix0 = -0.5f + icon.region().x(); + float ix1 = ix0 + icon.region().scale(); + float iy0 = -0.5f + icon.region().y(); + float iy1 = iy0 + icon.region().scale(); + float u0 = icon.tx(); + float v0 = icon.ty(); + float u1 = icon.tx() + icon.tw(); + float v1 = icon.ty() + icon.th(); - iconVertex(entry, ivertexbuilder, ix1, iy0, u0, v1); - iconVertex(entry, ivertexbuilder, ix0, iy0, u1, v1); - iconVertex(entry, ivertexbuilder, ix0, iy1, u1, v0); - iconVertex(entry, ivertexbuilder, ix1, iy1, u0, v0); - pose.popPose(); - } + iconVertex(entry, ivertexbuilder, ix1, iy0, u0, v1); + iconVertex(entry, ivertexbuilder, ix0, iy0, u1, v1); + iconVertex(entry, ivertexbuilder, ix0, iy1, u1, v0); + iconVertex(entry, ivertexbuilder, ix1, iy1, u0, v0); + pose.popPose(); + } - private static void iconVertex(PoseStack.Pose entry, VertexConsumer builder, float x, float y, float u, float v) { - builder.addVertex(entry.pose(), x, y, 0) - .setUv(u, v) - .setNormal(entry, 0.0F, 1.0F, 0.0F); - } + private static void iconVertex(PoseStack.Pose entry, VertexConsumer builder, float x, float y, float u, float v) { + builder.addVertex(entry.pose(), x, y, 0) + .setUv(u, v) + .setNormal(entry, 0.0F, 1.0F, 0.0F); + } - public static RenderType get2DIcon(ResourceLocation rl) { - return RenderType.create( - "entity_body_icon", - DefaultVertexFormat.POSITION_TEX, - VertexFormat.Mode.QUADS, 256, false, true, - RenderType.CompositeState.builder() - .setShaderState(RenderStateShard.RENDERTYPE_ENTITY_GLINT_SHADER) - .setTextureState(new RenderStateShard.TextureStateShard(rl, false, false)) - .setTransparencyState(RenderStateShard.ADDITIVE_TRANSPARENCY) - .setDepthTestState(RenderStateShard.NO_DEPTH_TEST) - .createCompositeState(false) - ); - } + public static RenderType get2DIcon(ResourceLocation rl) { + return RenderType.create( + "entity_body_icon", + DefaultVertexFormat.POSITION_TEX, + VertexFormat.Mode.QUADS, 256, false, true, + RenderType.CompositeState.builder() + .setShaderState(RenderStateShard.RENDERTYPE_ENTITY_GLINT_SHADER) + .setTextureState(new RenderStateShard.TextureStateShard(rl, false, false)) + .setTransparencyState(RenderStateShard.ADDITIVE_TRANSPARENCY) + .setDepthTestState(RenderStateShard.NO_DEPTH_TEST) + .createCompositeState(false) + ); + } - public static void sync(EffectToClient eff) { - if (Minecraft.getInstance().level == null) return; - Entity e = Minecraft.getInstance().level.getEntity(eff.entity()); - if (!(e instanceof LivingEntity le)) return; - if (!L2LibReg.EFFECT.type().isProper(le)) return; - ClientEffectCap cap = L2LibReg.EFFECT.type().get(le); - if (eff.exist()) { - cap.map.put(eff.effect(), eff.level()); - } else { - cap.map.remove(eff.effect()); - } - } + public static void sync(EffectToClient eff) { + if (Minecraft.getInstance().level == null) return; + Entity e = Minecraft.getInstance().level.getEntity(eff.entity()); + if (!(e instanceof LivingEntity le)) return; + if (!L2LibReg.EFFECT.type().isProper(le)) return; + ClientEffectCap cap = L2LibReg.EFFECT.type().getOrCreate(le); + if (eff.exist()) { + cap.map.put(eff.effect(), eff.level()); + } else { + cap.map.remove(eff.effect()); + } + } } diff --git a/src/main/java/dev/xkmc/l2core/init/L2LibReg.java b/src/main/java/dev/xkmc/l2core/init/L2LibReg.java index f936e43..deec60e 100644 --- a/src/main/java/dev/xkmc/l2core/init/L2LibReg.java +++ b/src/main/java/dev/xkmc/l2core/init/L2LibReg.java @@ -7,45 +7,62 @@ 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.simple.*; -import dev.xkmc.l2core.serial.conditions.*; +import dev.xkmc.l2core.serial.configval.*; import dev.xkmc.l2core.serial.ingredients.EnchantmentIngredient; import dev.xkmc.l2core.serial.ingredients.PotionIngredient; +import dev.xkmc.l2core.serial.loot.AddItemModifier; +import dev.xkmc.l2core.serial.loot.AddLootTableModifier; +import dev.xkmc.l2core.serial.loot.PlayerFlagCondition; +import dev.xkmc.l2serial.serialization.codec.MapCodecAdaptor; +import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.level.storage.loot.predicates.LootItemConditionType; import net.neoforged.bus.api.IEventBus; import net.neoforged.neoforge.common.conditions.ICondition; +import net.neoforged.neoforge.common.loot.IGlobalLootModifier; import net.neoforged.neoforge.registries.NeoForgeRegistries; public class L2LibReg { - public static final Reg REG = new Reg(L2Core.MODID); + public static final Reg REG = new Reg(L2Core.MODID); - // ingredients - public static final IngReg INGREDIENT = IngReg.of(REG); - public static final IngVal ING_ENCH = INGREDIENT.reg("enchantment", EnchantmentIngredient.class); - public static final IngVal ING_POTION = INGREDIENT.reg("potion", PotionIngredient.class); + // ingredients + public static final IngReg INGREDIENT = IngReg.of(REG); + public static final IngVal ING_ENCH = INGREDIENT.reg("enchantment", EnchantmentIngredient.class); + public static final IngVal ING_POTION = INGREDIENT.reg("potion", PotionIngredient.class); - // conditions - public static final CdcReg CONDITION = CdcReg.of(REG, NeoForgeRegistries.CONDITION_SERIALIZERS); - public static final CdcVal CONDITION_BOOL = CONDITION.reg("bool_config", BooleanValueCondition.class); - public static final CdcVal CONDITION_INT = CONDITION.reg("int_config", IntValueCondition.class); - public static final CdcVal CONDITION_DOUBLE = CONDITION.reg("double_config", DoubleValueCondition.class); - public static final CdcVal CONDITION_STR = CONDITION.reg("string_config", StringValueCondition.class); - public static final CdcVal CONDITION_LIST_STR = CONDITION.reg("string_list_config", ListStringValueCondition.class); + // conditions + public static final CdcReg CONDITION = CdcReg.of(REG, NeoForgeRegistries.CONDITION_SERIALIZERS); + public static final CdcVal CONDITION_BOOL = CONDITION.reg("bool_config", BooleanValueCondition.class); + public static final CdcVal CONDITION_INT = CONDITION.reg("int_config", IntValueCondition.class); + public static final CdcVal CONDITION_DOUBLE = CONDITION.reg("double_config", DoubleValueCondition.class); + public static final CdcVal CONDITION_STR = CONDITION.reg("string_config", StringValueCondition.class); + public static final CdcVal CONDITION_LIST_STR = CONDITION.reg("string_list_config", ListStringValueCondition.class); - // attachments - public static final AttReg ATTACHMENT = AttReg.of(REG); + // attachments + public static final AttReg ATTACHMENT = AttReg.of(REG); - public static final AttVal.CapVal EFFECT = ATTACHMENT.entity("effect", - ClientEffectCap.class, ClientEffectCap::new, LivingEntity.class, e -> e.level().isClientSide()); - public static final AttVal.PlayerVal CONDITIONAL = ATTACHMENT.player("conditionals", - ConditionalData.class, ConditionalData::new, PlayerCapabilityNetworkHandler::new); - public static final AttVal.PlayerVal FLAGS = ATTACHMENT.player("flags", - PlayerFlagData.class, PlayerFlagData::new, PlayerCapabilityNetworkHandler::new); + public static final AttVal.CapVal EFFECT = ATTACHMENT.entity("effect", + ClientEffectCap.class, ClientEffectCap::new, LivingEntity.class, e -> e.level().isClientSide()); + public static final AttVal.PlayerVal CONDITIONAL = ATTACHMENT.player("conditionals", + ConditionalData.class, ConditionalData::new, PlayerCapabilityNetworkHandler::new); + public static final AttVal.PlayerVal FLAGS = ATTACHMENT.player("flags", + PlayerFlagData.class, PlayerFlagData::new, PlayerCapabilityNetworkHandler::new); - public static final DatapackReg MENU_LAYOUT = REG.dataReg("menu_layout", MenuLayoutConfig.class); + // loot modifiers + public static final CdcReg GLM = CdcReg.of(REG, NeoForgeRegistries.GLOBAL_LOOT_MODIFIER_SERIALIZERS); + public static final CdcVal ADD_ITEM = GLM.reg("add_item", AddItemModifier.MAP_CODEC); + public static final CdcVal ADD_TABLE = GLM.reg("add_table", AddLootTableModifier.MAP_CODEC); - public static void register(IEventBus bus) { - REG.register(bus); - } + // loot conditions + public static final SR LIC = SR.of(REG, BuiltInRegistries.LOOT_CONDITION_TYPE); + public static final Val LIC_FLAG = LIC.reg("player_flag", () -> new LootItemConditionType(MapCodecAdaptor.of(PlayerFlagCondition.class))); + + // datapack + public static final DatapackReg MENU_LAYOUT = REG.dataReg("menu_layout", MenuLayoutConfig.class); + + public static void register(IEventBus bus) { + REG.register(bus); + } } diff --git a/src/main/java/dev/xkmc/l2core/serial/conditions/BooleanValueCondition.java b/src/main/java/dev/xkmc/l2core/serial/conditions/BooleanValueCondition.java deleted file mode 100644 index b9584c3..0000000 --- a/src/main/java/dev/xkmc/l2core/serial/conditions/BooleanValueCondition.java +++ /dev/null @@ -1,31 +0,0 @@ -package dev.xkmc.l2core.serial.conditions; - -import com.mojang.serialization.MapCodec; -import dev.xkmc.l2core.init.L2LibReg; -import net.neoforged.fml.config.ConfigTracker; -import net.neoforged.neoforge.common.ModConfigSpec; -import net.neoforged.neoforge.common.conditions.ICondition; - -import java.util.ArrayList; - -public record BooleanValueCondition(String path, ArrayList line, boolean expected) implements ICondition { - - public static BooleanValueCondition of(String file, ModConfigSpec.ConfigValue config, boolean value) { - return new BooleanValueCondition(file, new ArrayList<>(config.getPath()), value); - } - - @Override - public boolean test(IContext context) { - var file = ConfigTracker.INSTANCE.fileMap().get(path); - if (file == null) return false; - var line = file.getConfigData().get(line()); - if (line == null) return false; - return line instanceof Boolean bool && bool == expected; - } - - @Override - public MapCodec codec() { - return L2LibReg.CONDITION_BOOL.get(); - } - -} diff --git a/src/main/java/dev/xkmc/l2core/serial/conditions/DoubleValueCondition.java b/src/main/java/dev/xkmc/l2core/serial/conditions/DoubleValueCondition.java deleted file mode 100644 index dbc2344..0000000 --- a/src/main/java/dev/xkmc/l2core/serial/conditions/DoubleValueCondition.java +++ /dev/null @@ -1,31 +0,0 @@ -package dev.xkmc.l2core.serial.conditions; - -import com.mojang.serialization.MapCodec; -import dev.xkmc.l2core.init.L2LibReg; -import net.neoforged.fml.config.ConfigTracker; -import net.neoforged.neoforge.common.ModConfigSpec; -import net.neoforged.neoforge.common.conditions.ICondition; - -import java.util.ArrayList; - -public record DoubleValueCondition(String path, ArrayList line, double low, double high) implements ICondition { - - public static DoubleValueCondition of(String file, ModConfigSpec.ConfigValue config, double low, double high) { - return new DoubleValueCondition(file, new ArrayList<>(config.getPath()), low, high); - } - - @Override - public boolean test(IContext context) { - var file = ConfigTracker.INSTANCE.fileMap().get(path); - if (file == null) return false; - var line = file.getConfigData().get(line()); - if (line == null) return false; - return line instanceof Double val && low <= val && val <= high; - } - - @Override - public MapCodec codec() { - return L2LibReg.CONDITION_DOUBLE.get(); - } - -} diff --git a/src/main/java/dev/xkmc/l2core/serial/conditions/ListStringValueCondition.java b/src/main/java/dev/xkmc/l2core/serial/conditions/ListStringValueCondition.java deleted file mode 100644 index 715a2d2..0000000 --- a/src/main/java/dev/xkmc/l2core/serial/conditions/ListStringValueCondition.java +++ /dev/null @@ -1,32 +0,0 @@ -package dev.xkmc.l2core.serial.conditions; - -import com.mojang.serialization.MapCodec; -import dev.xkmc.l2core.init.L2LibReg; -import net.neoforged.fml.config.ConfigTracker; -import net.neoforged.neoforge.common.ModConfigSpec; -import net.neoforged.neoforge.common.conditions.ICondition; - -import java.util.ArrayList; -import java.util.List; - -public record ListStringValueCondition(String path, ArrayList line, String key) implements ICondition { - - public static ListStringValueCondition of(String file, ModConfigSpec.ConfigValue> config, String key) { - return new ListStringValueCondition(file, new ArrayList<>(config.getPath()), key); - } - - @Override - public boolean test(IContext context) { - var file = ConfigTracker.INSTANCE.fileMap().get(path); - if (file == null) return false; - var line = file.getConfigData().get(line()); - if (line == null) return false; - return line instanceof List val && val.contains(key); - } - - @Override - public MapCodec codec() { - return L2LibReg.CONDITION_LIST_STR.get(); - } - -} diff --git a/src/main/java/dev/xkmc/l2core/serial/conditions/StringValueCondition.java b/src/main/java/dev/xkmc/l2core/serial/conditions/StringValueCondition.java deleted file mode 100644 index 87c2fb6..0000000 --- a/src/main/java/dev/xkmc/l2core/serial/conditions/StringValueCondition.java +++ /dev/null @@ -1,31 +0,0 @@ -package dev.xkmc.l2core.serial.conditions; - -import com.mojang.serialization.MapCodec; -import dev.xkmc.l2core.init.L2LibReg; -import net.neoforged.fml.config.ConfigTracker; -import net.neoforged.neoforge.common.ModConfigSpec; -import net.neoforged.neoforge.common.conditions.ICondition; - -import java.util.ArrayList; - -public record StringValueCondition(String path, ArrayList line, String key) implements ICondition { - - public static StringValueCondition of(String file, ModConfigSpec.ConfigValue config, String key) { - return new StringValueCondition(file, new ArrayList<>(config.getPath()), key); - } - - @Override - public boolean test(IContext context) { - var file = ConfigTracker.INSTANCE.fileMap().get(path); - if (file == null) return false; - var line = file.getConfigData().get(line()); - if (line == null) return false; - return line instanceof String val && val.equals(key); - } - - @Override - public MapCodec codec() { - return L2LibReg.CONDITION_STR.get(); - } - -} diff --git a/src/main/java/dev/xkmc/l2core/serial/configval/AbstractConfigParser.java b/src/main/java/dev/xkmc/l2core/serial/configval/AbstractConfigParser.java new file mode 100644 index 0000000..66b5ee4 --- /dev/null +++ b/src/main/java/dev/xkmc/l2core/serial/configval/AbstractConfigParser.java @@ -0,0 +1,15 @@ +package dev.xkmc.l2core.serial.configval; + +import net.neoforged.fml.config.ConfigTracker; + +import java.util.List; +import java.util.Optional; + +public class AbstractConfigParser { + + public static Optional parse(String path, List line) { + return Optional.ofNullable(ConfigTracker.INSTANCE.fileMap().get(path)) + .map(file -> file.getConfigData().get(line)); + } + +} diff --git a/src/main/java/dev/xkmc/l2core/serial/configval/BooleanConfigValue.java b/src/main/java/dev/xkmc/l2core/serial/configval/BooleanConfigValue.java new file mode 100644 index 0000000..2cb5ee0 --- /dev/null +++ b/src/main/java/dev/xkmc/l2core/serial/configval/BooleanConfigValue.java @@ -0,0 +1,45 @@ +package dev.xkmc.l2core.serial.configval; + +import com.mojang.datafixers.util.Either; +import com.mojang.serialization.Codec; +import net.neoforged.neoforge.common.ModConfigSpec; + +import java.util.List; +import java.util.function.BooleanSupplier; + +public record BooleanConfigValue(String path, List line) implements BooleanSupplier { + + public static BooleanConfigValue of(String file, ModConfigSpec.ConfigValue config) { + return new BooleanConfigValue(file, config.getPath()); + } + + public static BooleanConfigValue of(String data) { + int last = data.lastIndexOf('/'); + var line = data.substring(last + 1).split("\\."); + return new BooleanConfigValue(data.substring(0, last), List.of(line)); + } + + public static Codec CODEC = Codec.either(Codec.BOOL, Codec.STRING) + .xmap(e -> e.map(x -> (BooleanSupplier) (() -> x), BooleanConfigValue::of), + e -> e instanceof BooleanConfigValue val ? + Either.right(val.toData()) : + Either.left(e.getAsBoolean())); + + public boolean getAsBoolean() { + return AbstractConfigParser.parse(path, line) + .map(e -> e instanceof Boolean val ? val : false) + .orElse(false); + } + + public String toData() { + StringBuilder lines = new StringBuilder(); + for (var e : line) { + if (!lines.isEmpty()) { + lines.append("."); + } + lines.append(e); + } + return path + "/" + lines; + } + +} diff --git a/src/main/java/dev/xkmc/l2core/serial/configval/BooleanValueCondition.java b/src/main/java/dev/xkmc/l2core/serial/configval/BooleanValueCondition.java new file mode 100644 index 0000000..7b146a7 --- /dev/null +++ b/src/main/java/dev/xkmc/l2core/serial/configval/BooleanValueCondition.java @@ -0,0 +1,27 @@ +package dev.xkmc.l2core.serial.configval; + +import com.mojang.serialization.MapCodec; +import dev.xkmc.l2core.init.L2LibReg; +import net.neoforged.neoforge.common.ModConfigSpec; +import net.neoforged.neoforge.common.conditions.ICondition; + +import java.util.ArrayList; + +public record BooleanValueCondition(String path, ArrayList line, boolean expected) implements ICondition { + + public static BooleanValueCondition of(String file, ModConfigSpec.ConfigValue config, boolean value) { + return new BooleanValueCondition(file, new ArrayList<>(config.getPath()), value); + } + + @Override + public boolean test(IContext context) { + return AbstractConfigParser.parse(path, line) + .map(e -> e instanceof Boolean bool && bool == expected).orElse(false); + } + + @Override + public MapCodec codec() { + return L2LibReg.CONDITION_BOOL.get(); + } + +} diff --git a/src/main/java/dev/xkmc/l2core/serial/configval/DoubleConfigValue.java b/src/main/java/dev/xkmc/l2core/serial/configval/DoubleConfigValue.java new file mode 100644 index 0000000..9e480b1 --- /dev/null +++ b/src/main/java/dev/xkmc/l2core/serial/configval/DoubleConfigValue.java @@ -0,0 +1,46 @@ +package dev.xkmc.l2core.serial.configval; + +import com.mojang.datafixers.util.Either; +import com.mojang.serialization.Codec; +import net.neoforged.neoforge.common.ModConfigSpec; + +import java.util.List; +import java.util.function.DoubleSupplier; + +public record DoubleConfigValue(String path, List line) implements DoubleSupplier { + + public static DoubleConfigValue of(String file, ModConfigSpec.ConfigValue config) { + return new DoubleConfigValue(file, config.getPath()); + } + + public static DoubleConfigValue of(String data) { + int last = data.lastIndexOf('/'); + var line = data.substring(last + 1).split("\\."); + return new DoubleConfigValue(data.substring(0, last), List.of(line)); + } + + public static Codec CODEC = Codec.either(Codec.DOUBLE, Codec.STRING) + .xmap(e -> e.map(x -> (DoubleSupplier) (() -> x), DoubleConfigValue::of), + e -> e instanceof DoubleConfigValue val ? + Either.right(val.toData()) : + Either.left(e.getAsDouble())); + + @Override + public double getAsDouble() { + return AbstractConfigParser.parse(path, line) + .map(e -> e instanceof Number val ? val.doubleValue() : 0d) + .orElse(0d); + } + + public String toData() { + StringBuilder lines = new StringBuilder(); + for (var e : line) { + if (!lines.isEmpty()) { + lines.append("."); + } + lines.append(e); + } + return path + "/" + lines; + } + +} diff --git a/src/main/java/dev/xkmc/l2core/serial/configval/DoubleValueCondition.java b/src/main/java/dev/xkmc/l2core/serial/configval/DoubleValueCondition.java new file mode 100644 index 0000000..873e82d --- /dev/null +++ b/src/main/java/dev/xkmc/l2core/serial/configval/DoubleValueCondition.java @@ -0,0 +1,27 @@ +package dev.xkmc.l2core.serial.configval; + +import com.mojang.serialization.MapCodec; +import dev.xkmc.l2core.init.L2LibReg; +import net.neoforged.neoforge.common.ModConfigSpec; +import net.neoforged.neoforge.common.conditions.ICondition; + +import java.util.ArrayList; + +public record DoubleValueCondition(String path, ArrayList line, double low, double high) implements ICondition { + + public static DoubleValueCondition of(String file, ModConfigSpec.ConfigValue config, double low, double high) { + return new DoubleValueCondition(file, new ArrayList<>(config.getPath()), low, high); + } + + @Override + public boolean test(IContext context) { + return AbstractConfigParser.parse(path, line) + .map(e -> e instanceof Double val && low <= val && val <= high).orElse(false); + } + + @Override + public MapCodec codec() { + return L2LibReg.CONDITION_DOUBLE.get(); + } + +} diff --git a/src/main/java/dev/xkmc/l2core/serial/configval/IntConfigValue.java b/src/main/java/dev/xkmc/l2core/serial/configval/IntConfigValue.java new file mode 100644 index 0000000..2ae0ee6 --- /dev/null +++ b/src/main/java/dev/xkmc/l2core/serial/configval/IntConfigValue.java @@ -0,0 +1,45 @@ +package dev.xkmc.l2core.serial.configval; + +import com.mojang.datafixers.util.Either; +import com.mojang.serialization.Codec; +import net.neoforged.neoforge.common.ModConfigSpec; + +import java.util.List; +import java.util.function.IntSupplier; + +public record IntConfigValue(String path, List line) implements IntSupplier { + + public static IntConfigValue of(String file, ModConfigSpec.ConfigValue config) { + return new IntConfigValue(file, config.getPath()); + } + + public static IntConfigValue of(String data) { + int last = data.lastIndexOf('/'); + var line = data.substring(last + 1).split("\\."); + return new IntConfigValue(data.substring(0, last), List.of(line)); + } + + public static Codec CODEC = Codec.either(Codec.INT, Codec.STRING) + .xmap(e -> e.map(x -> (IntSupplier) (() -> x), IntConfigValue::of), + e -> e instanceof IntConfigValue val ? + Either.right(val.toData()) : + Either.left(e.getAsInt())); + + public int getAsInt() { + return AbstractConfigParser.parse(path, line) + .map(e -> e instanceof Number val ? val.intValue() : 0) + .orElse(0); + } + + public String toData() { + StringBuilder lines = new StringBuilder(); + for (var e : line) { + if (!lines.isEmpty()) { + lines.append("."); + } + lines.append(e); + } + return path + "/" + lines; + } + +} diff --git a/src/main/java/dev/xkmc/l2core/serial/conditions/IntValueCondition.java b/src/main/java/dev/xkmc/l2core/serial/configval/IntValueCondition.java similarity index 62% rename from src/main/java/dev/xkmc/l2core/serial/conditions/IntValueCondition.java rename to src/main/java/dev/xkmc/l2core/serial/configval/IntValueCondition.java index d0c23e8..d439acd 100644 --- a/src/main/java/dev/xkmc/l2core/serial/conditions/IntValueCondition.java +++ b/src/main/java/dev/xkmc/l2core/serial/configval/IntValueCondition.java @@ -1,10 +1,7 @@ -package dev.xkmc.l2core.serial.conditions; +package dev.xkmc.l2core.serial.configval; import com.mojang.serialization.MapCodec; -import dev.xkmc.l2core.init.L2Core; import dev.xkmc.l2core.init.L2LibReg; -import net.minecraft.resources.ResourceLocation; -import net.neoforged.fml.config.ConfigTracker; import net.neoforged.neoforge.common.ModConfigSpec; import net.neoforged.neoforge.common.conditions.ICondition; @@ -18,11 +15,8 @@ public record IntValueCondition(String path, ArrayList line, int low, in @Override public boolean test(IContext context) { - var file = ConfigTracker.INSTANCE.fileMap().get(path); - if (file == null) return false; - var line = file.getConfigData().get(line()); - if (line == null) return false; - return line instanceof Integer val && low <= val && val <= high; + return AbstractConfigParser.parse(path, line) + .map(e -> e instanceof Integer val && low <= val && val <= high).orElse(false); } diff --git a/src/main/java/dev/xkmc/l2core/serial/configval/ListStringValueCondition.java b/src/main/java/dev/xkmc/l2core/serial/configval/ListStringValueCondition.java new file mode 100644 index 0000000..2ced179 --- /dev/null +++ b/src/main/java/dev/xkmc/l2core/serial/configval/ListStringValueCondition.java @@ -0,0 +1,28 @@ +package dev.xkmc.l2core.serial.configval; + +import com.mojang.serialization.MapCodec; +import dev.xkmc.l2core.init.L2LibReg; +import net.neoforged.neoforge.common.ModConfigSpec; +import net.neoforged.neoforge.common.conditions.ICondition; + +import java.util.ArrayList; +import java.util.List; + +public record ListStringValueCondition(String path, ArrayList line, String key) implements ICondition { + + public static ListStringValueCondition of(String file, ModConfigSpec.ConfigValue> config, String key) { + return new ListStringValueCondition(file, new ArrayList<>(config.getPath()), key); + } + + @Override + public boolean test(IContext context) { + return AbstractConfigParser.parse(path, line) + .map(e -> e instanceof List val && val.contains(key)).orElse(false); + } + + @Override + public MapCodec codec() { + return L2LibReg.CONDITION_LIST_STR.get(); + } + +} diff --git a/src/main/java/dev/xkmc/l2core/serial/configval/StringValueCondition.java b/src/main/java/dev/xkmc/l2core/serial/configval/StringValueCondition.java new file mode 100644 index 0000000..fc91f55 --- /dev/null +++ b/src/main/java/dev/xkmc/l2core/serial/configval/StringValueCondition.java @@ -0,0 +1,27 @@ +package dev.xkmc.l2core.serial.configval; + +import com.mojang.serialization.MapCodec; +import dev.xkmc.l2core.init.L2LibReg; +import net.neoforged.neoforge.common.ModConfigSpec; +import net.neoforged.neoforge.common.conditions.ICondition; + +import java.util.ArrayList; + +public record StringValueCondition(String path, ArrayList line, String key) implements ICondition { + + public static StringValueCondition of(String file, ModConfigSpec.ConfigValue config, String key) { + return new StringValueCondition(file, new ArrayList<>(config.getPath()), key); + } + + @Override + public boolean test(IContext context) { + return AbstractConfigParser.parse(path, line) + .map(e -> e instanceof String val && val.equals(key)).orElse(false); + } + + @Override + public MapCodec codec() { + return L2LibReg.CONDITION_STR.get(); + } + +} diff --git a/src/main/java/dev/xkmc/l2core/serial/conditions/package-info.java b/src/main/java/dev/xkmc/l2core/serial/configval/package-info.java similarity index 79% rename from src/main/java/dev/xkmc/l2core/serial/conditions/package-info.java rename to src/main/java/dev/xkmc/l2core/serial/configval/package-info.java index 2f1dbb0..d1be5ae 100644 --- a/src/main/java/dev/xkmc/l2core/serial/conditions/package-info.java +++ b/src/main/java/dev/xkmc/l2core/serial/configval/package-info.java @@ -1,7 +1,7 @@ @MethodsReturnNonnullByDefault @ParametersAreNonnullByDefault -package dev.xkmc.l2core.serial.conditions; +package dev.xkmc.l2core.serial.configval; import net.minecraft.MethodsReturnNonnullByDefault; diff --git a/src/main/java/dev/xkmc/l2core/serial/loot/AddItemModifier.java b/src/main/java/dev/xkmc/l2core/serial/loot/AddItemModifier.java new file mode 100644 index 0000000..e6e08ea --- /dev/null +++ b/src/main/java/dev/xkmc/l2core/serial/loot/AddItemModifier.java @@ -0,0 +1,74 @@ +package dev.xkmc.l2core.serial.loot; + +import com.mojang.serialization.Codec; +import com.mojang.serialization.MapCodec; +import com.mojang.serialization.codecs.RecordCodecBuilder; +import dev.xkmc.l2core.serial.configval.DoubleConfigValue; +import it.unimi.dsi.fastutil.objects.ObjectArrayList; +import net.minecraft.core.registries.BuiltInRegistries; +import net.minecraft.world.item.Item; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.Items; +import net.minecraft.world.level.storage.loot.LootContext; +import net.minecraft.world.level.storage.loot.parameters.LootContextParams; +import net.minecraft.world.level.storage.loot.predicates.LootItemCondition; +import net.neoforged.neoforge.common.loot.LootModifier; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.Optional; +import java.util.function.DoubleSupplier; + +public class AddItemModifier extends LootModifier { + + public static final Codec CODEC = RecordCodecBuilder.create(i -> LootModifier.codecStart(i).and(i.group( + BuiltInRegistries.ITEM.byNameCodec().fieldOf("item").forGetter(m -> m.item), + BuiltInRegistries.ITEM.byNameCodec().optionalFieldOf("fail").forGetter(m -> m.fail == Items.AIR ? Optional.empty() : Optional.of(m.fail)), + DoubleConfigValue.CODEC.optionalFieldOf("chance") + .forGetter(m -> Optional.ofNullable(m.chance)) + )).apply(i, AddItemModifier::new)); + + public static final MapCodec MAP_CODEC = CODEC.dispatchMap(e -> e, AddItemModifier::codec); + + public final Item item, fail; + + @Nullable + public final DoubleSupplier chance; + + protected AddItemModifier(LootItemCondition[] conditionsIn, Item item, Optional fail, Optional chance) { + super(conditionsIn); + this.item = item; + this.fail = fail.orElse(Items.AIR); + this.chance = chance.orElse(null); + } + + public AddItemModifier(Item item, @Nullable DoubleConfigValue chance, LootItemCondition... conditionsIn) { + this(item, Items.AIR, chance, conditionsIn); + } + + public AddItemModifier(Item item, Item fail, @Nullable DoubleConfigValue chance, LootItemCondition... conditionsIn) { + super(conditionsIn); + this.item = item; + this.fail = fail; + this.chance = chance; + } + + @Override + protected @NotNull ObjectArrayList doApply(ObjectArrayList generatedLoot, LootContext context) { + if (!context.hasParam(LootContextParams.DAMAGE_SOURCE)) { + return generatedLoot; + } + if (chance == null || context.getRandom().nextDouble() <= chance.getAsDouble()) { + generatedLoot.add(new ItemStack(item)); + } else if (fail != Items.AIR) { + generatedLoot.add(new ItemStack(fail)); + } + return generatedLoot; + } + + @Override + public MapCodec codec() { + return MAP_CODEC; + } + +} diff --git a/src/main/java/dev/xkmc/l2core/serial/loot/AddLootTableModifier.java b/src/main/java/dev/xkmc/l2core/serial/loot/AddLootTableModifier.java new file mode 100644 index 0000000..5f97512 --- /dev/null +++ b/src/main/java/dev/xkmc/l2core/serial/loot/AddLootTableModifier.java @@ -0,0 +1,52 @@ +package dev.xkmc.l2core.serial.loot; + +import com.mojang.serialization.Codec; +import com.mojang.serialization.MapCodec; +import com.mojang.serialization.codecs.RecordCodecBuilder; +import it.unimi.dsi.fastutil.objects.ObjectArrayList; +import net.minecraft.core.registries.Registries; +import net.minecraft.resources.ResourceKey; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.storage.loot.LootContext; +import net.minecraft.world.level.storage.loot.predicates.LootItemCondition; +import net.neoforged.neoforge.common.loot.LootModifier; + +import javax.annotation.Nonnull; + +import static net.minecraft.world.level.storage.loot.LootTable.createStackSplitter; + +public class AddLootTableModifier extends LootModifier { + + public static final Codec CODEC = RecordCodecBuilder.create(inst -> codecStart(inst) + .and(ResourceLocation.CODEC.fieldOf("lootTable").forGetter((m) -> m.lootTable)) + .apply(inst, AddLootTableModifier::new)); + + public static final MapCodec MAP_CODEC = CODEC.dispatchMap(e -> e, AddLootTableModifier::codec); + + private final ResourceLocation lootTable; + + protected AddLootTableModifier(LootItemCondition[] conditionsIn, ResourceLocation lootTable) { + super(conditionsIn); + this.lootTable = lootTable; + } + + public AddLootTableModifier(ResourceLocation lootTable, LootItemCondition... conditionsIn) { + super(conditionsIn); + this.lootTable = lootTable; + } + + @Nonnull + @Override + protected ObjectArrayList doApply(ObjectArrayList generatedLoot, LootContext context) { + var extraTable = context.getResolver().lookupOrThrow(Registries.LOOT_TABLE) + .getOrThrow(ResourceKey.create(Registries.LOOT_TABLE, this.lootTable)).value(); + extraTable.getRandomItemsRaw(context, createStackSplitter(context.getLevel(), generatedLoot::add)); + return generatedLoot; + } + + @Override + public MapCodec codec() { + return MAP_CODEC; + } +} \ No newline at end of file diff --git a/src/main/java/dev/xkmc/l2core/serial/loot/PlayerFlagCondition.java b/src/main/java/dev/xkmc/l2core/serial/loot/PlayerFlagCondition.java new file mode 100644 index 0000000..3aa2889 --- /dev/null +++ b/src/main/java/dev/xkmc/l2core/serial/loot/PlayerFlagCondition.java @@ -0,0 +1,38 @@ +package dev.xkmc.l2core.serial.loot; + +import dev.xkmc.l2core.init.L2LibReg; +import dev.xkmc.l2serial.serialization.marker.SerialClass; +import dev.xkmc.l2serial.serialization.marker.SerialField; +import net.minecraft.world.level.storage.loot.LootContext; +import net.minecraft.world.level.storage.loot.parameters.LootContextParams; +import net.minecraft.world.level.storage.loot.predicates.LootItemCondition; +import net.minecraft.world.level.storage.loot.predicates.LootItemConditionType; + +@SerialClass +public class PlayerFlagCondition implements LootItemCondition { + + @SerialField + public String flag; + + @Deprecated + public PlayerFlagCondition() { + + } + + public PlayerFlagCondition(String flag) { + this.flag = flag; + } + + @Override + public LootItemConditionType getType() { + return L2LibReg.LIC_FLAG.get(); + } + + @Override + public boolean test(LootContext ctx) { + if (!ctx.hasParam(LootContextParams.LAST_DAMAGE_PLAYER)) return false; + var player = ctx.getParam(LootContextParams.LAST_DAMAGE_PLAYER); + return L2LibReg.FLAGS.type().getExisting(player).map(e -> e.hasFlag(flag)).orElse(false); + } + +} diff --git a/src/main/java/dev/xkmc/l2core/serial/loot/package-info.java b/src/main/java/dev/xkmc/l2core/serial/loot/package-info.java new file mode 100644 index 0000000..46b8003 --- /dev/null +++ b/src/main/java/dev/xkmc/l2core/serial/loot/package-info.java @@ -0,0 +1,8 @@ +@MethodsReturnNonnullByDefault +@ParametersAreNonnullByDefault + +package dev.xkmc.l2core.serial.loot; + +import net.minecraft.MethodsReturnNonnullByDefault; + +import javax.annotation.ParametersAreNonnullByDefault; \ No newline at end of file