remove config
This commit is contained in:
@@ -30,4 +30,4 @@ jei_version = 19.0.0.7
|
|||||||
lljij = false
|
lljij = false
|
||||||
rootMod = false
|
rootMod = false
|
||||||
|
|
||||||
l2serial_ver = 3.0.0-pre1
|
l2serial_ver = 3.0.0-pre3
|
||||||
Binary file not shown.
Binary file not shown.
@@ -2,10 +2,12 @@ package dev.xkmc.l2core.capability.attachment;
|
|||||||
|
|
||||||
import dev.xkmc.l2serial.serialization.codec.TagCodec;
|
import dev.xkmc.l2serial.serialization.codec.TagCodec;
|
||||||
import dev.xkmc.l2serial.util.Wrappers;
|
import dev.xkmc.l2serial.util.Wrappers;
|
||||||
|
import net.minecraft.core.HolderLookup;
|
||||||
import net.minecraft.nbt.CompoundTag;
|
import net.minecraft.nbt.CompoundTag;
|
||||||
import net.neoforged.neoforge.attachment.AttachmentType;
|
import net.neoforged.neoforge.attachment.AttachmentType;
|
||||||
import net.neoforged.neoforge.attachment.IAttachmentHolder;
|
import net.neoforged.neoforge.attachment.IAttachmentHolder;
|
||||||
import net.neoforged.neoforge.attachment.IAttachmentSerializer;
|
import net.neoforged.neoforge.attachment.IAttachmentSerializer;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
@@ -35,13 +37,13 @@ public class AttachmentDef<E> implements IAttachmentSerializer<CompoundTag, E> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public E read(IAttachmentHolder holder, CompoundTag tag) {
|
public E read(IAttachmentHolder holder, CompoundTag tag, HolderLookup.Provider provider) {
|
||||||
return Objects.requireNonNull(Wrappers.get(() -> TagCodec.fromTag(tag, cls, null, f -> true)));
|
return Objects.requireNonNull(Wrappers.get(() -> new TagCodec(provider).fromTag(tag, cls, null)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CompoundTag write(E attachment) {
|
public CompoundTag write(E attachment, HolderLookup.Provider provider) {
|
||||||
return Objects.requireNonNull(TagCodec.toTag(new CompoundTag(), attachment));
|
return Objects.requireNonNull(new TagCodec(provider).toTag(new CompoundTag(), attachment));
|
||||||
}
|
}
|
||||||
|
|
||||||
public Class<E> cls() {
|
public Class<E> cls() {
|
||||||
|
|||||||
@@ -1,25 +1,33 @@
|
|||||||
package dev.xkmc.l2core.capability.conditionals;
|
package dev.xkmc.l2core.capability.conditionals;
|
||||||
|
|
||||||
import dev.xkmc.l2core.capability.player.PlayerCapabilityTemplate;
|
import dev.xkmc.l2core.capability.player.PlayerCapabilityTemplate;
|
||||||
import dev.xkmc.l2core.init.L2LibraryConfig;
|
import dev.xkmc.l2serial.serialization.marker.SerialClass;
|
||||||
import dev.xkmc.l2serial.serialization.SerialClass;
|
import dev.xkmc.l2serial.serialization.marker.SerialField;
|
||||||
import dev.xkmc.l2serial.util.Wrappers;
|
import dev.xkmc.l2serial.util.Wrappers;
|
||||||
import net.minecraft.world.entity.player.Player;
|
import net.minecraft.world.entity.player.Player;
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
import java.util.HashMap;
|
import java.util.ArrayList;
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
@SerialClass
|
@SerialClass
|
||||||
public class ConditionalData extends PlayerCapabilityTemplate<ConditionalData> {
|
public class ConditionalData extends PlayerCapabilityTemplate<ConditionalData> {
|
||||||
|
|
||||||
@SerialClass.SerialField
|
@SerialField
|
||||||
public HashMap<TokenKey<?>, ConditionalToken> data = new HashMap<>();
|
public LinkedHashMap<TokenKey<?>, ConditionalToken> data = new LinkedHashMap<>();
|
||||||
@SerialClass.SerialField
|
|
||||||
public int tickSinceDeath = 0;
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onClone(boolean isWasDeath) {
|
public void onClone(Player player, boolean isWasDeath) {
|
||||||
tickSinceDeath = 0;
|
if (!isWasDeath) return;
|
||||||
|
List<TokenKey<?>> toRemove = new ArrayList<>();
|
||||||
|
for (var e : data.entrySet()) {
|
||||||
|
if (!e.getValue().retainOnDeath(player)) {
|
||||||
|
toRemove.add(e.getKey());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (var e : toRemove)
|
||||||
|
data.remove(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
public <T extends ConditionalToken, C extends Context> T getOrCreateData(TokenProvider<T, C> setEffect, C ent) {
|
public <T extends ConditionalToken, C extends Context> T getOrCreateData(TokenProvider<T, C> setEffect, C ent) {
|
||||||
@@ -33,12 +41,14 @@ public class ConditionalData extends PlayerCapabilityTemplate<ConditionalData> {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void tick(Player player) {
|
public void tick(Player player) {
|
||||||
tickSinceDeath++;
|
List<TokenKey<?>> toRemove = new ArrayList<>();
|
||||||
if (L2LibraryConfig.SERVER.restoreFullHealthOnRespawn.get() &&
|
for (var e : data.entrySet()) {
|
||||||
tickSinceDeath < 60 && player.getHealth() < player.getMaxHealth()) {
|
if (e.getValue().tick(player)) {
|
||||||
player.setHealth(player.getMaxHealth());
|
toRemove.add(e.getKey());
|
||||||
}
|
}
|
||||||
data.entrySet().removeIf(e -> e.getValue().tick(player));
|
}
|
||||||
|
for (var e : toRemove)
|
||||||
|
data.remove(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean hasData(TokenKey<?> eff) {
|
public boolean hasData(TokenKey<?> eff) {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
package dev.xkmc.l2core.capability.conditionals;
|
package dev.xkmc.l2core.capability.conditionals;
|
||||||
|
|
||||||
import dev.xkmc.l2serial.serialization.SerialClass;
|
import dev.xkmc.l2serial.serialization.marker.SerialClass;
|
||||||
import net.minecraft.world.entity.player.Player;
|
import net.minecraft.world.entity.player.Player;
|
||||||
|
|
||||||
@SerialClass
|
@SerialClass
|
||||||
@@ -10,6 +10,13 @@ public class ConditionalToken {
|
|||||||
* return true to remove
|
* return true to remove
|
||||||
*/
|
*/
|
||||||
public boolean tick(Player player) {
|
public boolean tick(Player player) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* return true to retain
|
||||||
|
* */
|
||||||
|
public boolean retainOnDeath(Player player) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,15 +1,17 @@
|
|||||||
package dev.xkmc.l2core.capability.player;
|
package dev.xkmc.l2core.capability.player;
|
||||||
|
|
||||||
import dev.xkmc.l2core.util.Proxy;
|
import dev.xkmc.l2core.util.Proxy;
|
||||||
import dev.xkmc.l2serial.serialization.SerialClass;
|
|
||||||
import dev.xkmc.l2serial.serialization.codec.PacketCodec;
|
import dev.xkmc.l2serial.serialization.codec.PacketCodec;
|
||||||
|
import dev.xkmc.l2serial.serialization.marker.SerialField;
|
||||||
|
import net.minecraft.core.RegistryAccess;
|
||||||
|
|
||||||
import java.util.function.Predicate;
|
import java.util.function.Predicate;
|
||||||
|
|
||||||
public class ClientSyncHandler {
|
public class ClientSyncHandler {
|
||||||
|
|
||||||
public static <T extends PlayerCapabilityTemplate<T>> void parse(byte[] tag, PlayerCapabilityHolder<T> holder, Predicate<SerialClass.SerialField> pred) {
|
public static <T extends PlayerCapabilityTemplate<T>> void parse(
|
||||||
PacketCodec.fromBytes(tag, holder.cls(), Proxy.getClientPlayer().getData(holder.type()), pred);
|
RegistryAccess access, byte[] tag, PlayerCapabilityHolder<T> holder, Predicate<SerialField> pred) {
|
||||||
|
PacketCodec.fromBytes(access, tag, holder.cls(), Proxy.getClientPlayer().getData(holder.type()), pred);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
package dev.xkmc.l2core.capability.player;
|
package dev.xkmc.l2core.capability.player;
|
||||||
|
|
||||||
import dev.xkmc.l2serial.network.SerialPacketBase;
|
import dev.xkmc.l2serial.network.SerialPacketBase;
|
||||||
import dev.xkmc.l2serial.serialization.SerialClass;
|
|
||||||
import dev.xkmc.l2serial.serialization.codec.PacketCodec;
|
import dev.xkmc.l2serial.serialization.codec.PacketCodec;
|
||||||
|
import dev.xkmc.l2serial.serialization.marker.SerialClass;
|
||||||
|
import dev.xkmc.l2serial.serialization.marker.SerialField;
|
||||||
import net.minecraft.resources.ResourceLocation;
|
import net.minecraft.resources.ResourceLocation;
|
||||||
import net.minecraft.server.level.ServerPlayer;
|
import net.minecraft.server.level.ServerPlayer;
|
||||||
import net.minecraft.world.entity.player.Player;
|
import net.minecraft.world.entity.player.Player;
|
||||||
@@ -18,27 +19,28 @@ public record PlayerCapToClient(Action action, ResourceLocation holderID, byte[]
|
|||||||
public static <T extends PlayerCapabilityTemplate<T>> PlayerCapToClient
|
public static <T extends PlayerCapabilityTemplate<T>> PlayerCapToClient
|
||||||
of(ServerPlayer player, Action action, PlayerCapabilityHolder<T> holder, T handler) {
|
of(ServerPlayer player, Action action, PlayerCapabilityHolder<T> holder, T handler) {
|
||||||
return new PlayerCapToClient(action, holder.id,
|
return new PlayerCapToClient(action, holder.id,
|
||||||
PacketCodec.toBytes(handler, holder.cls(), action.pred),
|
PacketCodec.toBytes(player.level().registryAccess(),
|
||||||
|
handler, holder.cls(), action.pred),
|
||||||
player.getUUID());
|
player.getUUID());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void handle(@Nullable Player player) {
|
public void handle(Player player) {
|
||||||
ClientSyncHandler.parse(data, PlayerCapabilityHolder.INTERNAL_MAP.get(holderID), action.pred);
|
ClientSyncHandler.parse(player.level().registryAccess(), data,
|
||||||
|
PlayerCapabilityHolder.INTERNAL_MAP.get(holderID), action.pred);
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum Action {
|
public enum Action {
|
||||||
ALL(e -> true),
|
ALL(e -> true),
|
||||||
CLIENT(SerialClass.SerialField::toClient),
|
CLIENT(SerialField::toClient),
|
||||||
TRACK(SerialClass.SerialField::toTracking),
|
TRACK(SerialField::toTracking),
|
||||||
;
|
;
|
||||||
public final Predicate<SerialClass.SerialField> pred;
|
public final Predicate<SerialField> pred;
|
||||||
|
|
||||||
Action(Predicate<SerialClass.SerialField> pred) {
|
Action(Predicate<SerialField> pred) {
|
||||||
this.pred = pred;
|
this.pred = pred;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
package dev.xkmc.l2core.capability.player;
|
package dev.xkmc.l2core.capability.player;
|
||||||
|
|
||||||
import dev.xkmc.l2core.capability.attachment.GeneralCapabilityTemplate;
|
import dev.xkmc.l2core.capability.attachment.GeneralCapabilityTemplate;
|
||||||
import dev.xkmc.l2serial.serialization.SerialClass;
|
import dev.xkmc.l2serial.serialization.marker.SerialClass;
|
||||||
import net.minecraft.world.entity.player.Player;
|
import net.minecraft.world.entity.player.Player;
|
||||||
|
|
||||||
@SerialClass
|
@SerialClass
|
||||||
@@ -10,7 +10,7 @@ public class PlayerCapabilityTemplate<T extends PlayerCapabilityTemplate<T>> ext
|
|||||||
public void init(Player player) {
|
public void init(Player player) {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onClone(boolean isWasDeath) {
|
public void onClone(Player player, boolean isWasDeath) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -27,7 +27,6 @@ public class L2Core {
|
|||||||
// TODO public static final L2Registrate REGISTRATE = new L2Registrate(MODID);
|
// TODO public static final L2Registrate REGISTRATE = new L2Registrate(MODID);
|
||||||
|
|
||||||
public static final PacketHandler PACKET_HANDLER = new PacketHandler(MODID, 1,
|
public static final PacketHandler PACKET_HANDLER = new PacketHandler(MODID, 1,
|
||||||
e -> e.create(SyncPacket.class, PLAY_TO_CLIENT),
|
|
||||||
e -> e.create(EffectToClient.class, PLAY_TO_CLIENT),
|
e -> e.create(EffectToClient.class, PLAY_TO_CLIENT),
|
||||||
e -> e.create(PlayerCapToClient.class, PLAY_TO_CLIENT),
|
e -> e.create(PlayerCapToClient.class, PLAY_TO_CLIENT),
|
||||||
e -> e.create(TokenToClient.class, PLAY_TO_CLIENT)
|
e -> e.create(TokenToClient.class, PLAY_TO_CLIENT)
|
||||||
@@ -36,7 +35,6 @@ public class L2Core {
|
|||||||
public L2Core(IEventBus bus) {
|
public L2Core(IEventBus bus) {
|
||||||
Handlers.register();
|
Handlers.register();
|
||||||
L2LibReg.register(bus);
|
L2LibReg.register(bus);
|
||||||
L2LibraryConfig.init();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@SubscribeEvent
|
@SubscribeEvent
|
||||||
|
|||||||
@@ -1,6 +0,0 @@
|
|||||||
package dev.xkmc.l2core.init;
|
|
||||||
|
|
||||||
//@Mod.EventBusSubscriber(value = Dist.CLIENT, path = L2Library.MODID, bus = Mod.EventBusSubscriber.Bus.MOD)
|
|
||||||
public class L2LibraryClient {
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,81 +0,0 @@
|
|||||||
package dev.xkmc.l2core.init;
|
|
||||||
|
|
||||||
import net.neoforged.fml.ModLoadingContext;
|
|
||||||
import net.neoforged.fml.config.IConfigSpec;
|
|
||||||
import net.neoforged.fml.config.ModConfig;
|
|
||||||
import net.neoforged.neoforge.common.ModConfigSpec;
|
|
||||||
import org.apache.commons.lang3.tuple.Pair;
|
|
||||||
|
|
||||||
public class L2LibraryConfig {
|
|
||||||
|
|
||||||
public static class Client {
|
|
||||||
|
|
||||||
public final ModConfigSpec.DoubleValue infoAlpha;
|
|
||||||
public final ModConfigSpec.IntValue infoAnchor;
|
|
||||||
public final ModConfigSpec.DoubleValue infoMaxWidth;
|
|
||||||
|
|
||||||
public final ModConfigSpec.BooleanValue selectionDisplayRequireShift;
|
|
||||||
public final ModConfigSpec.BooleanValue selectionScrollRequireShift;
|
|
||||||
|
|
||||||
|
|
||||||
Client(ModConfigSpec.Builder builder) {
|
|
||||||
infoAlpha = builder.comment("Info background transparency. 1 means opaque.")
|
|
||||||
.defineInRange("infoAlpha", 0.5, 0, 1);
|
|
||||||
infoAnchor = builder.comment("Info alignment. 0 means top. 1 means middle. 2 means bottom.")
|
|
||||||
.defineInRange("infoAnchor", 1, 0, 2);
|
|
||||||
infoMaxWidth = builder.comment("Info max width. 0.5 means half screen. default: 0.3")
|
|
||||||
.defineInRange("infoMaxWidth", 0.3, 0, 0.5);
|
|
||||||
|
|
||||||
selectionDisplayRequireShift = builder.comment("Render Selection only when pressing shift")
|
|
||||||
.define("selectionDisplayRequireShift", false);
|
|
||||||
selectionScrollRequireShift = builder.comment("Scroll for selection only when pressing shift")
|
|
||||||
.define("selectionScrollRequireShift", true);
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class Server {
|
|
||||||
|
|
||||||
public final ModConfigSpec.BooleanValue restoreFullHealthOnRespawn;
|
|
||||||
|
|
||||||
Server(ModConfigSpec.Builder builder) {
|
|
||||||
restoreFullHealthOnRespawn = builder.comment("Restore full health on respawn")
|
|
||||||
.define("restoreFullHealthOnRespawn", true);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public static final ModConfigSpec CLIENT_SPEC;
|
|
||||||
public static final Client CLIENT;
|
|
||||||
|
|
||||||
public static final ModConfigSpec SERVER_SPEC;
|
|
||||||
public static final Server SERVER;
|
|
||||||
|
|
||||||
static {
|
|
||||||
final Pair<Client, ModConfigSpec> client = new ModConfigSpec.Builder().configure(Client::new);
|
|
||||||
CLIENT_SPEC = client.getRight();
|
|
||||||
CLIENT = client.getLeft();
|
|
||||||
|
|
||||||
final Pair<Server, ModConfigSpec> server = new ModConfigSpec.Builder().configure(Server::new);
|
|
||||||
SERVER_SPEC = server.getRight();
|
|
||||||
SERVER = server.getLeft();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Registers any relevant listeners for config
|
|
||||||
*/
|
|
||||||
public static void init() {
|
|
||||||
register(ModConfig.Type.CLIENT, CLIENT_SPEC);
|
|
||||||
register(ModConfig.Type.SERVER, SERVER_SPEC);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void register(ModConfig.Type type, IConfigSpec<?> spec) {
|
|
||||||
var mod = ModLoadingContext.get().getActiveContainer();
|
|
||||||
String path = "l2_configs/" + mod.getModId() + "-" + type.extension() + ".toml";
|
|
||||||
ModLoadingContext.get().registerConfig(type, spec, path);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -5,18 +5,19 @@ import dev.xkmc.l2core.capability.player.PlayerCapabilityHolder;
|
|||||||
import dev.xkmc.l2core.init.L2Core;
|
import dev.xkmc.l2core.init.L2Core;
|
||||||
import dev.xkmc.l2serial.util.Wrappers;
|
import dev.xkmc.l2serial.util.Wrappers;
|
||||||
import net.minecraft.server.level.ServerPlayer;
|
import net.minecraft.server.level.ServerPlayer;
|
||||||
|
import net.minecraft.world.entity.LivingEntity;
|
||||||
import net.neoforged.bus.api.EventPriority;
|
import net.neoforged.bus.api.EventPriority;
|
||||||
import net.neoforged.bus.api.SubscribeEvent;
|
import net.neoforged.bus.api.SubscribeEvent;
|
||||||
import net.neoforged.fml.common.Mod;
|
import net.neoforged.fml.common.EventBusSubscriber;
|
||||||
import net.neoforged.neoforge.event.entity.living.LivingEvent;
|
|
||||||
import net.neoforged.neoforge.event.entity.player.PlayerEvent;
|
import net.neoforged.neoforge.event.entity.player.PlayerEvent;
|
||||||
|
import net.neoforged.neoforge.event.tick.EntityTickEvent;
|
||||||
|
|
||||||
@Mod.EventBusSubscriber(modid = L2Core.MODID, bus = Mod.EventBusSubscriber.Bus.FORGE)
|
@EventBusSubscriber(modid = L2Core.MODID, bus = EventBusSubscriber.Bus.GAME)
|
||||||
public class BaseCapabilityEvents {
|
public class BaseCapabilityEvents {
|
||||||
|
|
||||||
@SubscribeEvent
|
@SubscribeEvent
|
||||||
public static void onLivingTick(LivingEvent.LivingTickEvent event) {
|
public static void onLivingTick(EntityTickEvent.Post event) {
|
||||||
if (event.getEntity().isAlive()) {
|
if (event.getEntity() instanceof LivingEntity le && le.isAlive()) {
|
||||||
for (GeneralCapabilityHolder<?, ?> holder : GeneralCapabilityHolder.INTERNAL_MAP.values()) {
|
for (GeneralCapabilityHolder<?, ?> holder : GeneralCapabilityHolder.INTERNAL_MAP.values()) {
|
||||||
if (holder.isFor(event.getEntity()))
|
if (holder.isFor(event.getEntity()))
|
||||||
holder.get(Wrappers.cast(event.getEntity())).tick(Wrappers.cast(event.getEntity()));
|
holder.get(Wrappers.cast(event.getEntity())).tick(Wrappers.cast(event.getEntity()));
|
||||||
@@ -28,7 +29,7 @@ public class BaseCapabilityEvents {
|
|||||||
public static void onPlayerClone(PlayerEvent.Clone event) {
|
public static void onPlayerClone(PlayerEvent.Clone event) {
|
||||||
for (PlayerCapabilityHolder<?> holder : PlayerCapabilityHolder.INTERNAL_MAP.values()) {
|
for (PlayerCapabilityHolder<?> holder : PlayerCapabilityHolder.INTERNAL_MAP.values()) {
|
||||||
ServerPlayer e = (ServerPlayer) event.getEntity();
|
ServerPlayer e = (ServerPlayer) event.getEntity();
|
||||||
holder.get(e).onClone(event.isWasDeath());
|
holder.get(e).onClone(e, event.isWasDeath());
|
||||||
holder.network.toClient(e);
|
holder.network.toClient(e);
|
||||||
holder.network.toTracking(e);
|
holder.network.toTracking(e);
|
||||||
}
|
}
|
||||||
@@ -37,14 +38,13 @@ public class BaseCapabilityEvents {
|
|||||||
@SubscribeEvent
|
@SubscribeEvent
|
||||||
public static void onServerPlayerJoin(PlayerEvent.PlayerLoggedInEvent event) {
|
public static void onServerPlayerJoin(PlayerEvent.PlayerLoggedInEvent event) {
|
||||||
ServerPlayer e = (ServerPlayer) event.getEntity();
|
ServerPlayer e = (ServerPlayer) event.getEntity();
|
||||||
if (e != null) {
|
if (e == null) return;
|
||||||
for (PlayerCapabilityHolder<?> holder : PlayerCapabilityHolder.INTERNAL_MAP.values()) {
|
for (PlayerCapabilityHolder<?> holder : PlayerCapabilityHolder.INTERNAL_MAP.values()) {
|
||||||
holder.get(e).init(e);
|
holder.get(e).init(e);
|
||||||
holder.network.toClient(e);
|
holder.network.toClient(e);
|
||||||
holder.network.toTracking(e);
|
holder.network.toTracking(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
@SubscribeEvent
|
@SubscribeEvent
|
||||||
public static void onStartTracking(PlayerEvent.StartTracking event) {
|
public static void onStartTracking(PlayerEvent.StartTracking event) {
|
||||||
|
|||||||
@@ -32,7 +32,9 @@ import net.minecraft.world.entity.LivingEntity;
|
|||||||
import net.minecraft.world.phys.Vec3;
|
import net.minecraft.world.phys.Vec3;
|
||||||
import net.neoforged.api.distmarker.Dist;
|
import net.neoforged.api.distmarker.Dist;
|
||||||
import net.neoforged.bus.api.SubscribeEvent;
|
import net.neoforged.bus.api.SubscribeEvent;
|
||||||
|
import net.neoforged.fml.common.EventBusSubscriber;
|
||||||
import net.neoforged.fml.common.Mod;
|
import net.neoforged.fml.common.Mod;
|
||||||
|
import net.neoforged.neoforge.client.event.ClientTickEvent;
|
||||||
import net.neoforged.neoforge.client.event.RenderLevelStageEvent;
|
import net.neoforged.neoforge.client.event.RenderLevelStageEvent;
|
||||||
import net.neoforged.neoforge.client.event.RenderLivingEvent;
|
import net.neoforged.neoforge.client.event.RenderLivingEvent;
|
||||||
import net.neoforged.neoforge.event.TickEvent;
|
import net.neoforged.neoforge.event.TickEvent;
|
||||||
@@ -41,17 +43,16 @@ import java.util.ArrayList;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
@Mod.EventBusSubscriber(value = Dist.CLIENT, modid = L2Core.MODID, bus = Mod.EventBusSubscriber.Bus.FORGE)
|
@EventBusSubscriber(value = Dist.CLIENT, modid = L2Core.MODID, bus = EventBusSubscriber.Bus.GAME)
|
||||||
public class ClientEffectRenderEvents {
|
public class ClientEffectRenderEvents {
|
||||||
|
|
||||||
private static final ArrayList<DelayedEntityRender> ICONS = new ArrayList<>();
|
private static final ArrayList<DelayedEntityRender> ICONS = new ArrayList<>();
|
||||||
|
|
||||||
@SubscribeEvent
|
@SubscribeEvent
|
||||||
public static void clientTick(TickEvent.ClientTickEvent event) {
|
public static void clientTick(ClientTickEvent.Post event) {
|
||||||
if (event.phase != TickEvent.Phase.END) return;
|
|
||||||
AbstractClientPlayer player = Proxy.getClientPlayer();
|
AbstractClientPlayer player = Proxy.getClientPlayer();
|
||||||
if (player != null) {
|
if (player != null) {
|
||||||
for (Map.Entry<MobEffect, MobEffectInstance> entry : player.getActiveEffectsMap().entrySet()) {
|
for (var entry : player.getActiveEffectsMap().entrySet()) {
|
||||||
if (entry.getKey() instanceof FirstPlayerRenderEffect effect) {
|
if (entry.getKey() instanceof FirstPlayerRenderEffect effect) {
|
||||||
effect.onClientLevelRender(player, entry.getValue());
|
effect.onClientLevelRender(player, entry.getValue());
|
||||||
}
|
}
|
||||||
@@ -68,26 +69,11 @@ public class ClientEffectRenderEvents {
|
|||||||
PoseStack stack = event.getPoseStack();
|
PoseStack stack = event.getPoseStack();
|
||||||
|
|
||||||
// cache the previous handler
|
// cache the previous handler
|
||||||
PoseStack posestack = RenderSystem.getModelViewStack();
|
|
||||||
var last = posestack.last();
|
|
||||||
posestack.popPose();
|
|
||||||
RenderSystem.applyModelViewMatrix();
|
|
||||||
|
|
||||||
RenderSystem.disableDepthTest();
|
|
||||||
for (DelayedEntityRender icon : ICONS) {
|
for (DelayedEntityRender icon : ICONS) {
|
||||||
renderIcon(stack, buffers, icon, event.getPartialTick(), camera, renderer.entityRenderDispatcher);
|
renderIcon(stack, buffers, icon, event.getPartialTick().getGameTimeDeltaTicks(), camera, renderer.entityRenderDispatcher);
|
||||||
}
|
}
|
||||||
buffers.endBatch();
|
buffers.endBatch();
|
||||||
|
|
||||||
// restore the previous handler
|
|
||||||
posestack.pushPose();
|
|
||||||
posestack.setIdentity();
|
|
||||||
posestack.last().pose().mul(last.pose());
|
|
||||||
posestack.last().normal().mul(last.normal());
|
|
||||||
RenderSystem.applyModelViewMatrix();
|
|
||||||
|
|
||||||
RenderSystem.enableDepthTest();
|
|
||||||
|
|
||||||
ICONS.clear();
|
ICONS.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -27,21 +27,21 @@ public record AttReg(DeferredRegister<AttachmentType<?>> att) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public <E, T extends AttachmentDef<E>> AttVal<E, T> reg(String id, Function<ResourceLocation, T> factory) {
|
public <E, T extends AttachmentDef<E>> AttVal<E, T> reg(String id, Function<ResourceLocation, T> factory) {
|
||||||
ResourceLocation rl = new ResourceLocation(att.getNamespace(), id);
|
ResourceLocation rl = ResourceLocation.fromNamespaceAndPath(att.getNamespace(), id);
|
||||||
T type = factory.apply(rl);
|
T type = factory.apply(rl);
|
||||||
return reg(id, type);
|
return reg(id, type);
|
||||||
}
|
}
|
||||||
|
|
||||||
public <E extends GeneralCapabilityTemplate<H, E>, H extends AttachmentHolder> AttVal.CapVal<H, E>
|
public <E extends GeneralCapabilityTemplate<H, E>, H extends AttachmentHolder> AttVal.CapVal<H, E>
|
||||||
entity(String id, Class<E> holder_class, Supplier<E> sup, Class<H> entity_class, Predicate<H> pred) {
|
entity(String id, Class<E> holder_class, Supplier<E> sup, Class<H> entity_class, Predicate<H> pred) {
|
||||||
ResourceLocation rl = new ResourceLocation(att.getNamespace(), id);
|
ResourceLocation rl = ResourceLocation.fromNamespaceAndPath(att.getNamespace(), id);
|
||||||
var type = new GeneralCapabilityHolder<>(rl, holder_class, sup, entity_class, pred);
|
var type = new GeneralCapabilityHolder<>(rl, holder_class, sup, entity_class, pred);
|
||||||
return new CapValImpl<>(att.register(id, type::type), type);
|
return new CapValImpl<>(att.register(id, type::type), type);
|
||||||
}
|
}
|
||||||
|
|
||||||
public <E extends PlayerCapabilityTemplate<E>> AttVal.PlayerVal<E>
|
public <E extends PlayerCapabilityTemplate<E>> AttVal.PlayerVal<E>
|
||||||
player(String id, Class<E> holder_class, Supplier<E> sup, PlayerCapabilityHolder.NetworkFactory<E> network) {
|
player(String id, Class<E> holder_class, Supplier<E> sup, PlayerCapabilityHolder.NetworkFactory<E> network) {
|
||||||
ResourceLocation rl = new ResourceLocation(att.getNamespace(), id);
|
ResourceLocation rl = ResourceLocation.fromNamespaceAndPath(att.getNamespace(), id);
|
||||||
var type = new PlayerCapabilityHolder<>(rl, holder_class, sup, network);
|
var type = new PlayerCapabilityHolder<>(rl, holder_class, sup, network);
|
||||||
return new PlayerValImpl<>(att.register(id, type::type), type);
|
return new PlayerValImpl<>(att.register(id, type::type), type);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,65 +0,0 @@
|
|||||||
package dev.xkmc.l2core.serial.config;
|
|
||||||
|
|
||||||
import dev.xkmc.l2serial.serialization.SerialClass;
|
|
||||||
import net.minecraft.resources.ResourceLocation;
|
|
||||||
|
|
||||||
import java.util.*;
|
|
||||||
import java.util.function.BiConsumer;
|
|
||||||
import java.util.function.Function;
|
|
||||||
import java.util.function.Supplier;
|
|
||||||
|
|
||||||
@Deprecated(forRemoval = true)
|
|
||||||
@SerialClass
|
|
||||||
public class BaseConfig {
|
|
||||||
|
|
||||||
protected ResourceLocation id;
|
|
||||||
|
|
||||||
public ResourceLocation getID() {
|
|
||||||
return id;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* called by Config Merger after it's merged
|
|
||||||
*/
|
|
||||||
protected void postMerge() {
|
|
||||||
}
|
|
||||||
|
|
||||||
public static <T, C> HashSet<T> collectSet(List<C> list, Function<C, Set<T>> getter) {
|
|
||||||
return list.stream().reduce(new HashSet<T>(), (a, c) -> {
|
|
||||||
a.addAll(getter.apply(c));
|
|
||||||
return a;
|
|
||||||
}, (a, b) -> {
|
|
||||||
a.addAll(b);
|
|
||||||
return a;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public static <T, C> ArrayList<T> collectList(List<C> list, Function<C, List<T>> getter) {
|
|
||||||
return list.stream().reduce(new ArrayList<>(), (a, c) -> {
|
|
||||||
a.addAll(getter.apply(c));
|
|
||||||
return a;
|
|
||||||
}, (a, b) -> {
|
|
||||||
a.addAll(b);
|
|
||||||
return a;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public static <T, C, K> HashMap<K, T> collectMap(List<C> list, Function<C, Map<K, T>> getter, Supplier<T> gen, BiConsumer<T, T> merger) {
|
|
||||||
return list.stream().reduce(new HashMap<>(), (a, c) -> {
|
|
||||||
getter.apply(c).forEach((k, v) -> merger.accept(a.computeIfAbsent(k, e -> gen.get()), v));
|
|
||||||
return a;
|
|
||||||
}, (a, b) -> {
|
|
||||||
b.forEach((k, v) -> merger.accept(a.computeIfAbsent(k, e -> gen.get()), v));
|
|
||||||
return a;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public static <C, K, T> HashMap<K, T> overrideMap(List<C> list, Function<C, HashMap<K, T>> getter) {
|
|
||||||
HashMap<K, T> ans = new HashMap<>();
|
|
||||||
for (C c : list) {
|
|
||||||
ans.putAll(getter.apply(c));
|
|
||||||
}
|
|
||||||
return ans;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,29 +0,0 @@
|
|||||||
package dev.xkmc.l2core.serial.config;
|
|
||||||
|
|
||||||
import net.minecraft.resources.ResourceLocation;
|
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
public class BaseConfigType<T extends BaseConfig> {
|
|
||||||
|
|
||||||
public final Class<T> cls;
|
|
||||||
public final String id;
|
|
||||||
public final PacketHandlerWithConfig parent;
|
|
||||||
|
|
||||||
final Map<ResourceLocation, T> configs = new HashMap<>();
|
|
||||||
|
|
||||||
protected BaseConfigType(PacketHandlerWithConfig parent, String id, Class<T> cls) {
|
|
||||||
this.parent = parent;
|
|
||||||
this.id = id;
|
|
||||||
this.cls = cls;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void beforeReload() {
|
|
||||||
configs.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void afterReload() {
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
package dev.xkmc.l2core.serial.config;
|
|
||||||
|
|
||||||
public enum CollectType {
|
|
||||||
OVERWRITE, COLLECT, MAP_COLLECT, MAP_OVERWRITE
|
|
||||||
}
|
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
package dev.xkmc.l2core.serial.config;
|
|
||||||
|
|
||||||
import java.lang.annotation.Documented;
|
|
||||||
import java.lang.annotation.Retention;
|
|
||||||
import java.lang.annotation.Target;
|
|
||||||
|
|
||||||
import static java.lang.annotation.ElementType.FIELD;
|
|
||||||
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
|
||||||
|
|
||||||
@Documented
|
|
||||||
@Retention(RUNTIME)
|
|
||||||
@Target(FIELD)
|
|
||||||
public @interface ConfigCollect {
|
|
||||||
|
|
||||||
CollectType value();
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,69 +0,0 @@
|
|||||||
package dev.xkmc.l2core.serial.config;
|
|
||||||
|
|
||||||
import com.google.gson.JsonElement;
|
|
||||||
import dev.xkmc.l2serial.serialization.codec.JsonCodec;
|
|
||||||
import net.minecraft.data.CachedOutput;
|
|
||||||
import net.minecraft.data.DataGenerator;
|
|
||||||
import net.minecraft.data.DataProvider;
|
|
||||||
import net.minecraft.resources.ResourceLocation;
|
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
|
||||||
import java.nio.file.Path;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.concurrent.CompletableFuture;
|
|
||||||
|
|
||||||
public abstract class ConfigDataProvider implements DataProvider {
|
|
||||||
|
|
||||||
private final DataGenerator generator;
|
|
||||||
private final String name;
|
|
||||||
|
|
||||||
private final Map<String, ConfigEntry<?>> map = new HashMap<>();
|
|
||||||
|
|
||||||
public ConfigDataProvider(DataGenerator generator, String name) {
|
|
||||||
this.generator = generator;
|
|
||||||
this.name = name;
|
|
||||||
}
|
|
||||||
|
|
||||||
public abstract void add(Collector map);
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public CompletableFuture<?> run(CachedOutput cache) {
|
|
||||||
Path folder = generator.getPackOutput().getOutputFolder();
|
|
||||||
add(new Collector(map));
|
|
||||||
List<CompletableFuture<?>> list = new ArrayList<>();
|
|
||||||
map.forEach((k, v) -> {
|
|
||||||
JsonElement elem = v.serialize();
|
|
||||||
if (elem != null) {
|
|
||||||
Path path = folder.resolve(k + ".json");
|
|
||||||
list.add(DataProvider.saveStable(cache, elem, path));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return CompletableFuture.allOf(list.toArray(CompletableFuture[]::new));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getName() {
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
|
|
||||||
public record Collector(Map<String, ConfigEntry<?>> map) {
|
|
||||||
|
|
||||||
public <T extends BaseConfig> void add(ConfigTypeEntry<T> type, ResourceLocation id, T config) {
|
|
||||||
map.put(type.asPath(id), new ConfigEntry<>(type, id, config));
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public record ConfigEntry<T extends BaseConfig>(ConfigTypeEntry<T> type, ResourceLocation id, T config) {
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
public JsonElement serialize() {
|
|
||||||
return JsonCodec.toJson(config, type.cls());
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
package dev.xkmc.l2core.serial.config;
|
|
||||||
|
|
||||||
import java.lang.annotation.Retention;
|
|
||||||
import java.lang.annotation.RetentionPolicy;
|
|
||||||
|
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
|
||||||
public @interface ConfigLoadOnStart {
|
|
||||||
}
|
|
||||||
@@ -1,98 +0,0 @@
|
|||||||
package dev.xkmc.l2core.serial.config;
|
|
||||||
|
|
||||||
import dev.xkmc.l2serial.serialization.type_cache.ClassCache;
|
|
||||||
import dev.xkmc.l2serial.serialization.type_cache.FieldCache;
|
|
||||||
import dev.xkmc.l2serial.serialization.type_cache.TypeInfo;
|
|
||||||
import dev.xkmc.l2serial.util.Wrappers;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
@SuppressWarnings({"rawtypes", "unchecked"})
|
|
||||||
public class ConfigMerger<T extends BaseConfig> {
|
|
||||||
|
|
||||||
private final ClassCache cache;
|
|
||||||
|
|
||||||
public ConfigMerger(Class<T> cls) {
|
|
||||||
this.cache = ClassCache.get(cls);
|
|
||||||
}
|
|
||||||
|
|
||||||
public T merge(List<T> list) throws Exception {
|
|
||||||
T ans = (T) cache.create();
|
|
||||||
for (FieldCache field : cache.getFields()) {
|
|
||||||
ConfigCollect collect = field.getAnnotation(ConfigCollect.class);
|
|
||||||
if (collect == null) continue;
|
|
||||||
switch (collect.value()) {
|
|
||||||
case OVERWRITE -> {
|
|
||||||
int n = list.size();
|
|
||||||
if (n > 0) {
|
|
||||||
field.set(ans, field.get(list.get(n - 1)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case COLLECT -> {
|
|
||||||
TypeInfo info = field.toType();
|
|
||||||
assert Collection.class.isAssignableFrom(info.getAsClass());
|
|
||||||
Collection val = (Collection) info.toCache().create();
|
|
||||||
for (T t : list) {
|
|
||||||
val.addAll((Collection) field.get(t));
|
|
||||||
}
|
|
||||||
field.set(ans, val);
|
|
||||||
}
|
|
||||||
case MAP_COLLECT -> {
|
|
||||||
TypeInfo info = field.toType();
|
|
||||||
TypeInfo sub = info.getGenericType(1);
|
|
||||||
assert Map.class.isAssignableFrom(info.getAsClass());
|
|
||||||
Map val = (Map) info.toCache().create();
|
|
||||||
|
|
||||||
if (Collection.class.isAssignableFrom(sub.getAsClass())) {
|
|
||||||
for (T t : list) {
|
|
||||||
Map map = (Map) field.get(t);
|
|
||||||
for (Object e : map.entrySet()) {
|
|
||||||
Map.Entry ent = (Map.Entry) e;
|
|
||||||
Collection col;
|
|
||||||
if (val.containsKey(ent.getKey())) {
|
|
||||||
col = (Collection) val.get(ent.getKey());
|
|
||||||
} else {
|
|
||||||
val.put(ent.getKey(), col = (Collection) sub.toCache().create());
|
|
||||||
}
|
|
||||||
col.addAll((Collection) ent.getValue());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (Map.class.isAssignableFrom(sub.getAsClass())) {
|
|
||||||
for (T t : list) {
|
|
||||||
Map map = (Map) field.get(t);
|
|
||||||
for (Object e : map.entrySet()) {
|
|
||||||
Map.Entry ent = (Map.Entry) e;
|
|
||||||
Map col;
|
|
||||||
if (val.containsKey(ent.getKey())) {
|
|
||||||
col = (Map) val.get(ent.getKey());
|
|
||||||
} else {
|
|
||||||
val.put(ent.getKey(), col = (Map) sub.toCache().create());
|
|
||||||
}
|
|
||||||
col.putAll((Map) ent.getValue());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
field.set(ans, val);
|
|
||||||
}
|
|
||||||
case MAP_OVERWRITE -> {
|
|
||||||
TypeInfo info = field.toType();
|
|
||||||
assert Map.class.isAssignableFrom(info.getAsClass());
|
|
||||||
Map val = (Map) info.toCache().create();
|
|
||||||
for (T t : list) {
|
|
||||||
val.putAll((Map) field.get(t));
|
|
||||||
}
|
|
||||||
field.set(ans, val);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ans.postMerge();
|
|
||||||
return ans;
|
|
||||||
}
|
|
||||||
|
|
||||||
public T apply(Collection<T> s) {
|
|
||||||
return Wrappers.get(() -> this.merge(new ArrayList<>(s)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,36 +0,0 @@
|
|||||||
package dev.xkmc.l2core.serial.config;
|
|
||||||
|
|
||||||
import dev.xkmc.l2serial.util.Wrappers;
|
|
||||||
import net.minecraft.resources.ResourceLocation;
|
|
||||||
|
|
||||||
import java.util.Collection;
|
|
||||||
|
|
||||||
public record ConfigTypeEntry<T extends BaseConfig>(PacketHandlerWithConfig channel, String name, Class<T> cls) {
|
|
||||||
|
|
||||||
public ConfigTypeEntry(PacketHandlerWithConfig channel, String name, Class<T> cls) {
|
|
||||||
this.channel = channel;
|
|
||||||
this.name = name;
|
|
||||||
this.cls = cls;
|
|
||||||
channel.addCachedConfig(name, cls);
|
|
||||||
}
|
|
||||||
|
|
||||||
public String asPath(ResourceLocation rl) {
|
|
||||||
return "data/" + rl.getNamespace() + "/" + channel.config_path + "/" + name + "/" + rl.getPath();
|
|
||||||
}
|
|
||||||
|
|
||||||
public T getMerged() {
|
|
||||||
MergedConfigType<T> type = Wrappers.cast(channel.types.get(name));
|
|
||||||
return type.load();
|
|
||||||
}
|
|
||||||
|
|
||||||
public Collection<T> getAll() {
|
|
||||||
MergedConfigType<T> type = Wrappers.cast(channel.types.get(name));
|
|
||||||
return type.configs.values();
|
|
||||||
}
|
|
||||||
|
|
||||||
public T getEntry(ResourceLocation id) {
|
|
||||||
MergedConfigType<T> type = Wrappers.cast(channel.types.get(name));
|
|
||||||
return type.configs.get(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,30 +0,0 @@
|
|||||||
package dev.xkmc.l2core.serial.config;
|
|
||||||
|
|
||||||
import net.minecraft.resources.ResourceLocation;
|
|
||||||
|
|
||||||
public class MergedConfigType<T extends BaseConfig> extends BaseConfigType<T> {
|
|
||||||
|
|
||||||
private T result;
|
|
||||||
|
|
||||||
MergedConfigType(PacketHandlerWithConfig parent, String id, Class<T> cls) {
|
|
||||||
super(parent, id, cls);
|
|
||||||
}
|
|
||||||
|
|
||||||
T load() {
|
|
||||||
if (result != null) {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
result = new ConfigMerger<>(cls).apply(configs.values());
|
|
||||||
result.id = new ResourceLocation(parent.name, id);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void afterReload() {
|
|
||||||
result = null;
|
|
||||||
if (cls.isAnnotationPresent(ConfigLoadOnStart.class)) {
|
|
||||||
load();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,143 +0,0 @@
|
|||||||
package dev.xkmc.l2core.serial.config;
|
|
||||||
|
|
||||||
import com.google.gson.Gson;
|
|
||||||
import com.google.gson.JsonElement;
|
|
||||||
import dev.xkmc.l2core.init.L2Core;
|
|
||||||
import dev.xkmc.l2serial.network.PacketHandler;
|
|
||||||
import dev.xkmc.l2serial.serialization.codec.JsonCodec;
|
|
||||||
import dev.xkmc.l2serial.util.Wrappers;
|
|
||||||
import net.minecraft.resources.ResourceLocation;
|
|
||||||
import net.minecraft.server.packs.resources.ResourceManager;
|
|
||||||
import net.minecraft.server.packs.resources.SimpleJsonResourceReloadListener;
|
|
||||||
import net.minecraft.util.profiling.ProfilerFiller;
|
|
||||||
import net.neoforged.fml.ModList;
|
|
||||||
import net.neoforged.neoforge.event.AddReloadListenerEvent;
|
|
||||||
import net.neoforged.neoforge.event.OnDatapackSyncEvent;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
|
||||||
import java.util.function.Function;
|
|
||||||
|
|
||||||
@SuppressWarnings("unused")
|
|
||||||
public class PacketHandlerWithConfig extends PacketHandler {
|
|
||||||
|
|
||||||
static final Map<String, PacketHandlerWithConfig> INTERNAL = new ConcurrentHashMap<>();
|
|
||||||
|
|
||||||
public static void onDatapackSync(OnDatapackSyncEvent event) {
|
|
||||||
for (PacketHandlerWithConfig handler : INTERNAL.values()) {
|
|
||||||
SyncPacket packet = new SyncPacket(handler.name, handler.configs);
|
|
||||||
if (event.getPlayer() == null) L2Core.PACKET_HANDLER.toAllClient(packet);
|
|
||||||
else L2Core.PACKET_HANDLER.toClientPlayer(packet, event.getPlayer());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void addReloadListeners(AddReloadListenerEvent event) {
|
|
||||||
for (PacketHandlerWithConfig handler : INTERNAL.values()) {
|
|
||||||
if (handler.listener != null)
|
|
||||||
event.addListener(handler.listener);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public ArrayList<ConfigInstance> configs = new ArrayList<>();
|
|
||||||
|
|
||||||
public final String config_path;
|
|
||||||
|
|
||||||
final ConfigReloadListener listener;
|
|
||||||
final List<Runnable> listener_before = new ArrayList<>();
|
|
||||||
final List<Runnable> listener_after = new ArrayList<>();
|
|
||||||
final Map<String, BaseConfigType<?>> types = new HashMap<>();
|
|
||||||
|
|
||||||
@SafeVarargs
|
|
||||||
public PacketHandlerWithConfig(String id, int version, Function<PacketHandler, PacketConfiguration<?>>... values) {
|
|
||||||
super(id, version, values);
|
|
||||||
INTERNAL.put(id, this);
|
|
||||||
config_path = id + "_config";
|
|
||||||
listener = new ConfigReloadListener(config_path);
|
|
||||||
listener_before.add(configs::clear);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void addBeforeReloadListener(Runnable runnable) {
|
|
||||||
listener_before.add(runnable);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void addAfterReloadListener(Runnable runnable) {
|
|
||||||
listener_after.add(runnable);
|
|
||||||
}
|
|
||||||
|
|
||||||
public <T extends BaseConfig> void addConfig(String id, Class<T> loader) {
|
|
||||||
BaseConfigType<T> c = new BaseConfigType<>(this, id, loader);
|
|
||||||
types.put(id, c);
|
|
||||||
addBeforeReloadListener(c::beforeReload);
|
|
||||||
addAfterReloadListener(c::afterReload);
|
|
||||||
}
|
|
||||||
|
|
||||||
public <T extends BaseConfig> void addCachedConfig(String id, Class<T> loader) {
|
|
||||||
MergedConfigType<T> c = new MergedConfigType<>(this, id, loader);
|
|
||||||
types.put(id, c);
|
|
||||||
addBeforeReloadListener(c::beforeReload);
|
|
||||||
addAfterReloadListener(c::afterReload);
|
|
||||||
}
|
|
||||||
|
|
||||||
<T extends BaseConfig> T getCachedConfig(String id) {
|
|
||||||
MergedConfigType<T> type = Wrappers.cast(types.get(id));
|
|
||||||
return type.load();
|
|
||||||
}
|
|
||||||
|
|
||||||
class ConfigReloadListener extends SimpleJsonResourceReloadListener {
|
|
||||||
|
|
||||||
public ConfigReloadListener(String path) {
|
|
||||||
super(new Gson(), path);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void apply(Map<ResourceLocation, JsonElement> map, ResourceManager manager, ProfilerFiller filler) {
|
|
||||||
listener_before.forEach(Runnable::run);
|
|
||||||
map.forEach((k, v) -> {
|
|
||||||
if (!k.getNamespace().startsWith("_")) {
|
|
||||||
if (!ModList.get().isLoaded(k.getNamespace())) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
String id = k.getPath().split("/")[0];
|
|
||||||
if (types.containsKey(id)) {
|
|
||||||
String name = k.getPath().substring(id.length() + 1);
|
|
||||||
ResourceLocation nk = new ResourceLocation(k.getNamespace(), name);
|
|
||||||
addJson(types.get(id), nk, v);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
listener_after.forEach(Runnable::run);
|
|
||||||
}
|
|
||||||
|
|
||||||
private <T extends BaseConfig> void addJson(BaseConfigType<T> type, ResourceLocation k, JsonElement v) {
|
|
||||||
T config = JsonCodec.from(v, type.cls, null);
|
|
||||||
if (config != null) {
|
|
||||||
addConfig(type, k, config);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private <T extends BaseConfig> void addConfig(BaseConfigType<T> type, ResourceLocation k, T config) {
|
|
||||||
config.id = k;
|
|
||||||
type.configs.put(k, config);
|
|
||||||
configs.add(new ConfigInstance(type.id, k, config));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Called on client side only
|
|
||||||
*/
|
|
||||||
public void apply(ArrayList<ConfigInstance> list) {
|
|
||||||
listener_before.forEach(Runnable::run);
|
|
||||||
for (var e : list) {
|
|
||||||
addConfig(types.get(e.name), e.id(), Wrappers.cast(e.config));
|
|
||||||
}
|
|
||||||
listener_after.forEach(Runnable::run);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public record ConfigInstance(String name, ResourceLocation id, BaseConfig config) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,48 +0,0 @@
|
|||||||
package dev.xkmc.l2core.serial.config;
|
|
||||||
|
|
||||||
import com.google.gson.JsonElement;
|
|
||||||
import dev.xkmc.l2serial.serialization.codec.JsonCodec;
|
|
||||||
import net.minecraft.data.CachedOutput;
|
|
||||||
import net.minecraft.data.DataGenerator;
|
|
||||||
import net.minecraft.data.DataProvider;
|
|
||||||
|
|
||||||
import java.nio.file.Path;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.concurrent.CompletableFuture;
|
|
||||||
import java.util.function.BiConsumer;
|
|
||||||
|
|
||||||
public abstract class RecordDataProvider implements DataProvider {
|
|
||||||
private final DataGenerator generator;
|
|
||||||
private final String name;
|
|
||||||
private final Map<String, Record> map = new HashMap<>();
|
|
||||||
|
|
||||||
public RecordDataProvider(DataGenerator generator, String name) {
|
|
||||||
this.generator = generator;
|
|
||||||
this.name = name;
|
|
||||||
}
|
|
||||||
|
|
||||||
public abstract void add(BiConsumer<String, Record> map);
|
|
||||||
|
|
||||||
public CompletableFuture<?> run(CachedOutput cache) {
|
|
||||||
Path folder = this.generator.getPackOutput().getOutputFolder();
|
|
||||||
this.add(this.map::put);
|
|
||||||
List<CompletableFuture<?>> list = new ArrayList<>();
|
|
||||||
this.map.forEach((k, v) -> {
|
|
||||||
JsonElement elem = JsonCodec.toJson(v);
|
|
||||||
if (elem != null) {
|
|
||||||
Path path = folder.resolve("data/" + k + ".json");
|
|
||||||
list.add(DataProvider.saveStable(cache, elem, path));
|
|
||||||
}
|
|
||||||
|
|
||||||
});
|
|
||||||
return CompletableFuture.allOf(list.toArray(CompletableFuture[]::new));
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getName() {
|
|
||||||
return this.name;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
package dev.xkmc.l2core.serial.config;
|
|
||||||
|
|
||||||
import dev.xkmc.l2serial.network.SerialPacketBase;
|
|
||||||
import net.minecraft.world.entity.player.Player;
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
|
|
||||||
public record SyncPacket(String id, ArrayList<PacketHandlerWithConfig.ConfigInstance> map)
|
|
||||||
implements SerialPacketBase<SyncPacket> {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void handle(@Nullable Player player) {
|
|
||||||
if (map != null) {
|
|
||||||
var handler = PacketHandlerWithConfig.INTERNAL.get(id);
|
|
||||||
handler.listener.apply(map);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
@MethodsReturnNonnullByDefault
|
|
||||||
@ParametersAreNonnullByDefault
|
|
||||||
|
|
||||||
package dev.xkmc.l2core.serial.config;
|
|
||||||
|
|
||||||
import net.minecraft.MethodsReturnNonnullByDefault;
|
|
||||||
|
|
||||||
import javax.annotation.ParametersAreNonnullByDefault;
|
|
||||||
@@ -1,8 +1,9 @@
|
|||||||
package dev.xkmc.l2core.serial.recipe;
|
package dev.xkmc.l2core.serial.recipe;
|
||||||
|
|
||||||
import com.mojang.serialization.Codec;
|
import com.mojang.serialization.MapCodec;
|
||||||
import net.minecraft.MethodsReturnNonnullByDefault;
|
import net.minecraft.MethodsReturnNonnullByDefault;
|
||||||
import net.minecraft.network.FriendlyByteBuf;
|
import net.minecraft.network.RegistryFriendlyByteBuf;
|
||||||
|
import net.minecraft.network.codec.StreamCodec;
|
||||||
import net.minecraft.world.item.ItemStack;
|
import net.minecraft.world.item.ItemStack;
|
||||||
import net.minecraft.world.item.crafting.CraftingBookCategory;
|
import net.minecraft.world.item.crafting.CraftingBookCategory;
|
||||||
import net.minecraft.world.item.crafting.ShapedRecipe;
|
import net.minecraft.world.item.crafting.ShapedRecipe;
|
||||||
@@ -41,12 +42,13 @@ public abstract class AbstractShapedRecipe<T extends AbstractShapedRecipe<T>> ex
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Codec<ShapedRecipe> codec() {
|
public MapCodec<ShapedRecipe> codec() {
|
||||||
return super.codec().xmap(factory::map, e -> e);
|
return super.codec().xmap(factory::map, e -> e);
|
||||||
}
|
}
|
||||||
|
|
||||||
public T fromNetwork(FriendlyByteBuf obj) {
|
@Override
|
||||||
return factory.map(super.fromNetwork(obj));
|
public StreamCodec<RegistryFriendlyByteBuf, ShapedRecipe> streamCodec() {
|
||||||
|
return super.streamCodec().map(factory::map, e -> e);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,10 @@
|
|||||||
package dev.xkmc.l2core.serial.recipe;
|
package dev.xkmc.l2core.serial.recipe;
|
||||||
|
|
||||||
import com.mojang.serialization.Codec;
|
import com.mojang.serialization.MapCodec;
|
||||||
import net.minecraft.MethodsReturnNonnullByDefault;
|
import net.minecraft.MethodsReturnNonnullByDefault;
|
||||||
import net.minecraft.core.NonNullList;
|
import net.minecraft.core.NonNullList;
|
||||||
import net.minecraft.network.FriendlyByteBuf;
|
import net.minecraft.network.RegistryFriendlyByteBuf;
|
||||||
|
import net.minecraft.network.codec.StreamCodec;
|
||||||
import net.minecraft.world.item.ItemStack;
|
import net.minecraft.world.item.ItemStack;
|
||||||
import net.minecraft.world.item.crafting.CraftingBookCategory;
|
import net.minecraft.world.item.crafting.CraftingBookCategory;
|
||||||
import net.minecraft.world.item.crafting.Ingredient;
|
import net.minecraft.world.item.crafting.Ingredient;
|
||||||
@@ -47,12 +48,13 @@ public abstract class AbstractShapelessRecipe<T extends AbstractShapelessRecipe<
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Codec<ShapelessRecipe> codec() {
|
public MapCodec<ShapelessRecipe> codec() {
|
||||||
return super.codec().xmap(factory::map, e -> e);
|
return super.codec().xmap(factory::map, e -> e);
|
||||||
}
|
}
|
||||||
|
|
||||||
public T fromNetwork(FriendlyByteBuf obj) {
|
@Override
|
||||||
return factory.map(super.fromNetwork(obj));
|
public StreamCodec<RegistryFriendlyByteBuf, ShapelessRecipe> streamCodec() {
|
||||||
|
return super.streamCodec().map(factory::map, e -> e);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,10 @@
|
|||||||
package dev.xkmc.l2core.serial.recipe;
|
package dev.xkmc.l2core.serial.recipe;
|
||||||
|
|
||||||
import com.mojang.serialization.Codec;
|
import com.mojang.serialization.Codec;
|
||||||
|
import com.mojang.serialization.MapCodec;
|
||||||
import net.minecraft.MethodsReturnNonnullByDefault;
|
import net.minecraft.MethodsReturnNonnullByDefault;
|
||||||
import net.minecraft.network.FriendlyByteBuf;
|
import net.minecraft.network.RegistryFriendlyByteBuf;
|
||||||
|
import net.minecraft.network.codec.StreamCodec;
|
||||||
import net.minecraft.world.item.ItemStack;
|
import net.minecraft.world.item.ItemStack;
|
||||||
import net.minecraft.world.item.crafting.Ingredient;
|
import net.minecraft.world.item.crafting.Ingredient;
|
||||||
import net.minecraft.world.item.crafting.SmithingTransformRecipe;
|
import net.minecraft.world.item.crafting.SmithingTransformRecipe;
|
||||||
@@ -42,12 +44,13 @@ public abstract class AbstractSmithingRecipe<T extends AbstractSmithingRecipe<T>
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Codec<SmithingTransformRecipe> codec() {
|
public MapCodec<SmithingTransformRecipe> codec() {
|
||||||
return super.codec().xmap(factory::map, e -> e);
|
return super.codec().xmap(factory::map, e -> e);
|
||||||
}
|
}
|
||||||
|
|
||||||
public T fromNetwork(FriendlyByteBuf obj) {
|
@Override
|
||||||
return factory.map(super.fromNetwork(obj));
|
public StreamCodec<RegistryFriendlyByteBuf, SmithingTransformRecipe> streamCodec() {
|
||||||
|
return super.streamCodec().map(factory::map, e -> e);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,13 +4,14 @@ import net.minecraft.core.RegistryAccess;
|
|||||||
import net.minecraft.world.Container;
|
import net.minecraft.world.Container;
|
||||||
import net.minecraft.world.item.ItemStack;
|
import net.minecraft.world.item.ItemStack;
|
||||||
import net.minecraft.world.item.crafting.Recipe;
|
import net.minecraft.world.item.crafting.Recipe;
|
||||||
|
import net.minecraft.world.item.crafting.RecipeInput;
|
||||||
import net.minecraft.world.item.crafting.RecipeSerializer;
|
import net.minecraft.world.item.crafting.RecipeSerializer;
|
||||||
import net.minecraft.world.item.crafting.RecipeType;
|
import net.minecraft.world.item.crafting.RecipeType;
|
||||||
import net.minecraft.world.level.Level;
|
import net.minecraft.world.level.Level;
|
||||||
|
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
public abstract class BaseRecipe<Rec extends SRec, SRec extends BaseRecipe<?, SRec, Inv>, Inv extends Container> implements Recipe<Inv> {
|
public abstract class BaseRecipe<Rec extends SRec, SRec extends BaseRecipe<?, SRec, Inv>, Inv extends RecipeInput> implements Recipe<Inv> {
|
||||||
|
|
||||||
private final RecType<Rec, SRec, Inv> factory;
|
private final RecType<Rec, SRec, Inv> factory;
|
||||||
|
|
||||||
@@ -39,11 +40,7 @@ public abstract class BaseRecipe<Rec extends SRec, SRec extends BaseRecipe<?, SR
|
|||||||
return factory.type.get();
|
return factory.type.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
public interface RecInv<R extends BaseRecipe<?, R, ?>> extends Container {
|
public static class RecType<Rec extends SRec, SRec extends BaseRecipe<?, SRec, Inv>, Inv extends RecipeInput> extends RecSerializer<Rec, Inv> {
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class RecType<Rec extends SRec, SRec extends BaseRecipe<?, SRec, Inv>, Inv extends Container> extends RecSerializer<Rec, Inv> {
|
|
||||||
|
|
||||||
public final Supplier<RecipeType<SRec>> type;
|
public final Supplier<RecipeType<SRec>> type;
|
||||||
|
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import net.minecraft.data.recipes.RecipeOutput;
|
|||||||
import net.minecraft.resources.ResourceLocation;
|
import net.minecraft.resources.ResourceLocation;
|
||||||
import net.minecraft.world.Container;
|
import net.minecraft.world.Container;
|
||||||
import net.minecraft.world.item.Item;
|
import net.minecraft.world.item.Item;
|
||||||
|
import net.minecraft.world.item.crafting.RecipeInput;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
@@ -20,7 +21,7 @@ public class BaseRecipeBuilder<
|
|||||||
T extends BaseRecipeBuilder<T, Rec, SRec, Inv>,
|
T extends BaseRecipeBuilder<T, Rec, SRec, Inv>,
|
||||||
Rec extends SRec,
|
Rec extends SRec,
|
||||||
SRec extends BaseRecipe<?, SRec, Inv>,
|
SRec extends BaseRecipe<?, SRec, Inv>,
|
||||||
Inv extends Container
|
Inv extends RecipeInput
|
||||||
> implements RecipeBuilder {
|
> implements RecipeBuilder {
|
||||||
|
|
||||||
protected final BaseRecipe.RecType<Rec, SRec, Inv> type;
|
protected final BaseRecipe.RecType<Rec, SRec, Inv> type;
|
||||||
@@ -63,7 +64,7 @@ public class BaseRecipeBuilder<
|
|||||||
.rewards(AdvancementRewards.Builder.recipe(id))
|
.rewards(AdvancementRewards.Builder.recipe(id))
|
||||||
.requirements(AdvancementRequirements.Strategy.OR);
|
.requirements(AdvancementRequirements.Strategy.OR);
|
||||||
this.criteria.forEach(builder::addCriterion);
|
this.criteria.forEach(builder::addCriterion);
|
||||||
id = new ResourceLocation(id.getNamespace(), "recipes/" +
|
id = ResourceLocation.fromNamespaceAndPath(id.getNamespace(), "recipes/" +
|
||||||
BuiltInRegistries.RECIPE_SERIALIZER.getKey(type).getPath() + "/" + id.getPath());
|
BuiltInRegistries.RECIPE_SERIALIZER.getKey(type).getPath() + "/" + id.getPath());
|
||||||
pvd.accept(id, recipe, builder.build(id));
|
pvd.accept(id, recipe, builder.build(id));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package dev.xkmc.l2core.serial.recipe;
|
|||||||
|
|
||||||
import net.minecraft.advancements.Advancement;
|
import net.minecraft.advancements.Advancement;
|
||||||
import net.minecraft.advancements.AdvancementHolder;
|
import net.minecraft.advancements.AdvancementHolder;
|
||||||
|
import net.minecraft.core.component.DataComponentType;
|
||||||
import net.minecraft.data.recipes.RecipeOutput;
|
import net.minecraft.data.recipes.RecipeOutput;
|
||||||
import net.minecraft.resources.ResourceLocation;
|
import net.minecraft.resources.ResourceLocation;
|
||||||
import net.minecraft.world.item.ItemStack;
|
import net.minecraft.world.item.ItemStack;
|
||||||
@@ -21,10 +22,10 @@ public record NBTRecipeWrapper(RecipeOutput pvd, ItemStack stack) implements Rec
|
|||||||
@Override
|
@Override
|
||||||
public void accept(ResourceLocation id, Recipe<?> recipe, @Nullable AdvancementHolder advancement, ICondition... conditions) {
|
public void accept(ResourceLocation id, Recipe<?> recipe, @Nullable AdvancementHolder advancement, ICondition... conditions) {
|
||||||
if (recipe instanceof ShapedRecipe r) {
|
if (recipe instanceof ShapedRecipe r) {
|
||||||
r.result.setTag(stack.getTag());
|
r.result.applyComponents(stack.getComponents());
|
||||||
}
|
}
|
||||||
if (recipe instanceof ShapelessRecipe r) {
|
if (recipe instanceof ShapelessRecipe r) {
|
||||||
r.result.setTag(stack.getTag());
|
r.result.applyComponents(stack.getComponents());
|
||||||
}
|
}
|
||||||
pvd.accept(id, recipe, advancement, conditions);
|
pvd.accept(id, recipe, advancement, conditions);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import net.neoforged.api.distmarker.Dist;
|
|||||||
import net.neoforged.fml.loading.FMLEnvironment;
|
import net.neoforged.fml.loading.FMLEnvironment;
|
||||||
import net.neoforged.neoforge.server.ServerLifecycleHooks;
|
import net.neoforged.neoforge.server.ServerLifecycleHooks;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
||||||
public class Proxy {
|
public class Proxy {
|
||||||
@@ -23,6 +24,7 @@ public class Proxy {
|
|||||||
return Optional.ofNullable(ServerLifecycleHooks.getCurrentServer());
|
return Optional.ofNullable(ServerLifecycleHooks.getCurrentServer());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
public static LocalPlayer getClientPlayer() {
|
public static LocalPlayer getClientPlayer() {
|
||||||
return Minecraft.getInstance().player;
|
return Minecraft.getInstance().player;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user