From 40203055f8e42df818f12405e8996c6b9b949d5b Mon Sep 17 00:00:00 2001 From: Leclowndu93150 Date: Tue, 23 Sep 2025 23:17:19 +0200 Subject: [PATCH 01/20] progress --- neoforge-main/build.gradle.kts | 13 ++- .../crafting/client/ClientPacketHandler.java | 41 +++----- .../crafting/data/CCAttachments.java | 50 ++++------ .../crafting/events/WorldEventHandler.java | 90 ++++++++++-------- .../crafting/field/ActiveWorldFields.java | 62 +++++-------- .../crafting/field/MiniaturizationField.java | 93 +++++++++++++------ .../network/ClientFieldUnwatchPacket.java | 61 ++++++------ .../network/ClientFieldWatchPacket.java | 83 ++++++++++------- .../crafting/network/NetworkHandler.java | 4 +- .../projector/FieldProjectorBlock.java | 47 ++++++---- 10 files changed, 292 insertions(+), 252 deletions(-) diff --git a/neoforge-main/build.gradle.kts b/neoforge-main/build.gradle.kts index 34e9142..05f0f29 100644 --- a/neoforge-main/build.gradle.kts +++ b/neoforge-main/build.gradle.kts @@ -62,10 +62,10 @@ neoForge { logLevel.set(org.slf4j.event.Level.DEBUG) sourceSet = project.sourceSets.main - // JetBrains Runtime Hotswap - if (!System.getenv().containsKey("CI")) { - jvmArgument("-XX:+AllowEnhancedClassRedefinition") - } +// // JetBrains Runtime Hotswap +// if (!System.getenv().containsKey("CI")) { +// jvmArgument("-XX:+AllowEnhancedClassRedefinition") +// } } create("client") { @@ -121,6 +121,9 @@ repositories { password = project.findProperty("gpr.token") as String? ?: System.getenv("GITHUB_TOKEN") } } + maven("https://cursemaven.com"){ + name = "CurseMaven" + } } dependencies { @@ -135,6 +138,8 @@ dependencies { testImplementation("org.junit.jupiter:junit-jupiter:5.7.1") testRuntimeOnly("org.junit.platform:junit-platform-launcher") + implementation("curse.maven:jei-238222:7024953") + jarJar(libs.rxjava) jarJar(libs.reactivestreams) } diff --git a/neoforge-main/src/main/java/dev/compactmods/crafting/client/ClientPacketHandler.java b/neoforge-main/src/main/java/dev/compactmods/crafting/client/ClientPacketHandler.java index b2aa98c..798c39b 100644 --- a/neoforge-main/src/main/java/dev/compactmods/crafting/client/ClientPacketHandler.java +++ b/neoforge-main/src/main/java/dev/compactmods/crafting/client/ClientPacketHandler.java @@ -25,8 +25,7 @@ public static void handleFieldActivation(IMiniaturizationField { -//// fields.setLevel(mc.level); -//// CompactCrafting.LOGGER.debug("Registering field on client"); -//// final IMiniaturizationField fieldRegistered = fields.registerField(field); -//// -//// CompactCrafting.LOGGER.debug("Setting field references"); -//// -//// field.getProjectorPositions() -//// .map(mc.level::getBlockEntity) -//// .map(tile -> (FieldProjectorEntity) tile) -//// .filter(Objects::nonNull) -//// .forEach(tile -> { -//// final BlockState state = tile.getBlockState(); -//// tile.setFieldRef(fieldRegistered.getRef()); -//// }); -//// }); -// } + public static void handleFieldData(CompoundTag fieldData) { + Minecraft mc = Minecraft.getInstance(); + if (mc.level == null) + return; + + MiniaturizationField field = MiniaturizationField.fromNBT(mc.level, fieldData); + mc.level.getData(CCAttachments.ACTIVE_FIELDS).registerField(field); + } public static void removeField(BlockPos fieldCenter) { Minecraft mc = Minecraft.getInstance(); @@ -112,7 +92,8 @@ public static void changeFieldRecipe(BlockPos center, RecipeHolder> ATTACHMENT_TYPES = DeferredRegister.create(NeoForgeRegistries.ATTACHMENT_TYPES, CompactCrafting.MOD_ID); DeferredHolder, AttachmentType> ACTIVE_FIELDS = ATTACHMENT_TYPES - .register("active_fields", () -> AttachmentType.builder((holder) -> ActiveWorldFields.create((Level) holder)).build()); - - static IAttachmentSerializer holderWith(Codec codec, BiConsumer setter) { - return new IAttachmentSerializer<>() { - @Override - public @NotNull T read(@NotNull IAttachmentHolder holder, @NotNull Tag tag, HolderLookup.@NotNull Provider provider) { - var parse = codec.parse(provider.createSerializationContext(NbtOps.INSTANCE), tag); - if (parse.error().isPresent()) { - throw new RuntimeException(parse.error().get().toString()); - } - if (parse.result().isEmpty()) - throw new RuntimeException("Result not present"); - - var data = parse.result().get(); - setter.accept(data, holder); - return data; + .register("active_fields", () -> AttachmentType.builder((holder) -> ActiveWorldFields.create((Level) holder)) + .serialize(new ActiveWorldFieldsSerializer()) + .build()); + + class ActiveWorldFieldsSerializer implements IAttachmentSerializer { + @Override + public @NotNull ActiveWorldFields read(@NotNull IAttachmentHolder holder, @NotNull Tag tag, HolderLookup.@NotNull Provider provider) { + Level level = (Level) holder; + ActiveWorldFields fields = ActiveWorldFields.create(level); + if (tag instanceof ListTag listTag) { + fields.deserializeNBT(listTag); } + return fields; + } - @Override - public Tag write(@NotNull T attachment, HolderLookup.@NotNull Provider provider) { - var encode = codec.encodeStart(provider.createSerializationContext(NbtOps.INSTANCE), attachment); - if (encode.error().isPresent()) { - throw new RuntimeException(encode.error().get().toString()); - } - if (encode.result().isEmpty()) - throw new RuntimeException("Result not present"); - - return encode.result().get(); - } - }; + @Override + public Tag write(@NotNull ActiveWorldFields attachment, HolderLookup.@NotNull Provider provider) { + return attachment.serializeNBT(); + } } } diff --git a/neoforge-main/src/main/java/dev/compactmods/crafting/events/WorldEventHandler.java b/neoforge-main/src/main/java/dev/compactmods/crafting/events/WorldEventHandler.java index f8e804b..f3373a9 100644 --- a/neoforge-main/src/main/java/dev/compactmods/crafting/events/WorldEventHandler.java +++ b/neoforge-main/src/main/java/dev/compactmods/crafting/events/WorldEventHandler.java @@ -3,6 +3,11 @@ import dev.compactmods.crafting.CompactCrafting; import dev.compactmods.crafting.data.CCAttachments; import dev.compactmods.crafting.field.ActiveWorldFields; +import dev.compactmods.crafting.field.MiniaturizationField; +import dev.compactmods.crafting.network.ClientFieldWatchPacket; +import dev.compactmods.crafting.network.ClientFieldUnwatchPacket; +import dev.compactmods.crafting.network.FieldActivatedPacket; +import dev.compactmods.crafting.network.NetworkHandler; import io.reactivex.rxjava3.subjects.PublishSubject; import io.reactivex.rxjava3.subjects.Subject; import net.minecraft.server.level.ServerLevel; @@ -10,10 +15,12 @@ import net.minecraft.world.level.ChunkPos; import net.neoforged.bus.api.SubscribeEvent; import net.neoforged.fml.common.EventBusSubscriber; +import net.neoforged.neoforge.event.entity.player.PlayerEvent; import net.neoforged.neoforge.event.level.ChunkEvent; import net.neoforged.neoforge.event.level.ChunkWatchEvent; import net.neoforged.neoforge.event.server.ServerStartedEvent; import net.neoforged.neoforge.event.tick.LevelTickEvent; +import net.neoforged.neoforge.network.PacketDistributor; @SuppressWarnings("unused") @EventBusSubscriber(modid = CompactCrafting.MOD_ID) @@ -28,18 +35,19 @@ public class WorldEventHandler { @SubscribeEvent public static void onServerStarted(final ServerStartedEvent evt) { CompactCrafting.LOGGER.trace("Server started; calling previously active fields to validate themselves."); -// for (ServerLevel level : evt.getServer().getAllLevels()) { -// // FIXME -//// level.getCapability(CCCapabilities.FIELDS) -//// .resolve() -//// .ifPresent(fields -> { -//// fields.setLevel(level); -//// fields.getFields().forEach(f -> { -//// f.setLevel(level); -//// f.checkLoaded(); -//// }); -//// }); -// } + for (ServerLevel level : evt.getServer().getAllLevels()) { + level.getExistingData(CCAttachments.ACTIVE_FIELDS).ifPresent(fields -> { + fields.getFields().forEach(f -> { + if (f instanceof MiniaturizationField mf) { + mf.checkLoaded(); + // Send field activation to all players tracking the chunk + ChunkPos chunkPos = new ChunkPos(mf.getCenter()); + FieldActivatedPacket packet = new FieldActivatedPacket(mf, mf.serverData()); + PacketDistributor.sendToPlayersTrackingChunk(level, chunkPos, packet); + } + }); + }); + } } @SubscribeEvent @@ -53,19 +61,12 @@ public static void onStartChunkTracking(final ChunkWatchEvent.Watch event) { final ChunkPos pos = event.getPos(); final ServerLevel level = event.getLevel(); - // FIXME -// level.getCapability(CCCapabilities.FIELDS) -// .map(f -> f.getFields(pos)) -// .ifPresent(activeFields -> { -// activeFields.forEach(field -> { -// ClientFieldWatchPacket pkt = new ClientFieldWatchPacket(field); -// -// NetworkHandler.MAIN_CHANNEL.send( -// PacketDistributor.PLAYER.with(() -> player), -// pkt -// ); -// }); -// }); + level.getExistingData(CCAttachments.ACTIVE_FIELDS).ifPresent(fields -> { + fields.getFields(pos).forEach(field -> { + ClientFieldWatchPacket pkt = new ClientFieldWatchPacket(field); + PacketDistributor.sendToPlayer(player, pkt); + }); + }); } @SubscribeEvent @@ -74,19 +75,12 @@ public static void onStopChunkTracking(final ChunkWatchEvent.UnWatch event) { final ChunkPos pos = event.getPos(); final ServerLevel level = event.getLevel(); - // FIXME -// level.getCapability(CCCapabilities.FIELDS) -// .map(f -> f.getFields(pos)) -// .ifPresent(activeFields -> { -// activeFields.forEach(field -> { -// ClientFieldUnwatchPacket pkt = new ClientFieldUnwatchPacket(field.getCenter()); -// -// NetworkHandler.MAIN_CHANNEL.send( -// PacketDistributor.PLAYER.with(() -> player), -// pkt -// ); -// }); -// }); + level.getExistingData(CCAttachments.ACTIVE_FIELDS).ifPresent(fields -> { + fields.getFields(pos).forEach(field -> { + ClientFieldUnwatchPacket pkt = new ClientFieldUnwatchPacket(field.getCenter()); + PacketDistributor.sendToPlayer(player, pkt); + }); + }); } @SubscribeEvent @@ -98,4 +92,24 @@ public static void chunkLoaded(final ChunkEvent.Load cEvent) { public static void chunkUnloaded(final ChunkEvent.Unload cEvent) { CHUNK_CHANGES.onNext(cEvent); } + + @SubscribeEvent + public static void onPlayerLogin(final PlayerEvent.PlayerLoggedInEvent event) { + if (event.getEntity() instanceof ServerPlayer player) { + ServerLevel level = player.serverLevel(); + // Send all active fields in the player's view distance + level.getExistingData(CCAttachments.ACTIVE_FIELDS).ifPresent(fields -> { + fields.getFields().forEach(field -> { + if (field instanceof MiniaturizationField mf) { + // Check if player can see this field's chunk + ChunkPos fieldChunk = new ChunkPos(mf.getCenter()); + if (player.getChunkTrackingView().contains(fieldChunk.x, fieldChunk.z)) { + FieldActivatedPacket packet = new FieldActivatedPacket(mf, mf.serverData()); + PacketDistributor.sendToPlayer(player, packet); + } + } + }); + }); + } + } } diff --git a/neoforge-main/src/main/java/dev/compactmods/crafting/field/ActiveWorldFields.java b/neoforge-main/src/main/java/dev/compactmods/crafting/field/ActiveWorldFields.java index b63e0a1..0285df7 100644 --- a/neoforge-main/src/main/java/dev/compactmods/crafting/field/ActiveWorldFields.java +++ b/neoforge-main/src/main/java/dev/compactmods/crafting/field/ActiveWorldFields.java @@ -3,10 +3,13 @@ import dev.compactmods.crafting.CompactCrafting; import dev.compactmods.crafting.api.field.IMiniaturizationField; import dev.compactmods.crafting.api.field.ITickingMiniaturizationField; +import dev.compactmods.crafting.data.NbtListCollector; import dev.compactmods.crafting.network.FieldDeactivatedPacket; import dev.compactmods.crafting.projector.ProjectorHelper; import dev.compactmods.crafting.recipes.MiniaturizationRecipe; import net.minecraft.core.BlockPos; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.ListTag; import net.minecraft.resources.ResourceKey; import net.minecraft.server.level.ServerLevel; import net.minecraft.world.level.ChunkPos; @@ -60,15 +63,6 @@ public void tickFields() { public void addFieldInstance(IMiniaturizationField field) { BlockPos center = field.getCenter(); fields.put(center, field); - - // TODO: Attachment for field invalidation -// LazyOptional lazy = LazyOptional.of(() -> field); -// laziness.put(center, lazy); -// field.setRef(lazy); -// -// lazy.addListener(lo -> { -// lo.ifPresent(this::unregisterField); -// }); } public IMiniaturizationField registerField(IMiniaturizationField field) { @@ -83,19 +77,8 @@ public IMiniaturizationField registerField(IMiniaturizati addFieldInstance(field); - // FIXME - Set projector back-references to field - // field.getProjectors().locations().forEach(pos -> { -// BlockState stateAt = level.getBlockState(pos); -// if (!(stateAt.getBlock() instanceof FieldProjectorBlock)) -// return; -// -// if (stateAt.hasBlockEntity()) { -// BlockEntity tileAt = level.getBlockEntity(pos); -// if (tileAt instanceof FieldProjectorEntity) { -// // ((FieldProjectorEntity) tileAt).setFieldRef(field.getRef()); -// } -// } -// }); + // Projectors can find their field through the ActiveWorldFields attachment + // using the field center position, so no need to store back-references return field; } @@ -138,22 +121,23 @@ public ResourceKey getLevel() { return level.dimension(); } + public ListTag serializeNBT() { + return getFields() + .map(field -> { + if (field instanceof MiniaturizationField mf) { + return mf.serverData(); + } + return new CompoundTag(); + }) + .collect(NbtListCollector.toNbtList()); + } - -// public ListTag serializeNBT() { -// return getFields() -// .map(IMiniaturizationField::serverData) -// .collect(NbtListCollector.toNbtList()); -// } -// - - -// public void deserializeNBT(ListTag nbt) { -// nbt.forEach(item -> { -// if (item instanceof CompoundTag ct) { -// MiniaturizationField field = new MiniaturizationField(ct); -// addFieldInstance(field); -// } -// }); -// } + public void deserializeNBT(ListTag nbt) { + nbt.forEach(item -> { + if (item instanceof CompoundTag ct) { + MiniaturizationField field = MiniaturizationField.fromNBT(level, ct); + addFieldInstance(field); + } + }); + } } diff --git a/neoforge-main/src/main/java/dev/compactmods/crafting/field/MiniaturizationField.java b/neoforge-main/src/main/java/dev/compactmods/crafting/field/MiniaturizationField.java index c83208e..f659623 100644 --- a/neoforge-main/src/main/java/dev/compactmods/crafting/field/MiniaturizationField.java +++ b/neoforge-main/src/main/java/dev/compactmods/crafting/field/MiniaturizationField.java @@ -10,6 +10,7 @@ import dev.compactmods.crafting.core.CCMiniaturizationRecipes; import dev.compactmods.crafting.crafting.CraftingHelper; import dev.compactmods.crafting.events.WorldEventHandler; +import dev.compactmods.crafting.network.FieldActivatedPacket; import dev.compactmods.crafting.network.FieldDeactivatedPacket; import dev.compactmods.crafting.network.FieldRecipeChangedPacket; import dev.compactmods.crafting.recipes.MiniaturizationRecipe; @@ -22,6 +23,10 @@ import net.minecraft.core.Direction; import net.minecraft.core.Vec3i; import net.minecraft.core.particles.DustParticleOptions; +import net.minecraft.core.registries.BuiltInRegistries; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.NbtUtils; +import net.minecraft.resources.ResourceLocation; import net.minecraft.core.particles.ParticleOptions; import net.minecraft.core.particles.ParticleTypes; import net.minecraft.server.level.ServerLevel; @@ -91,30 +96,43 @@ public MiniaturizationField(Level level, MiniaturizationFieldSize size, BlockPos setupChunkListener(); } -// public MiniaturizationField(CompoundTag nbt) { -// this.craftingState = EnumCraftingState.valueOf(nbt.getString("state")); -// -// this.center = NbtUtils.readBlockPos(nbt, "center").orElseThrow(); -// this.size = MiniaturizationFieldSize.valueOf(nbt.getString("size")); -// -// setupChunkListener(); -// -// // temp load recipe -// if (nbt.contains("recipe")) { -// this.recipeId = ResourceLocation.parse(nbt.getString("recipe")); -// this.craftingProgress = nbt.getInt("progress"); -// } -// -// if (nbt.contains("matchedBlocks")) { -// StructureTemplate t = new StructureTemplate(); -// t.load(BuiltInRegistries.BLOCK.asLookup(), nbt.getCompound("matchedBlocks")); -// this.matchedBlocks = t; -// } else { -// this.matchedBlocks = null; -// } -// -// this.disabled = nbt.contains("disabled") && nbt.getBoolean("disabled"); -// } + private MiniaturizationField(Level level, CompoundTag nbt) { + this.level = level; + this.craftingState = EnumCraftingState.valueOf(nbt.getString("state")); + + this.center = NbtUtils.readBlockPos(nbt, "center").orElseThrow(); + this.size = MiniaturizationFieldSize.valueOf(nbt.getString("size")); + this.projectors = new FieldProjectorSet(new WeakReference<>(level), this.size.getProjectorLocations(this.center).collect(Collectors.toSet()), this.size); + + setupChunkListener(); + + // temp load recipe + if (nbt.contains("recipe")) { + ResourceLocation recipeId = ResourceLocation.parse(nbt.getString("recipe")); + this.craftingProgress = nbt.getInt("progress"); + + // Load recipe from registry + level.getRecipeManager().byKey(recipeId).ifPresent(recipe -> { + if (recipe.value() instanceof MiniaturizationRecipe mr) { + this.currentRecipe = (RecipeHolder) recipe; + } + }); + } + + if (nbt.contains("matchedBlocks")) { + StructureTemplate t = new StructureTemplate(); + t.load(BuiltInRegistries.BLOCK.asLookup(), nbt.getCompound("matchedBlocks")); + this.matchedBlocks = t; + } else { + this.matchedBlocks = null; + } + + this.disabled = nbt.contains("disabled") && nbt.getBoolean("disabled"); + } + + public static MiniaturizationField fromNBT(Level level, CompoundTag nbt) { + return new MiniaturizationField(level, nbt); + } private void setupChunkListener() { // add projector and central chunks @@ -562,9 +580,8 @@ public void enable() { this.projectors.enableAll(); if (this.level instanceof ServerLevel sl) { - // FIXME - // FieldDeactivatedPacket update = new FieldActivatedPacket(this, this.clientData()); - // PacketDistributor.sendToPlayersTrackingChunk(sl, new ChunkPos(center), update); + FieldActivatedPacket update = new FieldActivatedPacket(this, this.serverData()); + PacketDistributor.sendToPlayersTrackingChunk(sl, new ChunkPos(center), update); } } @@ -594,7 +611,27 @@ public MiniaturizationRecipe currentRecipe() { return currentRecipe.value(); } - // FIXME + public CompoundTag serverData() { + CompoundTag nbt = new CompoundTag(); + nbt.putString("size", size.name()); + nbt.put("center", NbtUtils.writeBlockPos(center)); + + nbt.putString("state", craftingState.name()); + + if (currentRecipe != null) { + nbt.putString("recipe", currentRecipe.id().toString()); + nbt.putInt("progress", craftingProgress); + } + + if (matchedBlocks != null) { + nbt.put("matchedBlocks", matchedBlocks.save(new CompoundTag())); + } + + nbt.putBoolean("disabled", this.disabled); + + return nbt; + } + // @Override // public Tag serializeNBT() { // CompoundTag fieldInfo = new CompoundTag(); diff --git a/neoforge-main/src/main/java/dev/compactmods/crafting/network/ClientFieldUnwatchPacket.java b/neoforge-main/src/main/java/dev/compactmods/crafting/network/ClientFieldUnwatchPacket.java index 385a670..a31f031 100644 --- a/neoforge-main/src/main/java/dev/compactmods/crafting/network/ClientFieldUnwatchPacket.java +++ b/neoforge-main/src/main/java/dev/compactmods/crafting/network/ClientFieldUnwatchPacket.java @@ -1,28 +1,33 @@ -//package dev.compactmods.crafting.network; -// -//import dev.compactmods.crafting.client.ClientPacketHandler; -//import net.minecraft.core.BlockPos; -//import net.minecraft.network.FriendlyByteBuf; -//import net.neoforged.neoforge.network.NetworkEvent; -// -//public class ClientFieldUnwatchPacket { -// -// private final BlockPos center; -// -// public ClientFieldUnwatchPacket(BlockPos center) { -// this.center = center; -// } -// -// public ClientFieldUnwatchPacket(FriendlyByteBuf buf) { -// this.center = buf.readBlockPos(); -// } -// -// public static void encode(ClientFieldUnwatchPacket pkt, FriendlyByteBuf buf) { -// buf.writeBlockPos(pkt.center); -// } -// -// public static boolean handle(ClientFieldUnwatchPacket pkt, NetworkEvent.Context context) { -// ClientPacketHandler.removeField(pkt.center); -// return true; -// } -//} +package dev.compactmods.crafting.network; + +import dev.compactmods.crafting.CompactCrafting; +import dev.compactmods.crafting.client.ClientPacketHandler; +import net.minecraft.core.BlockPos; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.network.codec.StreamCodec; +import net.minecraft.network.protocol.common.custom.CustomPacketPayload; +import net.neoforged.fml.loading.FMLEnvironment; +import net.neoforged.neoforge.network.handling.IPayloadHandler; + +public record ClientFieldUnwatchPacket(BlockPos center) implements CustomPacketPayload { + + public static final Type TYPE = new Type<>(CompactCrafting.modRL("field_unwatch")); + + public static final StreamCodec STREAM_CODEC = StreamCodec.composite( + BlockPos.STREAM_CODEC, ClientFieldUnwatchPacket::center, + ClientFieldUnwatchPacket::new + ); + + public static final IPayloadHandler HANDLER = (pkt, ctx) -> { + ctx.enqueueWork(() -> { + if (FMLEnvironment.dist.isClient()) { + ClientPacketHandler.removeField(pkt.center); + } + }); + }; + + @Override + public Type type() { + return TYPE; + } +} diff --git a/neoforge-main/src/main/java/dev/compactmods/crafting/network/ClientFieldWatchPacket.java b/neoforge-main/src/main/java/dev/compactmods/crafting/network/ClientFieldWatchPacket.java index 12f994c..7f5a625 100644 --- a/neoforge-main/src/main/java/dev/compactmods/crafting/network/ClientFieldWatchPacket.java +++ b/neoforge-main/src/main/java/dev/compactmods/crafting/network/ClientFieldWatchPacket.java @@ -1,31 +1,52 @@ -//package dev.compactmods.crafting.network; -// -//import dev.compactmods.crafting.api.field.IMiniaturizationField; -//import dev.compactmods.crafting.client.ClientPacketHandler; -//import dev.compactmods.crafting.field.MiniaturizationField; -//import net.minecraft.nbt.CompoundTag; -//import net.minecraft.network.FriendlyByteBuf; -// -//public class ClientFieldWatchPacket { -// -// private final IMiniaturizationField field; -// private final CompoundTag clientData; -// -// public ClientFieldWatchPacket(IMiniaturizationField field) { -// this.field = field; -// this.clientData = field.clientData(); -// } -// -// public ClientFieldWatchPacket(FriendlyByteBuf buf) { -// this.field = new MiniaturizationField(); -// this.clientData = buf.readNbt(); -// } -// -// public static void encode(ClientFieldWatchPacket pkt, FriendlyByteBuf buf) { -// buf.writeNbt(pkt.field.clientData()); -// } -// -// public static void handle(ClientFieldWatchPacket pkt) { -// ClientPacketHandler.handleFieldData(pkt.clientData); -// } -//} +package dev.compactmods.crafting.network; + +import dev.compactmods.crafting.CompactCrafting; +import dev.compactmods.crafting.api.field.IMiniaturizationField; +import dev.compactmods.crafting.api.field.MiniaturizationFieldSize; +import dev.compactmods.crafting.client.ClientPacketHandler; +import dev.compactmods.crafting.field.MiniaturizationField; +import dev.compactmods.crafting.recipes.MiniaturizationRecipe; +import net.minecraft.core.BlockPos; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.network.codec.ByteBufCodecs; +import net.minecraft.network.codec.StreamCodec; +import net.minecraft.network.protocol.common.custom.CustomPacketPayload; +import net.neoforged.fml.loading.FMLEnvironment; +import net.neoforged.neoforge.network.handling.IPayloadHandler; + +public record ClientFieldWatchPacket(MiniaturizationFieldSize fieldSize, BlockPos center, CompoundTag clientData) implements CustomPacketPayload { + + public static final Type TYPE = new Type<>(CompactCrafting.modRL("field_watch")); + + public ClientFieldWatchPacket(IMiniaturizationField field) { + this(field.getFieldSize(), field.getCenter(), getClientData(field)); + } + + private static CompoundTag getClientData(IMiniaturizationField field) { + if (field instanceof MiniaturizationField mf) { + return mf.serverData(); + } + return new CompoundTag(); + } + + public static final StreamCodec STREAM_CODEC = StreamCodec.composite( + MiniaturizationFieldSize.STREAM_CODEC, ClientFieldWatchPacket::fieldSize, + BlockPos.STREAM_CODEC, ClientFieldWatchPacket::center, + ByteBufCodecs.COMPOUND_TAG, ClientFieldWatchPacket::clientData, + ClientFieldWatchPacket::new + ); + + public static final IPayloadHandler HANDLER = (pkt, ctx) -> { + ctx.enqueueWork(() -> { + if (FMLEnvironment.dist.isClient()) { + ClientPacketHandler.handleFieldData(pkt.clientData); + } + }); + }; + + @Override + public Type type() { + return TYPE; + } +} diff --git a/neoforge-main/src/main/java/dev/compactmods/crafting/network/NetworkHandler.java b/neoforge-main/src/main/java/dev/compactmods/crafting/network/NetworkHandler.java index 8579d60..ec36c67 100644 --- a/neoforge-main/src/main/java/dev/compactmods/crafting/network/NetworkHandler.java +++ b/neoforge-main/src/main/java/dev/compactmods/crafting/network/NetworkHandler.java @@ -11,8 +11,8 @@ public static void onPacketRegistration(final RegisterPayloadHandlersEvent paylo main.playToClient(FieldDeactivatedPacket.TYPE, FieldDeactivatedPacket.STREAM_CODEC, FieldDeactivatedPacket.HANDLER); main.playToClient(FieldActivatedPacket.TYPE, FieldActivatedPacket.STREAM_CODEC, FieldActivatedPacket.HANDLER); -// main.playToClient(ClientFieldWatchPacket.TYPE, ClientFieldWatchPacket.CODEC, ClientFieldWatchPacket.HANDLER); -// main.playToClient(ClientFieldUnwatchPacket.TYPE, ClientFieldUnwatchPacket.CODEC, ClientFieldUnwatchPacket.HANDLER); + main.playToClient(ClientFieldWatchPacket.TYPE, ClientFieldWatchPacket.STREAM_CODEC, ClientFieldWatchPacket.HANDLER); + main.playToClient(ClientFieldUnwatchPacket.TYPE, ClientFieldUnwatchPacket.STREAM_CODEC, ClientFieldUnwatchPacket.HANDLER); main.playToClient(FieldRecipeChangedPacket.TYPE, FieldRecipeChangedPacket.STREAM_CODEC, FieldRecipeChangedPacket.HANDLER); } diff --git a/neoforge-main/src/main/java/dev/compactmods/crafting/projector/FieldProjectorBlock.java b/neoforge-main/src/main/java/dev/compactmods/crafting/projector/FieldProjectorBlock.java index d32191c..758f6ea 100644 --- a/neoforge-main/src/main/java/dev/compactmods/crafting/projector/FieldProjectorBlock.java +++ b/neoforge-main/src/main/java/dev/compactmods/crafting/projector/FieldProjectorBlock.java @@ -6,6 +6,7 @@ import dev.compactmods.crafting.api.projector.FieldProjectorProperties; import dev.compactmods.crafting.client.render.GhostProjectorPlacementRenderer; import dev.compactmods.crafting.data.CCAttachments; +import dev.compactmods.crafting.field.IMutableMiniaturizationField; import dev.compactmods.crafting.field.MiniaturizationField; import dev.compactmods.crafting.network.FieldActivatedPacket; import dev.compactmods.crafting.recipes.MiniaturizationRecipe; @@ -259,28 +260,34 @@ public void neighborChanged(BlockState state, Level level, BlockPos pos, Block c if (level.isClientSide) return; - // FIXME REDSTONE HANDLING + // Redstone handling if (isActive(state)) { CompactCrafting.LOGGER.debug("redstone check!"); -// BlockEntity tile = level.getBlockEntity(pos); -// if (tile instanceof FieldProjectorEntity) { -// FieldProjectorEntity fpt = (FieldProjectorEntity) tile; -// if (level.getBestNeighborSignal(pos) > 0) { -// // receiving power from some side, turn off rendering -// fpt.getField().ifPresent(IMiniaturizationField::disable); -// } else { -// // check other projectors, if there's a redstone signal anywhere, we disable the field -// fpt.getField().ifPresent(IMiniaturizationField::checkRedstone); -// } -// } -// } else { -// // not active, but we may be re-enabling a disabled field -// ProjectorHelper.getClosestOppositeSize(level, pos).ifPresent(size -> { -// final BlockPos center = size.getCenterFromProjector(pos, state.getValue(FACING)); -// level.getCapability(CCCapabilities.FIELDS).ifPresent(fields -> { -// fields.get(center).ifPresent(IMiniaturizationField::checkRedstone); -// }); -// }); + BlockEntity tile = level.getBlockEntity(pos); + if (tile instanceof FieldProjectorEntity fpt) { + // Find the field this projector belongs to + ProjectorHelper.getClosestOppositeSize(level, pos).ifPresent(size -> { + final BlockPos center = size.getCenterFromProjector(pos, state.getValue(FACING)); + level.getData(CCAttachments.ACTIVE_FIELDS).get(center).ifPresent(field -> { + if (level.getBestNeighborSignal(pos) > 0) { + // receiving power from some side, turn off rendering + if (field instanceof IMutableMiniaturizationField mutable) { + mutable.disable(); + } + } else { + // check other projectors, if there's a redstone signal anywhere, we disable the field + field.checkRedstone(); + } + }); + }); + } + } else { + // not active, but we may be re-enabling a disabled field + ProjectorHelper.getClosestOppositeSize(level, pos).ifPresent(size -> { + final BlockPos center = size.getCenterFromProjector(pos, state.getValue(FACING)); + level.getData(CCAttachments.ACTIVE_FIELDS).get(center) + .ifPresent(IMiniaturizationField::checkRedstone); + }); } } From 9faf200d226ced6d2204c69ab4f9129c58c36275 Mon Sep 17 00:00:00 2001 From: Leclowndu93150 Date: Tue, 23 Sep 2025 23:39:29 +0200 Subject: [PATCH 02/20] progress 2 --- neoforge-main/build.gradle.kts | 1 + .../JeiMiniaturizationCraftingCategory.java | 519 ------------------ .../compat/jei/JeiMiniaturizationPlugin.java | 51 -- .../providers/FieldProjectorProvider.java | 100 ---- .../providers/FieldProxyProvider.java | 42 -- .../crafting/client/ui/ScreenArea.java | 27 + .../crafting}/compat/ModBusEvents.java | 12 +- .../JeiMiniaturizationCraftingCategory.java | 514 +++++++++++++++++ .../compat/jei/JeiMiniaturizationPlugin.java | 51 ++ .../crafting}/compat/theoneprobe/TOPMain.java | 2 - .../compat/theoneprobe/TheOneProbeCompat.java | 4 +- .../providers/FieldProjectorProvider.java | 108 ++++ .../crafting}/fakeworld/RecipeChunk.java | 0 .../fakeworld/RenderingChunkProvider.java | 0 .../fakeworld/RenderingSpawnInfo.java | 0 .../crafting}/fakeworld/RenderingWorld.java | 2 +- .../data/compactcrafting/recipe/oak_door.json | 30 + 17 files changed, 740 insertions(+), 723 deletions(-) delete mode 100644 neoforge-main/gtfo/compat/jei/JeiMiniaturizationCraftingCategory.java delete mode 100644 neoforge-main/gtfo/compat/jei/JeiMiniaturizationPlugin.java delete mode 100644 neoforge-main/gtfo/compat/theoneprobe/providers/FieldProjectorProvider.java delete mode 100644 neoforge-main/gtfo/compat/theoneprobe/providers/FieldProxyProvider.java create mode 100644 neoforge-main/src/main/java/dev/compactmods/crafting/client/ui/ScreenArea.java rename neoforge-main/{gtfo => src/main/java/dev/compactmods/crafting}/compat/ModBusEvents.java (55%) create mode 100644 neoforge-main/src/main/java/dev/compactmods/crafting/compat/jei/JeiMiniaturizationCraftingCategory.java create mode 100644 neoforge-main/src/main/java/dev/compactmods/crafting/compat/jei/JeiMiniaturizationPlugin.java rename neoforge-main/{gtfo => src/main/java/dev/compactmods/crafting}/compat/theoneprobe/TOPMain.java (77%) rename neoforge-main/{gtfo => src/main/java/dev/compactmods/crafting}/compat/theoneprobe/TheOneProbeCompat.java (82%) create mode 100644 neoforge-main/src/main/java/dev/compactmods/crafting/compat/theoneprobe/providers/FieldProjectorProvider.java rename neoforge-main/{gtfo => src/main/java/dev/compactmods/crafting}/fakeworld/RecipeChunk.java (100%) rename neoforge-main/{gtfo => src/main/java/dev/compactmods/crafting}/fakeworld/RenderingChunkProvider.java (100%) rename neoforge-main/{gtfo => src/main/java/dev/compactmods/crafting}/fakeworld/RenderingSpawnInfo.java (100%) rename neoforge-main/{gtfo => src/main/java/dev/compactmods/crafting}/fakeworld/RenderingWorld.java (99%) create mode 100644 neoforge-main/src/main/resources/data/compactcrafting/recipe/oak_door.json diff --git a/neoforge-main/build.gradle.kts b/neoforge-main/build.gradle.kts index 05f0f29..bfbf2f3 100644 --- a/neoforge-main/build.gradle.kts +++ b/neoforge-main/build.gradle.kts @@ -139,6 +139,7 @@ dependencies { testRuntimeOnly("org.junit.platform:junit-platform-launcher") implementation("curse.maven:jei-238222:7024953") + implementation("curse.maven:the-one-probe-245211:5836106") jarJar(libs.rxjava) jarJar(libs.reactivestreams) diff --git a/neoforge-main/gtfo/compat/jei/JeiMiniaturizationCraftingCategory.java b/neoforge-main/gtfo/compat/jei/JeiMiniaturizationCraftingCategory.java deleted file mode 100644 index 248a417..0000000 --- a/neoforge-main/gtfo/compat/jei/JeiMiniaturizationCraftingCategory.java +++ /dev/null @@ -1,519 +0,0 @@ -package dev.compactmods.crafting.compat.jei; - -import java.nio.FloatBuffer; -import java.util.*; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.stream.IntStream; - -import com.mojang.blaze3d.platform.InputConstants; -import com.mojang.blaze3d.platform.Window; -import com.mojang.blaze3d.systems.RenderSystem; -import com.mojang.blaze3d.vertex.PoseStack; -import com.mojang.math.Matrix4f; -import com.mojang.math.Quaternion; -import dev.compactmods.crafting.CompactCrafting; -import dev.compactmods.crafting.api.components.IRecipeBlockComponent; -import dev.compactmods.crafting.api.recipe.layers.IRecipeLayer; -import dev.compactmods.crafting.client.fakeworld.RenderingWorld; -import dev.compactmods.crafting.client.ui.ScreenArea; -import dev.compactmods.crafting.core.CCBlocks; -import dev.compactmods.crafting.recipes.MiniaturizationRecipe; -import dev.compactmods.crafting.recipes.components.BlockComponent; -import dev.compactmods.crafting.util.BlockSpaceUtil; -import mezz.jei.api.constants.VanillaTypes; -import mezz.jei.api.gui.builder.IRecipeLayoutBuilder; -import mezz.jei.api.gui.builder.IRecipeSlotBuilder; -import mezz.jei.api.gui.drawable.IDrawable; -import mezz.jei.api.gui.drawable.IDrawableStatic; -import mezz.jei.api.gui.ingredient.IRecipeSlotsView; -import mezz.jei.api.helpers.IGuiHelper; -import mezz.jei.api.recipe.IFocusGroup; -import mezz.jei.api.recipe.RecipeIngredientRole; -import mezz.jei.api.recipe.RecipeType; -import mezz.jei.api.recipe.category.IRecipeCategory; -import net.minecraft.ChatFormatting; -import net.minecraft.client.Minecraft; -import net.minecraft.client.gui.GuiComponent; -import net.minecraft.client.renderer.GameRenderer; -import net.minecraft.client.renderer.LightTexture; -import net.minecraft.client.renderer.MultiBufferSource; -import net.minecraft.client.renderer.block.BlockRenderDispatcher; -import net.minecraft.client.renderer.texture.OverlayTexture; -import net.minecraft.client.resources.sounds.SimpleSoundInstance; -import net.minecraft.client.sounds.SoundManager; -import net.minecraft.core.BlockPos; -import net.minecraft.network.chat.Component; -import net.minecraft.network.chat.MutableComponent; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.sounds.SoundEvents; -import net.minecraft.world.item.Item; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.Items; -import net.minecraft.world.level.block.entity.BlockEntity; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.phys.AABB; -import net.minecraft.world.phys.Vec3; -import net.minecraftforge.client.model.data.ModelData; -import org.lwjgl.BufferUtils; - -public class JeiMiniaturizationCraftingCategory implements IRecipeCategory { - - public static final ResourceLocation UID = new ResourceLocation(CompactCrafting.MOD_ID, "miniaturization"); - public static final RecipeType RECIPE_TYPE = new RecipeType<>(UID, MiniaturizationRecipe.class); - - private final IDrawable icon; - private final BlockRenderDispatcher blocks; - private RenderingWorld previewLevel; - - private IGuiHelper guiHelper; - private final IDrawableStatic background; - private final IDrawableStatic slotDrawable; - private final IDrawableStatic arrowOutputs; - - private boolean singleLayer = false; - private int singleLayerOffset = 0; - private boolean debugMode = false; - - private ScreenArea explodeToggle = new ScreenArea(30, 75, 10, 10); - private ScreenArea layerUp = new ScreenArea(55, 75, 10, 10); - private ScreenArea layerSwap = new ScreenArea(70, 75, 10, 10); - private ScreenArea layerDown = new ScreenArea(85, 75, 10, 10); - - /** - * Whether the preview is exploded (expanded) or not. - */ - private boolean exploded = false; - - /** - * Explode multiplier; specifies how far apart blocks are rendered. - */ - private double explodeMulti = 1.0d; - - private final MutableComponent MATERIAL_COMPONENT = Component.translatable(CompactCrafting.MOD_ID + ".jei.miniaturization.component") - .withStyle(ChatFormatting.GRAY) - .withStyle(ChatFormatting.ITALIC); - - private final MutableComponent CATALYST = Component.translatable(CompactCrafting.MOD_ID + ".jei.miniaturization.catalyst") - .withStyle(ChatFormatting.YELLOW) - .withStyle(ChatFormatting.ITALIC); - - public JeiMiniaturizationCraftingCategory(IGuiHelper guiHelper) { - int width = (9 * 18) + 10; - int height = 60 + (10 + (18 * 3) + 5); - - this.guiHelper = guiHelper; - this.background = guiHelper.createBlankDrawable(width, height); - this.slotDrawable = guiHelper.getSlotDrawable(); - this.icon = guiHelper.createDrawableIngredient(VanillaTypes.ITEM_STACK, new ItemStack(CCBlocks.FIELD_PROJECTOR_BLOCK.get())); - this.arrowOutputs = guiHelper.createDrawable(new ResourceLocation(CompactCrafting.MOD_ID, "textures/gui/jei-arrow-outputs.png"), 0, 0, 24, 19); - - this.blocks = Minecraft.getInstance().getBlockRenderer(); - this.previewLevel = null; - } - - @Override - public RecipeType getRecipeType() { - return RECIPE_TYPE; - } - - //region JEI implementation requirements - @Override - public Component getTitle() { - return Component.translatable(CompactCrafting.MOD_ID + ".jei.miniaturization.title"); - } - - @Override - public IDrawable getBackground() { - return background; - } - - @Override - public IDrawable getIcon() { - return this.icon; - } - //endregion - - - @Override - public void setRecipe(IRecipeLayoutBuilder layout, MiniaturizationRecipe recipe, IFocusGroup focuses) { - previewLevel = new RenderingWorld(recipe); - - singleLayer = false; - singleLayerOffset = 0; - - try { - addMaterialSlots(recipe, layout); - addCatalystSlots(recipe, layout); - - int fromRightEdge = this.background.getWidth() - (18 * 2) - 5; - addOutputSlots(recipe, layout, fromRightEdge); - } catch (Exception ex) { - CompactCrafting.LOGGER.error(recipe.getRecipeIdentifier()); - CompactCrafting.LOGGER.error("Error displaying recipe", ex); - } - } - - private IRecipeSlotBuilder addCatalystSlots(MiniaturizationRecipe recipe, IRecipeLayoutBuilder layout) { - final var catalystSlot = layout.addSlot(RecipeIngredientRole.CATALYST, 1, 1) - .setBackground(slotDrawable, -1, -1); - - if (!recipe.getCatalyst().matches(ItemStack.EMPTY)) { - catalystSlot.addItemStacks(new ArrayList<>(recipe.getCatalyst().getPossible())) - .addTooltipCallback((slots, c) -> c.add(CATALYST)); - } - - return catalystSlot; - } - - private void addMaterialSlots(MiniaturizationRecipe recipe, IRecipeLayoutBuilder layout) { - AtomicInteger inputOffset = new AtomicInteger(); - - final int GUTTER_X = 5; - final int OFFSET_Y = 64; - - recipe.getComponentTotals() - .entrySet() - .stream() - .filter(comp -> comp.getValue() > 0) - .sorted(Map.Entry.comparingByValue(Comparator.reverseOrder())) - .forEach((comp) -> { - String component = comp.getKey(); - int required = comp.getValue(); - int finalInputOffset = inputOffset.get(); - - IRecipeBlockComponent bs = recipe.getComponents().getBlock(component).get(); - if (bs instanceof BlockComponent bsc) { - Item bi = bsc.getBlock().asItem(); - - int slotX = GUTTER_X + (finalInputOffset % 9) * 18; - int slotY = (OFFSET_Y + 24) + ((finalInputOffset / 9) * 18); - - final var slot = layout.addSlot(RecipeIngredientRole.INPUT, slotX, slotY) - .setBackground(slotDrawable, -1, -1); - - if (bi != Items.AIR) { - slot.addItemStack(new ItemStack(bi, required)); - slot.addTooltipCallback((slots, c) -> c.add(MATERIAL_COMPONENT)); - inputOffset.getAndIncrement(); - } - } - }); - - for (int i = inputOffset.get(); i < 18; i++) { - int slotX = GUTTER_X + (i % 9) * 18; - int slotY = (OFFSET_Y + 24) + ((i / 9) * 18); - - layout.addSlot(RecipeIngredientRole.INPUT, slotX, slotY).setBackground(slotDrawable, -1, -1); - } - } - - private void addOutputSlots(MiniaturizationRecipe recipe, IRecipeLayoutBuilder layout, int GUTTER_X) { - final var out = recipe.getOutputs(); - for (int outputNum = 0; outputNum < 6; outputNum++) { - int x = (18 * (outputNum % 2)) + GUTTER_X + 1; - int y = (18 * (outputNum / 2)) + 8 + 1; - - final var slot = layout.addSlot(RecipeIngredientRole.OUTPUT, x, y) - .setBackground(slotDrawable, -1, -1); - - if (outputNum < out.length) - slot.addItemStack(out[outputNum]); - } - } - //endregion - - - @Override - public List getTooltipStrings(MiniaturizationRecipe recipe, IRecipeSlotsView slots, double mouseX, double mouseY) { - if (explodeToggle.contains(mouseX, mouseY)) { - if (!exploded) return List.of(Component.translatable("compactcrafting.jei.toggle_exploded_view")); - else return List.of(Component.translatable("compactcrafting.jei.toggle_condensed_view")); - } - - if (layerSwap.contains(mouseX, mouseY)) { - if (singleLayer) return List.of(Component.translatable("compactcrafting.jei.all_layers_mode")); - else return List.of(Component.translatable("compactcrafting.jei.single_layer_mode")); - } - - if (layerUp.contains(mouseX, mouseY) && singleLayer) { - if (singleLayerOffset < recipe.getDimensions().getYsize() - 1) - return List.of(Component.translatable("compactcrafting.jei.layer_up")); - } - - if (layerDown.contains(mouseX, mouseY) && singleLayer) { - if (singleLayerOffset > 0) - return List.of(Component.translatable("compactcrafting.jei.layer_down")); - } - - return Collections.emptyList(); - } - - @Override - public boolean handleInput(MiniaturizationRecipe recipe, double mouseX, double mouseY, InputConstants.Key input) { - if (input.getType() == InputConstants.Type.MOUSE && input.getValue() == 0) { - SoundManager handler = Minecraft.getInstance().getSoundManager(); - - if (explodeToggle.contains(mouseX, mouseY)) { - explodeMulti = exploded ? 1.0d : 1.6d; - exploded = !exploded; - handler.play(SimpleSoundInstance.forUI(SoundEvents.UI_BUTTON_CLICK, 1.0F)); - return true; - } - - if (layerSwap.contains(mouseX, mouseY)) { - singleLayer = !singleLayer; - handler.play(SimpleSoundInstance.forUI(SoundEvents.UI_BUTTON_CLICK, 1.0F)); - return true; - } - - if (layerUp.contains(mouseX, mouseY) && singleLayer) { - if (singleLayerOffset < recipe.getDimensions().getYsize() - 1) { - handler.play(SimpleSoundInstance.forUI(SoundEvents.UI_BUTTON_CLICK, 1.0F)); - singleLayerOffset++; - } - return true; - } - - if (layerDown.contains(mouseX, mouseY) && singleLayer) { - if (singleLayerOffset > 0) { - handler.play(SimpleSoundInstance.forUI(SoundEvents.UI_BUTTON_CLICK, 1.0F)); - singleLayerOffset--; - } - - return true; - } - } - - return false; - } - - //region Rendering help - private void drawScaledTexture( - PoseStack matrixStack, - ResourceLocation texture, - ScreenArea area, - float u, float v, - int uWidth, int vHeight, - int textureWidth, int textureHeight) { - - RenderSystem.setShader(GameRenderer::getPositionTexShader); - RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); - RenderSystem.setShaderTexture(0, texture); - - RenderSystem.enableDepthTest(); - GuiComponent.blit(matrixStack, area.x, area.y, area.width, area.height, u, v, uWidth, vHeight, textureWidth, textureHeight); - } - - //endregion - - @Override - public void draw(MiniaturizationRecipe recipe, IRecipeSlotsView slots, PoseStack pose, double mouseX, double mouseY) { - AABB dims = recipe.getDimensions(); - - Window mainWindow = Minecraft.getInstance().getWindow(); - - drawScaledTexture(pose, - new ResourceLocation(CompactCrafting.MOD_ID, "textures/gui/jei-arrow-field.png"), - new ScreenArea(7, 20, 17, 22), - 0, 0, 17, 22, 17, 22); - - drawScaledTexture(pose, - new ResourceLocation(CompactCrafting.MOD_ID, "textures/gui/jei-arrow-outputs.png"), - new ScreenArea(100, 25, 24, 19), - 0, 0, 24, 19, 24, 19); - - int scissorX = 27; - int scissorY = 0; - - double guiScaleFactor = mainWindow.getGuiScale(); - ScreenArea scissorBounds = new ScreenArea( - scissorX, scissorY, - 70, - 70 - ); - - renderPreviewControls(pose, dims); - - if (previewLevel != null) renderRecipe(recipe, pose, dims, guiScaleFactor, scissorBounds); - } - - private void renderRecipe(MiniaturizationRecipe recipe, PoseStack mx, AABB dims, double guiScaleFactor, ScreenArea scissorBounds) { - try { - GuiComponent.fill( - mx, - scissorBounds.x, scissorBounds.y, - scissorBounds.x + scissorBounds.width, - scissorBounds.height, - 0xFF404040 - ); - - MultiBufferSource.BufferSource buffers = Minecraft.getInstance().renderBuffers().bufferSource(); - - final double scale = Minecraft.getInstance().getWindow().getGuiScale(); - final Matrix4f matrix = mx.last().pose(); - final FloatBuffer buf = BufferUtils.createFloatBuffer(16); - matrix.store(buf); - - // { x, y, z } - Vec3 translation = new Vec3( - buf.get(12) * scale, - buf.get(13) * scale, - buf.get(14) * scale); - - scissorBounds.x *= scale; - scissorBounds.y *= scale; - scissorBounds.width *= scale; - scissorBounds.height *= scale; - final int scissorX = Math.round(Math.round(translation.x + scissorBounds.x)); - final int scissorY = Math.round(Math.round(Minecraft.getInstance().getWindow().getHeight() - scissorBounds.y - scissorBounds.height - translation.y)); - final int scissorW = Math.round(scissorBounds.width); - final int scissorH = Math.round(scissorBounds.height); - RenderSystem.enableScissor(scissorX, scissorY, scissorW, scissorH); - - mx.pushPose(); - - mx.translate( - 27 + (35), - scissorBounds.y + (35), - 100); - - Vec3 dimsVec = new Vec3(dims.getXsize(), dims.getYsize(), dims.getZsize()); - float recipeAvgDim = (float) dimsVec.length(); - float previewScale = (float) ((3 + Math.exp(3 - (recipeAvgDim / 5))) / explodeMulti); - mx.scale(previewScale, -previewScale, previewScale); - - drawActualRecipe(recipe, mx, dims, buffers); - - mx.popPose(); - - buffers.endBatch(); - - RenderSystem.disableScissor(); - } catch (Exception ex) { - CompactCrafting.LOGGER.warn(ex); - } - } - - private void drawActualRecipe(MiniaturizationRecipe recipe, PoseStack mx, AABB dims, MultiBufferSource.BufferSource buffers) { - double gameTime = Minecraft.getInstance().level.getGameTime(); - double test = Math.toDegrees(gameTime) / 15; - mx.mulPose(new Quaternion(35f, - (float) -test, - 0, - true)); - - double ySize = recipe.getDimensions().getYsize(); - - // Variable explode based on mouse position (clamped) - // double explodeMulti = MathHelper.clamp(mouseX, 0, this.background.getWidth())/this.background.getWidth()*2+1; - - int[] renderLayers; - if (!singleLayer) { - renderLayers = IntStream.range(0, (int) ySize).toArray(); - } else { - renderLayers = new int[]{singleLayerOffset}; - } - - mx.translate( - -(dims.getXsize() / 2) * explodeMulti - 0.5, - -(dims.getYsize() / 2) * explodeMulti - 0.5, - -(dims.getZsize() / 2) * explodeMulti - 0.5 - ); - - for (int y : renderLayers) { - recipe.getLayer(y).ifPresent(l -> renderRecipeLayer(recipe, mx, buffers, l, y)); - } - } - - private void renderPreviewControls(PoseStack mx, AABB dims) { - mx.pushPose(); - mx.translate(0, 0, 10); - - ResourceLocation sprites = new ResourceLocation(CompactCrafting.MOD_ID, "textures/gui/jei-sprites.png"); - - if (exploded) { - drawScaledTexture(mx, sprites, explodeToggle, 20, 0, 20, 20, 120, 20); - } else { - drawScaledTexture(mx, sprites, explodeToggle, 0, 0, 20, 20, 120, 20); - } - - // Layer change buttons - if (singleLayer) { - drawScaledTexture(mx, sprites, layerSwap, 60, 0, 20, 20, 120, 20); - } else { - drawScaledTexture(mx, sprites, layerSwap, 40, 0, 20, 20, 120, 20); - } - - if (singleLayer) { - if (singleLayerOffset < dims.getYsize() - 1) - drawScaledTexture(mx, sprites, layerUp, 80, 0, 20, 20, 120, 20); - - if (singleLayerOffset > 0) { - drawScaledTexture(mx, sprites, layerDown, 100, 0, 20, 20, 120, 20); - } - } - - // drawScaledTexture(mx, sprites, bindPlate, 120, 0, 20, 20, 140, 20); - - mx.popPose(); - } - - private void renderRecipeLayer(MiniaturizationRecipe recipe, PoseStack mx, MultiBufferSource.BufferSource buffers, IRecipeLayer l, int layerY) { - // Begin layer - mx.pushPose(); - - AABB layerBounds = BlockSpaceUtil.getLayerBounds(recipe.getDimensions(), layerY); - BlockPos.betweenClosedStream(layerBounds).forEach(filledPos -> { - mx.pushPose(); - - mx.translate( - ((filledPos.getX() + 0.5) * explodeMulti), - ((layerY + 0.5) * explodeMulti), - ((filledPos.getZ() + 0.5) * explodeMulti) - ); - - BlockPos zeroedPos = filledPos.below(layerY); - Optional componentForPosition = l.getComponentForPosition(zeroedPos); - componentForPosition - .flatMap(recipe.getComponents()::getBlock) - .ifPresent(comp -> renderComponent(mx, buffers, comp, filledPos)); - - mx.popPose(); - }); - - // Done with layer - mx.popPose(); - } - - private void renderComponent(PoseStack mx, MultiBufferSource.BufferSource buffers, IRecipeBlockComponent state, BlockPos filledPos) { - // TODO - Render switching at fixed interval - if (state.didErrorRendering()) - return; - - BlockState state1 = state.getRenderState(); - - ModelData data = ModelData.EMPTY; - if (previewLevel != null && state1.hasBlockEntity()) { - // create fake world instance - // get tile entity - extend EmptyBlockReader with impl - BlockEntity be = previewLevel.getBlockEntity(filledPos); - if (be != null) - data = be.getModelData(); - } - - try { - // TODO: Revisit render types - blocks.renderSingleBlock(state1, - mx, - buffers, - LightTexture.FULL_SKY, - OverlayTexture.NO_OVERLAY, - data, null); - } catch (Exception e) { - state.markRenderingErrored(); - - CompactCrafting.LOGGER.warn("Error rendering block in preview: {}", state1); - CompactCrafting.LOGGER.error("Stack Trace", e); - } - } -} \ No newline at end of file diff --git a/neoforge-main/gtfo/compat/jei/JeiMiniaturizationPlugin.java b/neoforge-main/gtfo/compat/jei/JeiMiniaturizationPlugin.java deleted file mode 100644 index 7995557..0000000 --- a/neoforge-main/gtfo/compat/jei/JeiMiniaturizationPlugin.java +++ /dev/null @@ -1,51 +0,0 @@ -package dev.compactmods.crafting.compat.jei; - -import dev.compactmods.crafting.CompactCrafting; -import dev.compactmods.crafting.core.CCItems; -import dev.compactmods.crafting.core.CCMiniaturizationRecipes; -import mezz.jei.api.IModPlugin; -import mezz.jei.api.JeiPlugin; -import mezz.jei.api.registration.IGuiHandlerRegistration; -import mezz.jei.api.registration.IRecipeCatalystRegistration; -import mezz.jei.api.registration.IRecipeCategoryRegistration; -import mezz.jei.api.registration.IRecipeRegistration; -import net.minecraft.client.Minecraft; -import net.minecraft.client.multiplayer.ClientLevel; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.crafting.RecipeManager; - -@JeiPlugin -public class JeiMiniaturizationPlugin implements IModPlugin { - @Override - public ResourceLocation getPluginUid() { - return new ResourceLocation(CompactCrafting.MOD_ID, "miniaturization_crafting"); - } - - @Override - public void registerCategories(IRecipeCategoryRegistration registration) { - registration.addRecipeCategories(new JeiMiniaturizationCraftingCategory(registration.getJeiHelpers().getGuiHelper())); - } - - @Override - public void registerGuiHandlers(IGuiHandlerRegistration registration) { - } - - @Override - public void registerRecipeCatalysts(IRecipeCatalystRegistration registration) { - registration.addRecipeCatalyst( - new ItemStack(CCItems.FIELD_PROJECTOR_ITEM.get(), 4), - JeiMiniaturizationCraftingCategory.RECIPE_TYPE); - - } - - @Override - public void registerRecipes(IRecipeRegistration registration) { - ClientLevel w = Minecraft.getInstance().level; - RecipeManager rm = w == null ? null : w.getRecipeManager(); - if(rm != null) { - final var miniRecipes = rm.getAllRecipesFor(CCMiniaturizationRecipes.MINIATURIZATION_RECIPE.get()); - registration.addRecipes(JeiMiniaturizationCraftingCategory.RECIPE_TYPE, miniRecipes); - } - } -} diff --git a/neoforge-main/gtfo/compat/theoneprobe/providers/FieldProjectorProvider.java b/neoforge-main/gtfo/compat/theoneprobe/providers/FieldProjectorProvider.java deleted file mode 100644 index 9cf45d2..0000000 --- a/neoforge-main/gtfo/compat/theoneprobe/providers/FieldProjectorProvider.java +++ /dev/null @@ -1,100 +0,0 @@ -package dev.compactmods.crafting.compat.theoneprobe.providers; - -import dev.compactmods.crafting.CompactCrafting; -import dev.compactmods.crafting.api.EnumCraftingState; -import dev.compactmods.crafting.api.recipe.IMiniaturizationRecipe; -import dev.compactmods.crafting.core.CCCapabilities; -import dev.compactmods.crafting.projector.FieldProjectorBlock; -import dev.compactmods.crafting.projector.FieldProjectorEntity; -import mcjty.theoneprobe.api.Color; -import mcjty.theoneprobe.api.ElementAlignment; -import mcjty.theoneprobe.api.IProbeHitData; -import mcjty.theoneprobe.api.IProbeInfo; -import mcjty.theoneprobe.api.IProbeInfoProvider; -import mcjty.theoneprobe.api.ProbeMode; -import net.minecraft.network.chat.Component; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.world.entity.player.Player; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.block.state.BlockState; - -import java.util.Set; - -public class FieldProjectorProvider implements IProbeInfoProvider { - - private static final ResourceLocation ID = new ResourceLocation(CompactCrafting.MOD_ID, "field_projector"); - @Override - public ResourceLocation getID() { - return ID; - } - - @Override - public void addProbeInfo(ProbeMode mode, IProbeInfo info, Player player, Level level, BlockState state, IProbeHitData hitData) { - if (!(state.getBlock() instanceof FieldProjectorBlock)) - return; - - // add info from server - if (FieldProjectorBlock.isActive(state) && level.getBlockEntity(hitData.getPos()) instanceof FieldProjectorEntity mFieldEntity) { - mFieldEntity.getCapability(CCCapabilities.MINIATURIZATION_FIELD) - .ifPresent(field -> { - IMiniaturizationRecipe recipe = field.getCurrentRecipe().orElse(null); - - final IProbeInfo recipeProgress = info.vertical( - info.defaultLayoutStyle() - .alignment(ElementAlignment.ALIGN_CENTER) - .spacing(1)); - - IProbeInfo group = recipeProgress.horizontal(info.defaultLayoutStyle() - .alignment(ElementAlignment.ALIGN_CENTER)); - - // group.text(new TranslationTextComponent(CompactCrafting.MOD_ID + ".top.current_recipe")); - - if(recipe != null) { - int progress = field.getProgress(); - - final Set possible = recipe.getCatalyst().getPossible(); - group.item(possible.size() > 1 ? possible.stream().findAny().get() : possible.stream().findFirst().get()); - - group.icon( - new ResourceLocation(CompactCrafting.MOD_ID, "textures/gui/jei-arrow-outputs.png"), - 0, 0, 24, 19, info.defaultIconStyle().textureHeight(19) - .textureWidth(24) - .height(19).width(24)); - - for (ItemStack out : recipe.getOutputs()) { - group.item(out); - } - - recipeProgress - .progress(1, 1, info.defaultProgressStyle() - .showText(false).borderColor(0).backgroundColor(0) - .height(0).width(110).filledColor(0) - .alternateFilledColor(0)) - - .progress(progress, recipe.getCraftingTime(), - info.defaultProgressStyle() - .height(5) - .width(100) - .showText(false) - .filledColor(0xFFCCCCCC) - .alternateFilledColor(0xFFCCCCCC) - .backgroundColor(Color.rgb(255, 250, 250, 50)) - .borderColor(0x00000000)) - ; - - if (field.getCraftingState() == EnumCraftingState.MATCHED && progress == 0) { - recipeProgress - .text(Component.translatable(CompactCrafting.MOD_ID + ".top.awaiting_catalyst")); - - } else { - if(mode == ProbeMode.EXTENDED) { - recipeProgress - .text(Component.translatable(CompactCrafting.MOD_ID + ".top.progress", progress, recipe.getCraftingTime())); - } - } - } - }); - } - } -} diff --git a/neoforge-main/gtfo/compat/theoneprobe/providers/FieldProxyProvider.java b/neoforge-main/gtfo/compat/theoneprobe/providers/FieldProxyProvider.java deleted file mode 100644 index cb4270e..0000000 --- a/neoforge-main/gtfo/compat/theoneprobe/providers/FieldProxyProvider.java +++ /dev/null @@ -1,42 +0,0 @@ -package dev.compactmods.crafting.compat.theoneprobe.providers; - -import dev.compactmods.crafting.CompactCrafting; -import dev.compactmods.crafting.core.CCCapabilities; -import dev.compactmods.crafting.proxies.block.FieldProxyBlock; -import dev.compactmods.crafting.proxies.data.BaseFieldProxyEntity; -import mcjty.theoneprobe.api.IProbeHitData; -import mcjty.theoneprobe.api.IProbeInfo; -import mcjty.theoneprobe.api.IProbeInfoProvider; -import mcjty.theoneprobe.api.ProbeMode; -import net.minecraft.core.BlockPos; -import net.minecraft.network.chat.Component; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.world.entity.player.Player; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.block.state.BlockState; - -public class FieldProxyProvider implements IProbeInfoProvider { - private static final ResourceLocation ID = new ResourceLocation(CompactCrafting.MOD_ID, "field_proxy"); - - @Override - public ResourceLocation getID() { - return ID; - } - - @Override - public void addProbeInfo(ProbeMode mode, IProbeInfo info, Player player, Level level, BlockState state, IProbeHitData hitData) { - if (!(state.getBlock() instanceof FieldProxyBlock)) - return; - - BaseFieldProxyEntity tile = (BaseFieldProxyEntity) level.getBlockEntity(hitData.getPos()); - if(tile == null) - return; - - tile.getCapability(CCCapabilities.MINIATURIZATION_FIELD) - .ifPresent(field -> { - BlockPos fieldCenter = field.getCenter(); - - info.text(Component.translatable("tooltip.compactcrafting.proxy_bound", fieldCenter.toString())); - }); - } -} diff --git a/neoforge-main/src/main/java/dev/compactmods/crafting/client/ui/ScreenArea.java b/neoforge-main/src/main/java/dev/compactmods/crafting/client/ui/ScreenArea.java new file mode 100644 index 0000000..fabe5b5 --- /dev/null +++ b/neoforge-main/src/main/java/dev/compactmods/crafting/client/ui/ScreenArea.java @@ -0,0 +1,27 @@ +package dev.compactmods.crafting.client.ui; + +public class ScreenArea { + public final int x; + public final int y; + public final int width; + public final int height; + + public ScreenArea(int x, int y, int width, int height) { + this.x = x; + this.y = y; + this.width = width; + this.height = height; + } + + public boolean contains(int mouseX, int mouseY) { + return mouseX >= x && mouseX < x + width && mouseY >= y && mouseY < y + height; + } + + public int getRight() { + return x + width; + } + + public int getBottom() { + return y + height; + } +} \ No newline at end of file diff --git a/neoforge-main/gtfo/compat/ModBusEvents.java b/neoforge-main/src/main/java/dev/compactmods/crafting/compat/ModBusEvents.java similarity index 55% rename from neoforge-main/gtfo/compat/ModBusEvents.java rename to neoforge-main/src/main/java/dev/compactmods/crafting/compat/ModBusEvents.java index 80c1b4c..83224e1 100644 --- a/neoforge-main/gtfo/compat/ModBusEvents.java +++ b/neoforge-main/src/main/java/dev/compactmods/crafting/compat/ModBusEvents.java @@ -1,13 +1,13 @@ -package dev.compactmods.crafting.events; +package dev.compactmods.crafting.compat; import dev.compactmods.crafting.CompactCrafting; import dev.compactmods.crafting.compat.theoneprobe.TheOneProbeCompat; -import net.minecraftforge.eventbus.api.SubscribeEvent; -import net.minecraftforge.fml.ModList; -import net.minecraftforge.fml.common.Mod; -import net.minecraftforge.fml.event.lifecycle.InterModEnqueueEvent; +import net.neoforged.bus.api.SubscribeEvent; +import net.neoforged.fml.ModList; +import net.neoforged.fml.common.EventBusSubscriber; +import net.neoforged.fml.event.lifecycle.InterModEnqueueEvent; -@Mod.EventBusSubscriber(modid = CompactCrafting.MOD_ID, bus = Mod.EventBusSubscriber.Bus.MOD) +@EventBusSubscriber(modid = CompactCrafting.MOD_ID, bus = EventBusSubscriber.Bus.MOD) public class ModBusEvents { @SubscribeEvent public static void enqueueIMC(final InterModEnqueueEvent event) { diff --git a/neoforge-main/src/main/java/dev/compactmods/crafting/compat/jei/JeiMiniaturizationCraftingCategory.java b/neoforge-main/src/main/java/dev/compactmods/crafting/compat/jei/JeiMiniaturizationCraftingCategory.java new file mode 100644 index 0000000..2610102 --- /dev/null +++ b/neoforge-main/src/main/java/dev/compactmods/crafting/compat/jei/JeiMiniaturizationCraftingCategory.java @@ -0,0 +1,514 @@ +//package dev.compactmods.crafting.compat.jei; +// +//import java.nio.FloatBuffer; +//import java.util.*; +//import java.util.concurrent.atomic.AtomicInteger; +//import java.util.stream.IntStream; +// +//import com.mojang.blaze3d.platform.InputConstants; +//import com.mojang.blaze3d.platform.Window; +//import com.mojang.blaze3d.systems.RenderSystem; +//import com.mojang.blaze3d.vertex.PoseStack; +//import dev.compactmods.crafting.CompactCrafting; +//import dev.compactmods.crafting.api.components.IRecipeBlockComponent; +//import dev.compactmods.crafting.api.recipe.layers.IRecipeLayer; +//import dev.compactmods.crafting.client.ui.ScreenArea; +//import dev.compactmods.crafting.core.CCBlocks; +//import dev.compactmods.crafting.recipes.MiniaturizationRecipe; +//import dev.compactmods.crafting.recipes.components.BlockComponent; +//import dev.compactmods.crafting.util.BlockSpaceUtil; +//import mezz.jei.api.constants.VanillaTypes; +//import mezz.jei.api.gui.builder.IRecipeLayoutBuilder; +//import mezz.jei.api.gui.builder.IRecipeSlotBuilder; +//import mezz.jei.api.gui.drawable.IDrawable; +//import mezz.jei.api.gui.drawable.IDrawableStatic; +//import mezz.jei.api.gui.ingredient.IRecipeSlotsView; +//import mezz.jei.api.helpers.IGuiHelper; +//import mezz.jei.api.recipe.IFocusGroup; +//import mezz.jei.api.recipe.RecipeIngredientRole; +//import mezz.jei.api.recipe.RecipeType; +//import mezz.jei.api.recipe.category.IRecipeCategory; +//import net.minecraft.ChatFormatting; +//import net.minecraft.client.Minecraft; +//import net.minecraft.client.renderer.GameRenderer; +//import net.minecraft.client.renderer.LightTexture; +//import net.minecraft.client.renderer.MultiBufferSource; +//import net.minecraft.client.renderer.block.BlockRenderDispatcher; +//import net.minecraft.client.renderer.texture.OverlayTexture; +//import net.minecraft.client.resources.sounds.SimpleSoundInstance; +//import net.minecraft.client.sounds.SoundManager; +//import net.minecraft.core.BlockPos; +//import net.minecraft.network.chat.Component; +//import net.minecraft.network.chat.MutableComponent; +//import net.minecraft.resources.ResourceLocation; +//import net.minecraft.sounds.SoundEvents; +//import net.minecraft.world.item.Item; +//import net.minecraft.world.item.ItemStack; +//import net.minecraft.world.item.Items; +//import net.minecraft.world.level.block.entity.BlockEntity; +//import net.minecraft.world.level.block.state.BlockState; +//import net.minecraft.world.phys.AABB; +//import net.minecraft.world.phys.Vec3; +//import org.lwjgl.BufferUtils; +// +//public class JeiMiniaturizationCraftingCategory implements IRecipeCategory { +// +// public static final ResourceLocation UID = new ResourceLocation(CompactCrafting.MOD_ID, "miniaturization"); +// public static final RecipeType RECIPE_TYPE = new RecipeType<>(UID, MiniaturizationRecipe.class); +// +// private final IDrawable icon; +// private final BlockRenderDispatcher blocks; +// private RenderingWorld previewLevel; +// +// private IGuiHelper guiHelper; +// private final IDrawableStatic background; +// private final IDrawableStatic slotDrawable; +// private final IDrawableStatic arrowOutputs; +// +// private boolean singleLayer = false; +// private int singleLayerOffset = 0; +// private boolean debugMode = false; +// +// private ScreenArea explodeToggle = new ScreenArea(30, 75, 10, 10); +// private ScreenArea layerUp = new ScreenArea(55, 75, 10, 10); +// private ScreenArea layerSwap = new ScreenArea(70, 75, 10, 10); +// private ScreenArea layerDown = new ScreenArea(85, 75, 10, 10); +// +// /** +// * Whether the preview is exploded (expanded) or not. +// */ +// private boolean exploded = false; +// +// /** +// * Explode multiplier; specifies how far apart blocks are rendered. +// */ +// private double explodeMulti = 1.0d; +// +// private final MutableComponent MATERIAL_COMPONENT = Component.translatable(CompactCrafting.MOD_ID + ".jei.miniaturization.component") +// .withStyle(ChatFormatting.GRAY) +// .withStyle(ChatFormatting.ITALIC); +// +// private final MutableComponent CATALYST = Component.translatable(CompactCrafting.MOD_ID + ".jei.miniaturization.catalyst") +// .withStyle(ChatFormatting.YELLOW) +// .withStyle(ChatFormatting.ITALIC); +// +// public JeiMiniaturizationCraftingCategory(IGuiHelper guiHelper) { +// int width = (9 * 18) + 10; +// int height = 60 + (10 + (18 * 3) + 5); +// +// this.guiHelper = guiHelper; +// this.background = guiHelper.createBlankDrawable(width, height); +// this.slotDrawable = guiHelper.getSlotDrawable(); +// this.icon = guiHelper.createDrawableIngredient(VanillaTypes.ITEM_STACK, new ItemStack(CCBlocks.FIELD_PROJECTOR_BLOCK.get())); +// this.arrowOutputs = guiHelper.createDrawable(new ResourceLocation(CompactCrafting.MOD_ID, "textures/gui/jei-arrow-outputs.png"), 0, 0, 24, 19); +// +// this.blocks = Minecraft.getInstance().getBlockRenderer(); +// this.previewLevel = null; +// } +// +// @Override +// public RecipeType getRecipeType() { +// return RECIPE_TYPE; +// } +// +// //region JEI implementation requirements +// @Override +// public Component getTitle() { +// return Component.translatable(CompactCrafting.MOD_ID + ".jei.miniaturization.title"); +// } +// +// @Override +// public IDrawable getBackground() { +// return background; +// } +// +// @Override +// public IDrawable getIcon() { +// return this.icon; +// } +// //endregion +// +// +// @Override +// public void setRecipe(IRecipeLayoutBuilder layout, MiniaturizationRecipe recipe, IFocusGroup focuses) { +// previewLevel = new RenderingWorld(recipe); +// +// singleLayer = false; +// singleLayerOffset = 0; +// +// try { +// addMaterialSlots(recipe, layout); +// addCatalystSlots(recipe, layout); +// +// int fromRightEdge = this.background.getWidth() - (18 * 2) - 5; +// addOutputSlots(recipe, layout, fromRightEdge); +// } catch (Exception ex) { +// CompactCrafting.LOGGER.error(recipe.getRecipeIdentifier()); +// CompactCrafting.LOGGER.error("Error displaying recipe", ex); +// } +// } +// +// private IRecipeSlotBuilder addCatalystSlots(MiniaturizationRecipe recipe, IRecipeLayoutBuilder layout) { +// final var catalystSlot = layout.addSlot(RecipeIngredientRole.CATALYST, 1, 1) +// .setBackground(slotDrawable, -1, -1); +// +// if (!recipe.getCatalyst().matches(ItemStack.EMPTY)) { +// catalystSlot.addItemStacks(new ArrayList<>(recipe.getCatalyst().getPossible())) +// .addTooltipCallback((slots, c) -> c.add(CATALYST)); +// } +// +// return catalystSlot; +// } +// +// private void addMaterialSlots(MiniaturizationRecipe recipe, IRecipeLayoutBuilder layout) { +// AtomicInteger inputOffset = new AtomicInteger(); +// +// final int GUTTER_X = 5; +// final int OFFSET_Y = 64; +// +// recipe.getComponentTotals() +// .entrySet() +// .stream() +// .filter(comp -> comp.getValue() > 0) +// .sorted(Map.Entry.comparingByValue(Comparator.reverseOrder())) +// .forEach((comp) -> { +// String component = comp.getKey(); +// int required = comp.getValue(); +// int finalInputOffset = inputOffset.get(); +// +// IRecipeBlockComponent bs = recipe.getComponents().getBlock(component).get(); +// if (bs instanceof BlockComponent bsc) { +// Item bi = bsc.getBlock().asItem(); +// +// int slotX = GUTTER_X + (finalInputOffset % 9) * 18; +// int slotY = (OFFSET_Y + 24) + ((finalInputOffset / 9) * 18); +// +// final var slot = layout.addSlot(RecipeIngredientRole.INPUT, slotX, slotY) +// .setBackground(slotDrawable, -1, -1); +// +// if (bi != Items.AIR) { +// slot.addItemStack(new ItemStack(bi, required)); +// slot.addTooltipCallback((slots, c) -> c.add(MATERIAL_COMPONENT)); +// inputOffset.getAndIncrement(); +// } +// } +// }); +// +// for (int i = inputOffset.get(); i < 18; i++) { +// int slotX = GUTTER_X + (i % 9) * 18; +// int slotY = (OFFSET_Y + 24) + ((i / 9) * 18); +// +// layout.addSlot(RecipeIngredientRole.INPUT, slotX, slotY).setBackground(slotDrawable, -1, -1); +// } +// } +// +// private void addOutputSlots(MiniaturizationRecipe recipe, IRecipeLayoutBuilder layout, int GUTTER_X) { +// final var out = recipe.getOutputs(); +// for (int outputNum = 0; outputNum < 6; outputNum++) { +// int x = (18 * (outputNum % 2)) + GUTTER_X + 1; +// int y = (18 * (outputNum / 2)) + 8 + 1; +// +// final var slot = layout.addSlot(RecipeIngredientRole.OUTPUT, x, y) +// .setBackground(slotDrawable, -1, -1); +// +// if (outputNum < out.length) +// slot.addItemStack(out[outputNum]); +// } +// } +// //endregion +// +// +// @Override +// public List getTooltipStrings(MiniaturizationRecipe recipe, IRecipeSlotsView slots, double mouseX, double mouseY) { +// if (explodeToggle.contains(mouseX, mouseY)) { +// if (!exploded) return List.of(Component.translatable("compactcrafting.jei.toggle_exploded_view")); +// else return List.of(Component.translatable("compactcrafting.jei.toggle_condensed_view")); +// } +// +// if (layerSwap.contains(mouseX, mouseY)) { +// if (singleLayer) return List.of(Component.translatable("compactcrafting.jei.all_layers_mode")); +// else return List.of(Component.translatable("compactcrafting.jei.single_layer_mode")); +// } +// +// if (layerUp.contains(mouseX, mouseY) && singleLayer) { +// if (singleLayerOffset < recipe.getDimensions().getYsize() - 1) +// return List.of(Component.translatable("compactcrafting.jei.layer_up")); +// } +// +// if (layerDown.contains(mouseX, mouseY) && singleLayer) { +// if (singleLayerOffset > 0) +// return List.of(Component.translatable("compactcrafting.jei.layer_down")); +// } +// +// return Collections.emptyList(); +// } +// +// @Override +// public boolean handleInput(MiniaturizationRecipe recipe, double mouseX, double mouseY, InputConstants.Key input) { +// if (input.getType() == InputConstants.Type.MOUSE && input.getValue() == 0) { +// SoundManager handler = Minecraft.getInstance().getSoundManager(); +// +// if (explodeToggle.contains(mouseX, mouseY)) { +// explodeMulti = exploded ? 1.0d : 1.6d; +// exploded = !exploded; +// handler.play(SimpleSoundInstance.forUI(SoundEvents.UI_BUTTON_CLICK, 1.0F)); +// return true; +// } +// +// if (layerSwap.contains(mouseX, mouseY)) { +// singleLayer = !singleLayer; +// handler.play(SimpleSoundInstance.forUI(SoundEvents.UI_BUTTON_CLICK, 1.0F)); +// return true; +// } +// +// if (layerUp.contains(mouseX, mouseY) && singleLayer) { +// if (singleLayerOffset < recipe.getDimensions().getYsize() - 1) { +// handler.play(SimpleSoundInstance.forUI(SoundEvents.UI_BUTTON_CLICK, 1.0F)); +// singleLayerOffset++; +// } +// return true; +// } +// +// if (layerDown.contains(mouseX, mouseY) && singleLayer) { +// if (singleLayerOffset > 0) { +// handler.play(SimpleSoundInstance.forUI(SoundEvents.UI_BUTTON_CLICK, 1.0F)); +// singleLayerOffset--; +// } +// +// return true; +// } +// } +// +// return false; +// } +// +// //region Rendering help +// private void drawScaledTexture( +// PoseStack matrixStack, +// ResourceLocation texture, +// ScreenArea area, +// float u, float v, +// int uWidth, int vHeight, +// int textureWidth, int textureHeight) { +// +// RenderSystem.setShader(GameRenderer::getPositionTexShader); +// RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); +// RenderSystem.setShaderTexture(0, texture); +// +// RenderSystem.enableDepthTest(); +// GuiComponent.blit(matrixStack, area.x, area.y, area.width, area.height, u, v, uWidth, vHeight, textureWidth, textureHeight); +// } +// +// //endregion +// +// @Override +// public void draw(MiniaturizationRecipe recipe, IRecipeSlotsView slots, PoseStack pose, double mouseX, double mouseY) { +// AABB dims = recipe.getDimensions(); +// +// Window mainWindow = Minecraft.getInstance().getWindow(); +// +// drawScaledTexture(pose, +// new ResourceLocation(CompactCrafting.MOD_ID, "textures/gui/jei-arrow-field.png"), +// new ScreenArea(7, 20, 17, 22), +// 0, 0, 17, 22, 17, 22); +// +// drawScaledTexture(pose, +// new ResourceLocation(CompactCrafting.MOD_ID, "textures/gui/jei-arrow-outputs.png"), +// new ScreenArea(100, 25, 24, 19), +// 0, 0, 24, 19, 24, 19); +// +// int scissorX = 27; +// int scissorY = 0; +// +// double guiScaleFactor = mainWindow.getGuiScale(); +// ScreenArea scissorBounds = new ScreenArea( +// scissorX, scissorY, +// 70, +// 70 +// ); +// +// renderPreviewControls(pose, dims); +// +// if (previewLevel != null) renderRecipe(recipe, pose, dims, guiScaleFactor, scissorBounds); +// } +// +// private void renderRecipe(MiniaturizationRecipe recipe, PoseStack mx, AABB dims, double guiScaleFactor, ScreenArea scissorBounds) { +// try { +// GuiComponent.fill( +// mx, +// scissorBounds.x, scissorBounds.y, +// scissorBounds.x + scissorBounds.width, +// scissorBounds.height, +// 0xFF404040 +// ); +// +// MultiBufferSource.BufferSource buffers = Minecraft.getInstance().renderBuffers().bufferSource(); +// +// final double scale = Minecraft.getInstance().getWindow().getGuiScale(); +// final Matrix4f matrix = mx.last().pose(); +// final FloatBuffer buf = BufferUtils.createFloatBuffer(16); +// matrix.store(buf); +// +// // { x, y, z } +// Vec3 translation = new Vec3( +// buf.get(12) * scale, +// buf.get(13) * scale, +// buf.get(14) * scale); +// +// scissorBounds.x *= scale; +// scissorBounds.y *= scale; +// scissorBounds.width *= scale; +// scissorBounds.height *= scale; +// final int scissorX = Math.round(Math.round(translation.x + scissorBounds.x)); +// final int scissorY = Math.round(Math.round(Minecraft.getInstance().getWindow().getHeight() - scissorBounds.y - scissorBounds.height - translation.y)); +// final int scissorW = Math.round(scissorBounds.width); +// final int scissorH = Math.round(scissorBounds.height); +// RenderSystem.enableScissor(scissorX, scissorY, scissorW, scissorH); +// +// mx.pushPose(); +// +// mx.translate( +// 27 + (35), +// scissorBounds.y + (35), +// 100); +// +// Vec3 dimsVec = new Vec3(dims.getXsize(), dims.getYsize(), dims.getZsize()); +// float recipeAvgDim = (float) dimsVec.length(); +// float previewScale = (float) ((3 + Math.exp(3 - (recipeAvgDim / 5))) / explodeMulti); +// mx.scale(previewScale, -previewScale, previewScale); +// +// drawActualRecipe(recipe, mx, dims, buffers); +// +// mx.popPose(); +// +// buffers.endBatch(); +// +// RenderSystem.disableScissor(); +// } catch (Exception ex) { +// CompactCrafting.LOGGER.warn(ex); +// } +// } +// +// private void drawActualRecipe(MiniaturizationRecipe recipe, PoseStack mx, AABB dims, MultiBufferSource.BufferSource buffers) { +// double gameTime = Minecraft.getInstance().level.getGameTime(); +// double test = Math.toDegrees(gameTime) / 15; +// mx.mulPose(new Quaternion(35f, +// (float) -test, +// 0, +// true)); +// +// double ySize = recipe.getDimensions().getYsize(); +// +// // Variable explode based on mouse position (clamped) +// // double explodeMulti = MathHelper.clamp(mouseX, 0, this.background.getWidth())/this.background.getWidth()*2+1; +// +// int[] renderLayers; +// if (!singleLayer) { +// renderLayers = IntStream.range(0, (int) ySize).toArray(); +// } else { +// renderLayers = new int[]{singleLayerOffset}; +// } +// +// mx.translate( +// -(dims.getXsize() / 2) * explodeMulti - 0.5, +// -(dims.getYsize() / 2) * explodeMulti - 0.5, +// -(dims.getZsize() / 2) * explodeMulti - 0.5 +// ); +// +// for (int y : renderLayers) { +// recipe.getLayer(y).ifPresent(l -> renderRecipeLayer(recipe, mx, buffers, l, y)); +// } +// } +// +// private void renderPreviewControls(PoseStack mx, AABB dims) { +// mx.pushPose(); +// mx.translate(0, 0, 10); +// +// ResourceLocation sprites = new ResourceLocation(CompactCrafting.MOD_ID, "textures/gui/jei-sprites.png"); +// +// if (exploded) { +// drawScaledTexture(mx, sprites, explodeToggle, 20, 0, 20, 20, 120, 20); +// } else { +// drawScaledTexture(mx, sprites, explodeToggle, 0, 0, 20, 20, 120, 20); +// } +// +// // Layer change buttons +// if (singleLayer) { +// drawScaledTexture(mx, sprites, layerSwap, 60, 0, 20, 20, 120, 20); +// } else { +// drawScaledTexture(mx, sprites, layerSwap, 40, 0, 20, 20, 120, 20); +// } +// +// if (singleLayer) { +// if (singleLayerOffset < dims.getYsize() - 1) +// drawScaledTexture(mx, sprites, layerUp, 80, 0, 20, 20, 120, 20); +// +// if (singleLayerOffset > 0) { +// drawScaledTexture(mx, sprites, layerDown, 100, 0, 20, 20, 120, 20); +// } +// } +// +// // drawScaledTexture(mx, sprites, bindPlate, 120, 0, 20, 20, 140, 20); +// +// mx.popPose(); +// } +// +// private void renderRecipeLayer(MiniaturizationRecipe recipe, PoseStack mx, MultiBufferSource.BufferSource buffers, IRecipeLayer l, int layerY) { +// // Begin layer +// mx.pushPose(); +// +// AABB layerBounds = BlockSpaceUtil.getLayerBounds(recipe.getDimensions(), layerY); +// BlockPos.betweenClosedStream(layerBounds).forEach(filledPos -> { +// mx.pushPose(); +// +// mx.translate( +// ((filledPos.getX() + 0.5) * explodeMulti), +// ((layerY + 0.5) * explodeMulti), +// ((filledPos.getZ() + 0.5) * explodeMulti) +// ); +// +// BlockPos zeroedPos = filledPos.below(layerY); +// Optional componentForPosition = l.getComponentForPosition(zeroedPos); +// componentForPosition +// .flatMap(recipe.getComponents()::getBlock) +// .ifPresent(comp -> renderComponent(mx, buffers, comp, filledPos)); +// +// mx.popPose(); +// }); +// +// // Done with layer +// mx.popPose(); +// } +// +// private void renderComponent(PoseStack mx, MultiBufferSource.BufferSource buffers, IRecipeBlockComponent state, BlockPos filledPos) { +// // TODO - Render switching at fixed interval +// if (state.didErrorRendering()) +// return; +// +// BlockState state1 = state.getRenderState(); +// +// ModelData data = ModelData.EMPTY; +// if (previewLevel != null && state1.hasBlockEntity()) { +// // create fake world instance +// // get tile entity - extend EmptyBlockReader with impl +// BlockEntity be = previewLevel.getBlockEntity(filledPos); +// if (be != null) +// data = be.getModelData(); +// } +// +// try { +// // TODO: Revisit render types +// blocks.renderSingleBlock(state1, +// mx, +// buffers, +// LightTexture.FULL_SKY, +// OverlayTexture.NO_OVERLAY, +// data, null); +// } catch (Exception e) { +// state.markRenderingErrored(); +// +// CompactCrafting.LOGGER.warn("Error rendering block in preview: {}", state1); +// CompactCrafting.LOGGER.error("Stack Trace", e); +// } +// } +//} \ No newline at end of file diff --git a/neoforge-main/src/main/java/dev/compactmods/crafting/compat/jei/JeiMiniaturizationPlugin.java b/neoforge-main/src/main/java/dev/compactmods/crafting/compat/jei/JeiMiniaturizationPlugin.java new file mode 100644 index 0000000..acbe8b5 --- /dev/null +++ b/neoforge-main/src/main/java/dev/compactmods/crafting/compat/jei/JeiMiniaturizationPlugin.java @@ -0,0 +1,51 @@ +//package dev.compactmods.crafting.compat.jei; +// +//import dev.compactmods.crafting.CompactCrafting; +//import dev.compactmods.crafting.core.CCItems; +//import dev.compactmods.crafting.core.CCMiniaturizationRecipes; +//import mezz.jei.api.IModPlugin; +//import mezz.jei.api.JeiPlugin; +//import mezz.jei.api.registration.IGuiHandlerRegistration; +//import mezz.jei.api.registration.IRecipeCatalystRegistration; +//import mezz.jei.api.registration.IRecipeCategoryRegistration; +//import mezz.jei.api.registration.IRecipeRegistration; +//import net.minecraft.client.Minecraft; +//import net.minecraft.client.multiplayer.ClientLevel; +//import net.minecraft.resources.ResourceLocation; +//import net.minecraft.world.item.ItemStack; +//import net.minecraft.world.item.crafting.RecipeManager; +// +//@JeiPlugin +//public class JeiMiniaturizationPlugin implements IModPlugin { +// @Override +// public ResourceLocation getPluginUid() { +// return new ResourceLocation(CompactCrafting.MOD_ID, "miniaturization_crafting"); +// } +// +// @Override +// public void registerCategories(IRecipeCategoryRegistration registration) { +// registration.addRecipeCategories(new JeiMiniaturizationCraftingCategory(registration.getJeiHelpers().getGuiHelper())); +// } +// +// @Override +// public void registerGuiHandlers(IGuiHandlerRegistration registration) { +// } +// +// @Override +// public void registerRecipeCatalysts(IRecipeCatalystRegistration registration) { +// registration.addRecipeCatalyst( +// new ItemStack(CCItems.FIELD_PROJECTOR_ITEM.get(), 4), +// JeiMiniaturizationCraftingCategory.RECIPE_TYPE); +// +// } +// +// @Override +// public void registerRecipes(IRecipeRegistration registration) { +// ClientLevel w = Minecraft.getInstance().level; +// RecipeManager rm = w == null ? null : w.getRecipeManager(); +// if(rm != null) { +// final var miniRecipes = rm.getAllRecipesFor(CCMiniaturizationRecipes.MINIATURIZATION_RECIPE.get()); +// registration.addRecipes(JeiMiniaturizationCraftingCategory.RECIPE_TYPE, miniRecipes); +// } +// } +//} diff --git a/neoforge-main/gtfo/compat/theoneprobe/TOPMain.java b/neoforge-main/src/main/java/dev/compactmods/crafting/compat/theoneprobe/TOPMain.java similarity index 77% rename from neoforge-main/gtfo/compat/theoneprobe/TOPMain.java rename to neoforge-main/src/main/java/dev/compactmods/crafting/compat/theoneprobe/TOPMain.java index adf441a..f5ff785 100644 --- a/neoforge-main/gtfo/compat/theoneprobe/TOPMain.java +++ b/neoforge-main/src/main/java/dev/compactmods/crafting/compat/theoneprobe/TOPMain.java @@ -1,7 +1,6 @@ package dev.compactmods.crafting.compat.theoneprobe; import dev.compactmods.crafting.compat.theoneprobe.providers.FieldProjectorProvider; -import dev.compactmods.crafting.compat.theoneprobe.providers.FieldProxyProvider; import mcjty.theoneprobe.api.ITheOneProbe; import java.util.function.Function; @@ -13,7 +12,6 @@ class TOPMain implements Function { public Void apply(Object o) { PROBE = (ITheOneProbe) o; PROBE.registerProvider(new FieldProjectorProvider()); - PROBE.registerProvider(new FieldProxyProvider()); return null; } diff --git a/neoforge-main/gtfo/compat/theoneprobe/TheOneProbeCompat.java b/neoforge-main/src/main/java/dev/compactmods/crafting/compat/theoneprobe/TheOneProbeCompat.java similarity index 82% rename from neoforge-main/gtfo/compat/theoneprobe/TheOneProbeCompat.java rename to neoforge-main/src/main/java/dev/compactmods/crafting/compat/theoneprobe/TheOneProbeCompat.java index 48cef4a..63b8310 100644 --- a/neoforge-main/gtfo/compat/theoneprobe/TheOneProbeCompat.java +++ b/neoforge-main/src/main/java/dev/compactmods/crafting/compat/theoneprobe/TheOneProbeCompat.java @@ -1,9 +1,9 @@ package dev.compactmods.crafting.compat.theoneprobe; -import net.minecraftforge.fml.InterModComms; -public class TheOneProbeCompat { +import net.neoforged.fml.InterModComms; +public class TheOneProbeCompat { public static void sendIMC() { InterModComms.sendTo("theoneprobe", "getTheOneProbe", TOPMain::new); diff --git a/neoforge-main/src/main/java/dev/compactmods/crafting/compat/theoneprobe/providers/FieldProjectorProvider.java b/neoforge-main/src/main/java/dev/compactmods/crafting/compat/theoneprobe/providers/FieldProjectorProvider.java new file mode 100644 index 0000000..b4e0090 --- /dev/null +++ b/neoforge-main/src/main/java/dev/compactmods/crafting/compat/theoneprobe/providers/FieldProjectorProvider.java @@ -0,0 +1,108 @@ +package dev.compactmods.crafting.compat.theoneprobe.providers; + +import dev.compactmods.crafting.CompactCrafting; +import dev.compactmods.crafting.api.EnumCraftingState; +import dev.compactmods.crafting.api.field.IMiniaturizationField; +import dev.compactmods.crafting.data.CCAttachments; +import dev.compactmods.crafting.projector.FieldProjectorBlock; +import dev.compactmods.crafting.projector.FieldProjectorEntity; +import dev.compactmods.crafting.projector.ProjectorHelper; +import dev.compactmods.crafting.recipes.MiniaturizationRecipe; +import mcjty.theoneprobe.api.Color; +import mcjty.theoneprobe.api.ElementAlignment; +import mcjty.theoneprobe.api.IProbeHitData; +import mcjty.theoneprobe.api.IProbeInfo; +import mcjty.theoneprobe.api.IProbeInfoProvider; +import mcjty.theoneprobe.api.ProbeMode; +import net.minecraft.network.chat.Component; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.Items; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.state.BlockState; + +import java.util.Set; + +public class FieldProjectorProvider implements IProbeInfoProvider { + + private static final ResourceLocation ID = ResourceLocation.fromNamespaceAndPath(CompactCrafting.MOD_ID, "field_projector"); + @Override + public ResourceLocation getID() { + return ID; + } + + @Override + public void addProbeInfo(ProbeMode mode, IProbeInfo info, Player player, Level level, BlockState state, IProbeHitData hitData) { + if (!(state.getBlock() instanceof FieldProjectorBlock)) + return; + + // add info from server + if (FieldProjectorBlock.isActive(state) && level.getBlockEntity(hitData.getPos()) instanceof FieldProjectorEntity mFieldEntity) { + // Find the field this projector belongs to + ProjectorHelper.getClosestOppositeSize(level, hitData.getPos()).ifPresent(size -> { + final var center = size.getCenterFromProjector(hitData.getPos(), state.getValue(FieldProjectorBlock.FACING)); + level.getData(CCAttachments.ACTIVE_FIELDS).get(center).ifPresent(field -> { + MiniaturizationRecipe recipe = field.recipeHolder() != null ? field.recipeHolder().value() : null; + + final IProbeInfo recipeProgress = info.vertical( + info.defaultLayoutStyle() + .alignment(ElementAlignment.ALIGN_CENTER) + .spacing(1)); + + IProbeInfo group = recipeProgress.horizontal(info.defaultLayoutStyle() + .alignment(ElementAlignment.ALIGN_CENTER)); + + // group.text(new TranslationTextComponent(CompactCrafting.MOD_ID + ".top.current_recipe")); + + if(recipe != null) { + int progress = field.getProgress(); + + // Get catalyst from recipe + var catalystTest = recipe.catalystTest(); + // For display, show the first possible catalyst (simplified) + group.item(new ItemStack(Items.REDSTONE)); // placeholder + + group.icon( + ResourceLocation.fromNamespaceAndPath(CompactCrafting.MOD_ID, "textures/gui/jei-arrow-outputs.png"), + 0, 0, 24, 19, info.defaultIconStyle().textureHeight(19) + .textureWidth(24) + .height(19).width(24)); + + for (ItemStack out : recipe.getOutputs()) { + group.item(out); + } + + recipeProgress + .progress(1, 1, info.defaultProgressStyle() + .showText(false).borderColor(0).backgroundColor(0) + .height(0).width(110).filledColor(0) + .alternateFilledColor(0)) + + .progress(progress, recipe.getCraftingTime(), + info.defaultProgressStyle() + .height(5) + .width(100) + .showText(false) + .filledColor(0xFFCCCCCC) + .alternateFilledColor(0xFFCCCCCC) + .backgroundColor(Color.rgb(255, 250, 250, 50)) + .borderColor(0x00000000)) + ; + + if (field.getCraftingState() == EnumCraftingState.MATCHED && progress == 0) { + recipeProgress + .text(Component.translatable(CompactCrafting.MOD_ID + ".top.awaiting_catalyst")); + + } else { + if(mode == ProbeMode.EXTENDED) { + recipeProgress + .text(Component.translatable(CompactCrafting.MOD_ID + ".top.progress", progress, recipe.getCraftingTime())); + } + } + } + }); + }); + } + } +} diff --git a/neoforge-main/gtfo/fakeworld/RecipeChunk.java b/neoforge-main/src/main/java/dev/compactmods/crafting/fakeworld/RecipeChunk.java similarity index 100% rename from neoforge-main/gtfo/fakeworld/RecipeChunk.java rename to neoforge-main/src/main/java/dev/compactmods/crafting/fakeworld/RecipeChunk.java diff --git a/neoforge-main/gtfo/fakeworld/RenderingChunkProvider.java b/neoforge-main/src/main/java/dev/compactmods/crafting/fakeworld/RenderingChunkProvider.java similarity index 100% rename from neoforge-main/gtfo/fakeworld/RenderingChunkProvider.java rename to neoforge-main/src/main/java/dev/compactmods/crafting/fakeworld/RenderingChunkProvider.java diff --git a/neoforge-main/gtfo/fakeworld/RenderingSpawnInfo.java b/neoforge-main/src/main/java/dev/compactmods/crafting/fakeworld/RenderingSpawnInfo.java similarity index 100% rename from neoforge-main/gtfo/fakeworld/RenderingSpawnInfo.java rename to neoforge-main/src/main/java/dev/compactmods/crafting/fakeworld/RenderingSpawnInfo.java diff --git a/neoforge-main/gtfo/fakeworld/RenderingWorld.java b/neoforge-main/src/main/java/dev/compactmods/crafting/fakeworld/RenderingWorld.java similarity index 99% rename from neoforge-main/gtfo/fakeworld/RenderingWorld.java rename to neoforge-main/src/main/java/dev/compactmods/crafting/fakeworld/RenderingWorld.java index 33a8a2a..dbe0c0c 100644 --- a/neoforge-main/gtfo/fakeworld/RenderingWorld.java +++ b/neoforge-main/src/main/java/dev/compactmods/crafting/fakeworld/RenderingWorld.java @@ -1,4 +1,4 @@ -//package dev.compactmods.crafting.client.fakeworld; +package dev.compactmods.crafting.fakeworld; // //import dev.compactmods.crafting.recipes.MiniaturizationRecipe; //import net.minecraft.client.Minecraft; diff --git a/neoforge-main/src/main/resources/data/compactcrafting/recipe/oak_door.json b/neoforge-main/src/main/resources/data/compactcrafting/recipe/oak_door.json new file mode 100644 index 0000000..7092c4d --- /dev/null +++ b/neoforge-main/src/main/resources/data/compactcrafting/recipe/oak_door.json @@ -0,0 +1,30 @@ +{ + "type": "compactcrafting:miniaturization", + "version": 1, + "recipeSize": 1, + "layers": [ + { + "type": "compactcrafting:filled", + "component": "P" + }, + { + "type": "compactcrafting:filled", + "component": "P" + } + ], + "catalyst": { + "id": "minecraft:iron_ingot" + }, + "components": { + "P": { + "type": "compactcrafting:block", + "block": "minecraft:oak_planks" + } + }, + "outputs": [ + { + "id": "minecraft:oak_door", + "Count": 1 + } + ] +} \ No newline at end of file From eeb498eb2d049cfead41ebbb8da5da16bdd1a1b3 Mon Sep 17 00:00:00 2001 From: Leclowndu93150 Date: Wed, 24 Sep 2025 00:57:32 +0200 Subject: [PATCH 03/20] the progress is insane --- .../crafting/client/render/GhostRenderer.java | 1 + .../field/MiniaturizationFieldRenderer.java | 2 +- .../JeiMiniaturizationCraftingCategory.java | 1033 +++++++++-------- .../compat/jei/JeiMiniaturizationPlugin.java | 103 +- .../crafting/fakeworld/RecipeChunk.java | 171 ++- .../fakeworld/RenderingChunkProvider.java | 166 +-- .../fakeworld/RenderingSpawnInfo.java | 198 ++-- .../crafting/fakeworld/RenderingWorld.java | 402 ++++--- .../crafting/field/MiniaturizationField.java | 6 + .../field/render/CraftingPreviewRenderer.java | 75 +- .../projector/FieldProjectorBlock.java | 3 +- .../recipes/MiniaturizationRecipe.java | 29 +- .../data/compactcrafting/recipe/oak_door.json | 2 +- 13 files changed, 1136 insertions(+), 1055 deletions(-) diff --git a/neoforge-main/src/main/java/dev/compactmods/crafting/client/render/GhostRenderer.java b/neoforge-main/src/main/java/dev/compactmods/crafting/client/render/GhostRenderer.java index 6020854..6f5e410 100644 --- a/neoforge-main/src/main/java/dev/compactmods/crafting/client/render/GhostRenderer.java +++ b/neoforge-main/src/main/java/dev/compactmods/crafting/client/render/GhostRenderer.java @@ -68,6 +68,7 @@ public static void renderTransparentBlock(BlockState state, @Nullable BlockPos p } public static void renderTransparentBlock(BlockState state, @Nullable BlockPos pos, PoseStack matrix, MultiBufferSource buffer, int ticksLeft) { + System.out.println("Rendering ghost block: " + state); final Minecraft mc = Minecraft.getInstance(); final BlockColors colors = mc.getBlockColors(); diff --git a/neoforge-main/src/main/java/dev/compactmods/crafting/client/render/field/MiniaturizationFieldRenderer.java b/neoforge-main/src/main/java/dev/compactmods/crafting/client/render/field/MiniaturizationFieldRenderer.java index da3273f..cb86cc1 100644 --- a/neoforge-main/src/main/java/dev/compactmods/crafting/client/render/field/MiniaturizationFieldRenderer.java +++ b/neoforge-main/src/main/java/dev/compactmods/crafting/client/render/field/MiniaturizationFieldRenderer.java @@ -63,7 +63,7 @@ public static void render(Level level, IMiniaturizationField { -// -// public static final ResourceLocation UID = new ResourceLocation(CompactCrafting.MOD_ID, "miniaturization"); -// public static final RecipeType RECIPE_TYPE = new RecipeType<>(UID, MiniaturizationRecipe.class); -// -// private final IDrawable icon; -// private final BlockRenderDispatcher blocks; -// private RenderingWorld previewLevel; -// -// private IGuiHelper guiHelper; -// private final IDrawableStatic background; -// private final IDrawableStatic slotDrawable; -// private final IDrawableStatic arrowOutputs; -// -// private boolean singleLayer = false; -// private int singleLayerOffset = 0; -// private boolean debugMode = false; -// -// private ScreenArea explodeToggle = new ScreenArea(30, 75, 10, 10); -// private ScreenArea layerUp = new ScreenArea(55, 75, 10, 10); -// private ScreenArea layerSwap = new ScreenArea(70, 75, 10, 10); -// private ScreenArea layerDown = new ScreenArea(85, 75, 10, 10); -// -// /** -// * Whether the preview is exploded (expanded) or not. -// */ -// private boolean exploded = false; -// -// /** -// * Explode multiplier; specifies how far apart blocks are rendered. -// */ -// private double explodeMulti = 1.0d; -// -// private final MutableComponent MATERIAL_COMPONENT = Component.translatable(CompactCrafting.MOD_ID + ".jei.miniaturization.component") -// .withStyle(ChatFormatting.GRAY) -// .withStyle(ChatFormatting.ITALIC); -// -// private final MutableComponent CATALYST = Component.translatable(CompactCrafting.MOD_ID + ".jei.miniaturization.catalyst") -// .withStyle(ChatFormatting.YELLOW) -// .withStyle(ChatFormatting.ITALIC); -// -// public JeiMiniaturizationCraftingCategory(IGuiHelper guiHelper) { -// int width = (9 * 18) + 10; -// int height = 60 + (10 + (18 * 3) + 5); -// -// this.guiHelper = guiHelper; -// this.background = guiHelper.createBlankDrawable(width, height); -// this.slotDrawable = guiHelper.getSlotDrawable(); -// this.icon = guiHelper.createDrawableIngredient(VanillaTypes.ITEM_STACK, new ItemStack(CCBlocks.FIELD_PROJECTOR_BLOCK.get())); -// this.arrowOutputs = guiHelper.createDrawable(new ResourceLocation(CompactCrafting.MOD_ID, "textures/gui/jei-arrow-outputs.png"), 0, 0, 24, 19); -// -// this.blocks = Minecraft.getInstance().getBlockRenderer(); -// this.previewLevel = null; -// } -// -// @Override -// public RecipeType getRecipeType() { -// return RECIPE_TYPE; -// } -// -// //region JEI implementation requirements -// @Override -// public Component getTitle() { -// return Component.translatable(CompactCrafting.MOD_ID + ".jei.miniaturization.title"); -// } -// -// @Override -// public IDrawable getBackground() { -// return background; -// } -// -// @Override -// public IDrawable getIcon() { -// return this.icon; -// } -// //endregion -// -// -// @Override -// public void setRecipe(IRecipeLayoutBuilder layout, MiniaturizationRecipe recipe, IFocusGroup focuses) { -// previewLevel = new RenderingWorld(recipe); -// -// singleLayer = false; -// singleLayerOffset = 0; -// -// try { -// addMaterialSlots(recipe, layout); -// addCatalystSlots(recipe, layout); -// -// int fromRightEdge = this.background.getWidth() - (18 * 2) - 5; -// addOutputSlots(recipe, layout, fromRightEdge); -// } catch (Exception ex) { -// CompactCrafting.LOGGER.error(recipe.getRecipeIdentifier()); -// CompactCrafting.LOGGER.error("Error displaying recipe", ex); -// } -// } -// -// private IRecipeSlotBuilder addCatalystSlots(MiniaturizationRecipe recipe, IRecipeLayoutBuilder layout) { -// final var catalystSlot = layout.addSlot(RecipeIngredientRole.CATALYST, 1, 1) -// .setBackground(slotDrawable, -1, -1); -// -// if (!recipe.getCatalyst().matches(ItemStack.EMPTY)) { -// catalystSlot.addItemStacks(new ArrayList<>(recipe.getCatalyst().getPossible())) -// .addTooltipCallback((slots, c) -> c.add(CATALYST)); -// } -// -// return catalystSlot; -// } -// -// private void addMaterialSlots(MiniaturizationRecipe recipe, IRecipeLayoutBuilder layout) { -// AtomicInteger inputOffset = new AtomicInteger(); -// -// final int GUTTER_X = 5; -// final int OFFSET_Y = 64; -// -// recipe.getComponentTotals() -// .entrySet() -// .stream() -// .filter(comp -> comp.getValue() > 0) -// .sorted(Map.Entry.comparingByValue(Comparator.reverseOrder())) -// .forEach((comp) -> { -// String component = comp.getKey(); -// int required = comp.getValue(); -// int finalInputOffset = inputOffset.get(); -// -// IRecipeBlockComponent bs = recipe.getComponents().getBlock(component).get(); -// if (bs instanceof BlockComponent bsc) { -// Item bi = bsc.getBlock().asItem(); -// -// int slotX = GUTTER_X + (finalInputOffset % 9) * 18; -// int slotY = (OFFSET_Y + 24) + ((finalInputOffset / 9) * 18); -// -// final var slot = layout.addSlot(RecipeIngredientRole.INPUT, slotX, slotY) -// .setBackground(slotDrawable, -1, -1); -// -// if (bi != Items.AIR) { -// slot.addItemStack(new ItemStack(bi, required)); -// slot.addTooltipCallback((slots, c) -> c.add(MATERIAL_COMPONENT)); -// inputOffset.getAndIncrement(); -// } -// } -// }); -// -// for (int i = inputOffset.get(); i < 18; i++) { -// int slotX = GUTTER_X + (i % 9) * 18; -// int slotY = (OFFSET_Y + 24) + ((i / 9) * 18); -// -// layout.addSlot(RecipeIngredientRole.INPUT, slotX, slotY).setBackground(slotDrawable, -1, -1); -// } -// } -// -// private void addOutputSlots(MiniaturizationRecipe recipe, IRecipeLayoutBuilder layout, int GUTTER_X) { -// final var out = recipe.getOutputs(); -// for (int outputNum = 0; outputNum < 6; outputNum++) { -// int x = (18 * (outputNum % 2)) + GUTTER_X + 1; -// int y = (18 * (outputNum / 2)) + 8 + 1; -// -// final var slot = layout.addSlot(RecipeIngredientRole.OUTPUT, x, y) -// .setBackground(slotDrawable, -1, -1); -// -// if (outputNum < out.length) -// slot.addItemStack(out[outputNum]); -// } -// } -// //endregion -// -// -// @Override -// public List getTooltipStrings(MiniaturizationRecipe recipe, IRecipeSlotsView slots, double mouseX, double mouseY) { -// if (explodeToggle.contains(mouseX, mouseY)) { -// if (!exploded) return List.of(Component.translatable("compactcrafting.jei.toggle_exploded_view")); -// else return List.of(Component.translatable("compactcrafting.jei.toggle_condensed_view")); -// } -// -// if (layerSwap.contains(mouseX, mouseY)) { -// if (singleLayer) return List.of(Component.translatable("compactcrafting.jei.all_layers_mode")); -// else return List.of(Component.translatable("compactcrafting.jei.single_layer_mode")); -// } -// -// if (layerUp.contains(mouseX, mouseY) && singleLayer) { -// if (singleLayerOffset < recipe.getDimensions().getYsize() - 1) -// return List.of(Component.translatable("compactcrafting.jei.layer_up")); -// } -// -// if (layerDown.contains(mouseX, mouseY) && singleLayer) { -// if (singleLayerOffset > 0) -// return List.of(Component.translatable("compactcrafting.jei.layer_down")); -// } -// -// return Collections.emptyList(); -// } -// -// @Override -// public boolean handleInput(MiniaturizationRecipe recipe, double mouseX, double mouseY, InputConstants.Key input) { -// if (input.getType() == InputConstants.Type.MOUSE && input.getValue() == 0) { -// SoundManager handler = Minecraft.getInstance().getSoundManager(); -// -// if (explodeToggle.contains(mouseX, mouseY)) { -// explodeMulti = exploded ? 1.0d : 1.6d; -// exploded = !exploded; -// handler.play(SimpleSoundInstance.forUI(SoundEvents.UI_BUTTON_CLICK, 1.0F)); -// return true; -// } -// -// if (layerSwap.contains(mouseX, mouseY)) { -// singleLayer = !singleLayer; -// handler.play(SimpleSoundInstance.forUI(SoundEvents.UI_BUTTON_CLICK, 1.0F)); -// return true; -// } -// -// if (layerUp.contains(mouseX, mouseY) && singleLayer) { -// if (singleLayerOffset < recipe.getDimensions().getYsize() - 1) { -// handler.play(SimpleSoundInstance.forUI(SoundEvents.UI_BUTTON_CLICK, 1.0F)); -// singleLayerOffset++; -// } -// return true; -// } -// -// if (layerDown.contains(mouseX, mouseY) && singleLayer) { -// if (singleLayerOffset > 0) { -// handler.play(SimpleSoundInstance.forUI(SoundEvents.UI_BUTTON_CLICK, 1.0F)); -// singleLayerOffset--; -// } -// -// return true; -// } -// } -// -// return false; -// } -// -// //region Rendering help -// private void drawScaledTexture( -// PoseStack matrixStack, -// ResourceLocation texture, -// ScreenArea area, -// float u, float v, -// int uWidth, int vHeight, -// int textureWidth, int textureHeight) { -// -// RenderSystem.setShader(GameRenderer::getPositionTexShader); -// RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); -// RenderSystem.setShaderTexture(0, texture); -// -// RenderSystem.enableDepthTest(); -// GuiComponent.blit(matrixStack, area.x, area.y, area.width, area.height, u, v, uWidth, vHeight, textureWidth, textureHeight); -// } -// -// //endregion -// -// @Override -// public void draw(MiniaturizationRecipe recipe, IRecipeSlotsView slots, PoseStack pose, double mouseX, double mouseY) { -// AABB dims = recipe.getDimensions(); -// -// Window mainWindow = Minecraft.getInstance().getWindow(); -// -// drawScaledTexture(pose, -// new ResourceLocation(CompactCrafting.MOD_ID, "textures/gui/jei-arrow-field.png"), -// new ScreenArea(7, 20, 17, 22), -// 0, 0, 17, 22, 17, 22); -// -// drawScaledTexture(pose, -// new ResourceLocation(CompactCrafting.MOD_ID, "textures/gui/jei-arrow-outputs.png"), -// new ScreenArea(100, 25, 24, 19), -// 0, 0, 24, 19, 24, 19); -// -// int scissorX = 27; -// int scissorY = 0; -// -// double guiScaleFactor = mainWindow.getGuiScale(); -// ScreenArea scissorBounds = new ScreenArea( -// scissorX, scissorY, -// 70, -// 70 -// ); -// -// renderPreviewControls(pose, dims); -// -// if (previewLevel != null) renderRecipe(recipe, pose, dims, guiScaleFactor, scissorBounds); -// } -// -// private void renderRecipe(MiniaturizationRecipe recipe, PoseStack mx, AABB dims, double guiScaleFactor, ScreenArea scissorBounds) { -// try { -// GuiComponent.fill( -// mx, -// scissorBounds.x, scissorBounds.y, -// scissorBounds.x + scissorBounds.width, -// scissorBounds.height, -// 0xFF404040 -// ); -// -// MultiBufferSource.BufferSource buffers = Minecraft.getInstance().renderBuffers().bufferSource(); -// -// final double scale = Minecraft.getInstance().getWindow().getGuiScale(); -// final Matrix4f matrix = mx.last().pose(); -// final FloatBuffer buf = BufferUtils.createFloatBuffer(16); -// matrix.store(buf); -// -// // { x, y, z } -// Vec3 translation = new Vec3( -// buf.get(12) * scale, -// buf.get(13) * scale, -// buf.get(14) * scale); -// -// scissorBounds.x *= scale; -// scissorBounds.y *= scale; -// scissorBounds.width *= scale; -// scissorBounds.height *= scale; -// final int scissorX = Math.round(Math.round(translation.x + scissorBounds.x)); -// final int scissorY = Math.round(Math.round(Minecraft.getInstance().getWindow().getHeight() - scissorBounds.y - scissorBounds.height - translation.y)); -// final int scissorW = Math.round(scissorBounds.width); -// final int scissorH = Math.round(scissorBounds.height); -// RenderSystem.enableScissor(scissorX, scissorY, scissorW, scissorH); -// -// mx.pushPose(); -// -// mx.translate( -// 27 + (35), -// scissorBounds.y + (35), -// 100); -// -// Vec3 dimsVec = new Vec3(dims.getXsize(), dims.getYsize(), dims.getZsize()); -// float recipeAvgDim = (float) dimsVec.length(); -// float previewScale = (float) ((3 + Math.exp(3 - (recipeAvgDim / 5))) / explodeMulti); -// mx.scale(previewScale, -previewScale, previewScale); -// -// drawActualRecipe(recipe, mx, dims, buffers); -// -// mx.popPose(); -// -// buffers.endBatch(); -// -// RenderSystem.disableScissor(); -// } catch (Exception ex) { -// CompactCrafting.LOGGER.warn(ex); -// } -// } -// -// private void drawActualRecipe(MiniaturizationRecipe recipe, PoseStack mx, AABB dims, MultiBufferSource.BufferSource buffers) { -// double gameTime = Minecraft.getInstance().level.getGameTime(); -// double test = Math.toDegrees(gameTime) / 15; -// mx.mulPose(new Quaternion(35f, -// (float) -test, -// 0, -// true)); -// -// double ySize = recipe.getDimensions().getYsize(); -// -// // Variable explode based on mouse position (clamped) -// // double explodeMulti = MathHelper.clamp(mouseX, 0, this.background.getWidth())/this.background.getWidth()*2+1; -// -// int[] renderLayers; -// if (!singleLayer) { -// renderLayers = IntStream.range(0, (int) ySize).toArray(); -// } else { -// renderLayers = new int[]{singleLayerOffset}; -// } -// -// mx.translate( -// -(dims.getXsize() / 2) * explodeMulti - 0.5, -// -(dims.getYsize() / 2) * explodeMulti - 0.5, -// -(dims.getZsize() / 2) * explodeMulti - 0.5 -// ); -// -// for (int y : renderLayers) { -// recipe.getLayer(y).ifPresent(l -> renderRecipeLayer(recipe, mx, buffers, l, y)); -// } -// } -// -// private void renderPreviewControls(PoseStack mx, AABB dims) { -// mx.pushPose(); -// mx.translate(0, 0, 10); -// -// ResourceLocation sprites = new ResourceLocation(CompactCrafting.MOD_ID, "textures/gui/jei-sprites.png"); -// -// if (exploded) { -// drawScaledTexture(mx, sprites, explodeToggle, 20, 0, 20, 20, 120, 20); -// } else { -// drawScaledTexture(mx, sprites, explodeToggle, 0, 0, 20, 20, 120, 20); -// } -// -// // Layer change buttons -// if (singleLayer) { -// drawScaledTexture(mx, sprites, layerSwap, 60, 0, 20, 20, 120, 20); -// } else { -// drawScaledTexture(mx, sprites, layerSwap, 40, 0, 20, 20, 120, 20); -// } -// -// if (singleLayer) { -// if (singleLayerOffset < dims.getYsize() - 1) -// drawScaledTexture(mx, sprites, layerUp, 80, 0, 20, 20, 120, 20); -// -// if (singleLayerOffset > 0) { -// drawScaledTexture(mx, sprites, layerDown, 100, 0, 20, 20, 120, 20); -// } -// } -// -// // drawScaledTexture(mx, sprites, bindPlate, 120, 0, 20, 20, 140, 20); -// -// mx.popPose(); -// } -// -// private void renderRecipeLayer(MiniaturizationRecipe recipe, PoseStack mx, MultiBufferSource.BufferSource buffers, IRecipeLayer l, int layerY) { -// // Begin layer -// mx.pushPose(); -// -// AABB layerBounds = BlockSpaceUtil.getLayerBounds(recipe.getDimensions(), layerY); -// BlockPos.betweenClosedStream(layerBounds).forEach(filledPos -> { -// mx.pushPose(); -// -// mx.translate( -// ((filledPos.getX() + 0.5) * explodeMulti), -// ((layerY + 0.5) * explodeMulti), -// ((filledPos.getZ() + 0.5) * explodeMulti) -// ); -// -// BlockPos zeroedPos = filledPos.below(layerY); -// Optional componentForPosition = l.getComponentForPosition(zeroedPos); -// componentForPosition -// .flatMap(recipe.getComponents()::getBlock) -// .ifPresent(comp -> renderComponent(mx, buffers, comp, filledPos)); -// -// mx.popPose(); -// }); -// -// // Done with layer -// mx.popPose(); -// } -// -// private void renderComponent(PoseStack mx, MultiBufferSource.BufferSource buffers, IRecipeBlockComponent state, BlockPos filledPos) { -// // TODO - Render switching at fixed interval -// if (state.didErrorRendering()) -// return; -// -// BlockState state1 = state.getRenderState(); -// -// ModelData data = ModelData.EMPTY; -// if (previewLevel != null && state1.hasBlockEntity()) { -// // create fake world instance -// // get tile entity - extend EmptyBlockReader with impl -// BlockEntity be = previewLevel.getBlockEntity(filledPos); -// if (be != null) -// data = be.getModelData(); -// } -// -// try { -// // TODO: Revisit render types -// blocks.renderSingleBlock(state1, -// mx, -// buffers, -// LightTexture.FULL_SKY, -// OverlayTexture.NO_OVERLAY, -// data, null); -// } catch (Exception e) { -// state.markRenderingErrored(); -// -// CompactCrafting.LOGGER.warn("Error rendering block in preview: {}", state1); -// CompactCrafting.LOGGER.error("Stack Trace", e); -// } -// } -//} \ No newline at end of file +package dev.compactmods.crafting.compat.jei; + +import java.nio.FloatBuffer; +import java.util.*; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.stream.IntStream; + +import com.mojang.blaze3d.platform.InputConstants; +import com.mojang.blaze3d.platform.Window; +import com.mojang.blaze3d.systems.RenderSystem; +import com.mojang.blaze3d.vertex.PoseStack; +import dev.compactmods.crafting.CompactCrafting; +import dev.compactmods.crafting.api.components.IRecipeBlockComponent; +import dev.compactmods.crafting.api.recipe.layers.IRecipeLayer; +import dev.compactmods.crafting.client.ui.ScreenArea; +import dev.compactmods.crafting.core.CCBlocks; +import dev.compactmods.crafting.fakeworld.RenderingWorld; +import dev.compactmods.crafting.recipes.MiniaturizationRecipe; +import dev.compactmods.crafting.recipes.components.BlockComponent; +import dev.compactmods.crafting.util.BlockSpaceUtil; +import mezz.jei.api.constants.VanillaTypes; +import mezz.jei.api.gui.builder.IRecipeLayoutBuilder; +import mezz.jei.api.gui.builder.IRecipeSlotBuilder; +import mezz.jei.api.gui.builder.ITooltipBuilder; +import mezz.jei.api.gui.drawable.IDrawable; +import mezz.jei.api.gui.drawable.IDrawableStatic; +import mezz.jei.api.gui.ingredient.IRecipeSlotsView; +import mezz.jei.api.gui.widgets.IRecipeExtrasBuilder; +import mezz.jei.api.helpers.IGuiHelper; +import mezz.jei.api.recipe.IFocusGroup; +import mezz.jei.api.recipe.RecipeIngredientRole; +import mezz.jei.api.recipe.RecipeType; +import mezz.jei.api.recipe.category.IRecipeCategory; +import net.minecraft.ChatFormatting; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.client.renderer.GameRenderer; +import net.minecraft.client.renderer.LightTexture; +import net.minecraft.client.renderer.MultiBufferSource; +import net.minecraft.client.renderer.block.BlockRenderDispatcher; +import net.minecraft.client.renderer.texture.OverlayTexture; +import net.minecraft.client.resources.sounds.SimpleSoundInstance; +import net.minecraft.client.sounds.SoundManager; +import net.minecraft.core.BlockPos; +import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.MutableComponent; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.sounds.SoundEvents; +import net.minecraft.world.item.Item; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.Items; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.AABB; +import net.minecraft.world.phys.Vec3; +import org.lwjgl.BufferUtils; +import org.joml.Matrix4f; +import org.joml.Quaternionf; +import net.neoforged.neoforge.client.model.data.ModelData; + +public class JeiMiniaturizationCraftingCategory implements IRecipeCategory { + + public static final ResourceLocation UID = ResourceLocation.fromNamespaceAndPath(CompactCrafting.MOD_ID, "miniaturization"); + public static final RecipeType RECIPE_TYPE = new RecipeType<>(UID, MiniaturizationRecipe.class); + + private final IDrawable icon; + private final BlockRenderDispatcher blocks; + private RenderingWorld previewLevel; + + private IGuiHelper guiHelper; + private final IDrawableStatic background; + private final IDrawableStatic slotDrawable; + private final IDrawableStatic arrowOutputs; + + private boolean singleLayer = false; + private int singleLayerOffset = 0; + private boolean debugMode = false; + + private ScreenArea explodeToggle = new ScreenArea(30, 75, 10, 10); + private ScreenArea layerUp = new ScreenArea(55, 75, 10, 10); + private ScreenArea layerSwap = new ScreenArea(70, 75, 10, 10); + private ScreenArea layerDown = new ScreenArea(85, 75, 10, 10); + + /** + * Whether the preview is exploded (expanded) or not. + */ + private boolean exploded = false; + + /** + * Explode multiplier; specifies how far apart blocks are rendered. + */ + private double explodeMulti = 1.0d; + + private final MutableComponent MATERIAL_COMPONENT = Component.translatable(CompactCrafting.MOD_ID + ".jei.miniaturization.component") + .withStyle(ChatFormatting.GRAY) + .withStyle(ChatFormatting.ITALIC); + + private final MutableComponent CATALYST = Component.translatable(CompactCrafting.MOD_ID + ".jei.miniaturization.catalyst") + .withStyle(ChatFormatting.YELLOW) + .withStyle(ChatFormatting.ITALIC); + + public JeiMiniaturizationCraftingCategory(IGuiHelper guiHelper) { + int width = (9 * 18) + 10; + int height = 60 + (10 + (18 * 3) + 5); + + this.guiHelper = guiHelper; + this.background = guiHelper.createBlankDrawable(width, height); + this.slotDrawable = guiHelper.getSlotDrawable(); + this.icon = guiHelper.createDrawableIngredient(VanillaTypes.ITEM_STACK, new ItemStack(CCBlocks.FIELD_PROJECTOR_BLOCK.get())); + this.arrowOutputs = guiHelper.createDrawable(ResourceLocation.fromNamespaceAndPath(CompactCrafting.MOD_ID, "textures/gui/jei-arrow-outputs.png"), 0, 0, 24, 19); + + this.blocks = Minecraft.getInstance().getBlockRenderer(); + this.previewLevel = null; + } + + @Override + public RecipeType getRecipeType() { + return RECIPE_TYPE; + } + + //region JEI implementation requirements + @Override + public Component getTitle() { + return Component.translatable(CompactCrafting.MOD_ID + ".jei.miniaturization.title"); + } + + @Override + public IDrawable getBackground() { + return background; + } + + @Override + public IDrawable getIcon() { + return this.icon; + } + //endregion + + + @Override + public void setRecipe(IRecipeLayoutBuilder layout, MiniaturizationRecipe recipe, IFocusGroup focuses) { + previewLevel = new RenderingWorld(recipe); + + singleLayer = false; + singleLayerOffset = 0; + + try { + addMaterialSlots(recipe, layout); + addCatalystSlots(recipe, layout); + + int fromRightEdge = this.background.getWidth() - (18 * 2) - 5; + addOutputSlots(recipe, layout, fromRightEdge); + } catch (Exception ex) { + CompactCrafting.LOGGER.error("Error displaying recipe", ex); + } + } + + private IRecipeSlotBuilder addCatalystSlots(MiniaturizationRecipe recipe, IRecipeLayoutBuilder layout) { + final var catalystSlot = layout.addSlot(RecipeIngredientRole.CATALYST, 1, 1) + .setBackground(slotDrawable, -1, -1); + + List catalystItems = recipe.catalystItems(); + if (!catalystItems.isEmpty()) { + catalystSlot.addItemStacks(catalystItems).addTooltipCallback((slots, c) -> c.add(CATALYST)); + } + + return catalystSlot; + } + + + private void addMaterialSlots(MiniaturizationRecipe recipe, IRecipeLayoutBuilder layout) { + AtomicInteger inputOffset = new AtomicInteger(); + + final int GUTTER_X = 5; + final int OFFSET_Y = 64; + + recipe.getComponentTotals() + .entrySet() + .stream() + .filter(comp -> comp.getValue() > 0) + .sorted(Map.Entry.comparingByValue(Comparator.reverseOrder())) + .forEach((comp) -> { + String component = comp.getKey(); + int required = comp.getValue(); + int finalInputOffset = inputOffset.get(); + + IRecipeBlockComponent bs = recipe.getComponents().getBlock(component).get(); + if (bs instanceof BlockComponent bsc) { + Item bi = bsc.getBlock().asItem(); + + int slotX = GUTTER_X + (finalInputOffset % 9) * 18; + int slotY = (OFFSET_Y + 24) + ((finalInputOffset / 9) * 18); + + final var slot = layout.addSlot(RecipeIngredientRole.INPUT, slotX, slotY) + .setBackground(slotDrawable, -1, -1); + + if (bi != Items.AIR) { + slot.addItemStack(new ItemStack(bi, required)); + slot.addTooltipCallback((slots, c) -> c.add(MATERIAL_COMPONENT)); + inputOffset.getAndIncrement(); + } + } + }); + + for (int i = inputOffset.get(); i < 18; i++) { + int slotX = GUTTER_X + (i % 9) * 18; + int slotY = (OFFSET_Y + 24) + ((i / 9) * 18); + + layout.addSlot(RecipeIngredientRole.INPUT, slotX, slotY).setBackground(slotDrawable, -1, -1); + } + } + + private void addOutputSlots(MiniaturizationRecipe recipe, IRecipeLayoutBuilder layout, int GUTTER_X) { + final var out = recipe.getOutputs(); + for (int outputNum = 0; outputNum < 6; outputNum++) { + int x = (18 * (outputNum % 2)) + GUTTER_X + 1; + int y = (18 * (outputNum / 2)) + 8 + 1; + + final var slot = layout.addSlot(RecipeIngredientRole.OUTPUT, x, y) + .setBackground(slotDrawable, -1, -1); + + if (outputNum < out.length) + slot.addItemStack(out[outputNum]); + } + } + //endregion + + + @Override + public void getTooltip(ITooltipBuilder tooltip, MiniaturizationRecipe recipe, IRecipeSlotsView slots, double mouseX, double mouseY) { + if (explodeToggle.contains((int)mouseX, (int)mouseY)) { + if (!exploded) tooltip.add(Component.translatable("compactcrafting.jei.toggle_exploded_view")); + else tooltip.add(Component.translatable("compactcrafting.jei.toggle_condensed_view")); + } + + if (layerSwap.contains((int)mouseX, (int)mouseY)) { + if (singleLayer) tooltip.add(Component.translatable("compactcrafting.jei.all_layers_mode")); + else tooltip.add(Component.translatable("compactcrafting.jei.single_layer_mode")); + } + + if (layerUp.contains((int)mouseX, (int)mouseY) && singleLayer) { + if (singleLayerOffset < recipe.getDimensions().getYsize() - 1) + tooltip.add(Component.translatable("compactcrafting.jei.layer_up")); + } + + if (layerDown.contains((int)mouseX, (int)mouseY) && singleLayer) { + if (singleLayerOffset > 0) + tooltip.add(Component.translatable("compactcrafting.jei.layer_down")); + } + } + + @Override + public void createRecipeExtras(IRecipeExtrasBuilder builder, MiniaturizationRecipe recipe, IFocusGroup focuses) { + // Input handling moved to new system - will be implemented separately if needed + } + + @Override + public boolean handleInput(MiniaturizationRecipe recipe, double mouseX, double mouseY, InputConstants.Key input) { + if (input.getType() == InputConstants.Type.MOUSE && input.getValue() == 0) { + SoundManager handler = Minecraft.getInstance().getSoundManager(); + + if (explodeToggle.contains((int)mouseX, (int)mouseY)) { + explodeMulti = exploded ? 1.0d : 1.6d; + exploded = !exploded; + handler.play(SimpleSoundInstance.forUI(SoundEvents.UI_BUTTON_CLICK, 1.0F)); + return true; + } + + if (layerSwap.contains((int)mouseX, (int)mouseY)) { + singleLayer = !singleLayer; + handler.play(SimpleSoundInstance.forUI(SoundEvents.UI_BUTTON_CLICK, 1.0F)); + return true; + } + + if (layerUp.contains((int)mouseX, (int)mouseY) && singleLayer) { + if (singleLayerOffset < recipe.getDimensions().getYsize() - 1) { + handler.play(SimpleSoundInstance.forUI(SoundEvents.UI_BUTTON_CLICK, 1.0F)); + singleLayerOffset++; + } + return true; + } + + if (layerDown.contains((int)mouseX, (int)mouseY) && singleLayer) { + if (singleLayerOffset > 0) { + handler.play(SimpleSoundInstance.forUI(SoundEvents.UI_BUTTON_CLICK, 1.0F)); + singleLayerOffset--; + } + + return true; + } + } + + return false; + } + + //region Rendering help + private void drawScaledTexture( + GuiGraphics guiGraphics, + ResourceLocation texture, + ScreenArea area, + float u, float v, + int uWidth, int vHeight, + int textureWidth, int textureHeight) { + + guiGraphics.blit(texture, area.x, area.y, area.width, area.height, u, v, uWidth, vHeight, textureWidth, textureHeight); + } + + //endregion + + @Override + public void draw(MiniaturizationRecipe recipe, IRecipeSlotsView slots, GuiGraphics guiGraphics, double mouseX, double mouseY) { + PoseStack pose = guiGraphics.pose(); + AABB dims = recipe.getDimensions(); + + Window mainWindow = Minecraft.getInstance().getWindow(); + + drawScaledTexture(guiGraphics, + ResourceLocation.fromNamespaceAndPath(CompactCrafting.MOD_ID, "textures/gui/jei-arrow-field.png"), + new ScreenArea(7, 20, 17, 22), + 0, 0, 17, 22, 17, 22); + + drawScaledTexture(guiGraphics, + ResourceLocation.fromNamespaceAndPath(CompactCrafting.MOD_ID, "textures/gui/jei-arrow-outputs.png"), + new ScreenArea(100, 25, 24, 19), + 0, 0, 24, 19, 24, 19); + + int scissorX = 27; + int scissorY = 0; + + double guiScaleFactor = mainWindow.getGuiScale(); + ScreenArea scissorBounds = new ScreenArea( + scissorX, scissorY, + 70, + 70 + ); + + renderPreviewControls(guiGraphics, dims); + + if (previewLevel != null) renderRecipe(recipe, guiGraphics, dims, guiScaleFactor, scissorBounds); + } + + private void renderRecipe(MiniaturizationRecipe recipe, GuiGraphics guiGraphics, AABB dims, double guiScaleFactor, ScreenArea scissorBounds) { + PoseStack mx = guiGraphics.pose(); + try { + guiGraphics.fill( + scissorBounds.x, scissorBounds.y, + scissorBounds.x + scissorBounds.width, + scissorBounds.height, + 0xFF404040 + ); + + MultiBufferSource.BufferSource buffers = Minecraft.getInstance().renderBuffers().bufferSource(); + + final double scale = Minecraft.getInstance().getWindow().getGuiScale(); + final Matrix4f matrix = mx.last().pose(); + final FloatBuffer buf = BufferUtils.createFloatBuffer(16); + matrix.get(buf); + + // { x, y, z } + Vec3 translation = new Vec3( + buf.get(12) * scale, + buf.get(13) * scale, + buf.get(14) * scale); + + int scaledX = (int)(scissorBounds.x * scale); + int scaledY = (int)(scissorBounds.y * scale); + int scaledWidth = (int)(scissorBounds.width * scale); + int scaledHeight = (int)(scissorBounds.height * scale); + final int scissorX = Math.round((float)(translation.x + scaledX)); + final int scissorY = Math.round((float)(Minecraft.getInstance().getWindow().getHeight() - scaledY - scaledHeight - translation.y)); + final int scissorW = Math.round((float)scaledWidth); + final int scissorH = Math.round((float)scaledHeight); + RenderSystem.enableScissor(scissorX, scissorY, scissorW, scissorH); + + mx.pushPose(); + + mx.translate( + 27 + (35), + scissorBounds.y + (35), + 100); + + Vec3 dimsVec = new Vec3(dims.getXsize(), dims.getYsize(), dims.getZsize()); + float recipeAvgDim = (float) dimsVec.length(); + float previewScale = (float) ((3 + Math.exp(3 - (recipeAvgDim / 5))) / explodeMulti); + mx.scale(previewScale, -previewScale, previewScale); + + drawActualRecipe(recipe, mx, dims, buffers); + + mx.popPose(); + + buffers.endBatch(); + + RenderSystem.disableScissor(); + } catch (Exception ex) { + CompactCrafting.LOGGER.warn(ex); + } + } + + private void drawActualRecipe(MiniaturizationRecipe recipe, PoseStack mx, AABB dims, MultiBufferSource.BufferSource buffers) { + double gameTime = Minecraft.getInstance().level.getGameTime(); + double test = Math.toDegrees(gameTime) / 15; + mx.mulPose(new Quaternionf().rotationXYZ( + (float) Math.toRadians(35f), + (float) Math.toRadians(-test), + 0 + )); + + double ySize = recipe.getDimensions().getYsize(); + + // Variable explode based on mouse position (clamped) + // double explodeMulti = MathHelper.clamp(mouseX, 0, this.background.getWidth())/this.background.getWidth()*2+1; + + int[] renderLayers; + if (!singleLayer) { + renderLayers = IntStream.range(0, (int) ySize).toArray(); + } else { + renderLayers = new int[]{singleLayerOffset}; + } + + mx.translate( + -(dims.getXsize() / 2) * explodeMulti - 0.5, + -(dims.getYsize() / 2) * explodeMulti - 0.5, + -(dims.getZsize() / 2) * explodeMulti - 0.5 + ); + + for (int y : renderLayers) { + recipe.getLayer(y).ifPresent(l -> renderRecipeLayer(recipe, mx, buffers, l, y)); + } + } + + private void renderPreviewControls(GuiGraphics guiGraphics, AABB dims) { + PoseStack mx = guiGraphics.pose(); + mx.pushPose(); + mx.translate(0, 0, 10); + + ResourceLocation sprites = ResourceLocation.fromNamespaceAndPath(CompactCrafting.MOD_ID, "textures/gui/jei-sprites.png"); + + if (exploded) { + drawScaledTexture(guiGraphics, sprites, explodeToggle, 20, 0, 20, 20, 120, 20); + } else { + drawScaledTexture(guiGraphics, sprites, explodeToggle, 0, 0, 20, 20, 120, 20); + } + + if (singleLayer) { + drawScaledTexture(guiGraphics, sprites, layerSwap, 60, 0, 20, 20, 120, 20); + } else { + drawScaledTexture(guiGraphics, sprites, layerSwap, 40, 0, 20, 20, 120, 20); + } + + if (singleLayer) { + if (singleLayerOffset < dims.getYsize() - 1) + drawScaledTexture(guiGraphics, sprites, layerUp, 80, 0, 20, 20, 120, 20); + + if (singleLayerOffset > 0) { + drawScaledTexture(guiGraphics, sprites, layerDown, 100, 0, 20, 20, 120, 20); + } + } + + mx.popPose(); + } + + private void renderRecipeLayer(MiniaturizationRecipe recipe, PoseStack mx, MultiBufferSource.BufferSource buffers, IRecipeLayer l, int layerY) { + // Begin layer + mx.pushPose(); + + AABB layerBounds = BlockSpaceUtil.getLayerBounds(recipe.getDimensions(), layerY); + BlockPos.betweenClosedStream(layerBounds).forEach(filledPos -> { + mx.pushPose(); + + mx.translate( + ((filledPos.getX() + 0.5) * explodeMulti), + ((layerY + 0.5) * explodeMulti), + ((filledPos.getZ() + 0.5) * explodeMulti) + ); + + BlockPos zeroedPos = filledPos.below(layerY); + Optional componentForPosition = l.getComponentForPosition(zeroedPos); + componentForPosition + .flatMap(recipe.getComponents()::getBlock) + .ifPresent(comp -> renderComponent(mx, buffers, comp, filledPos)); + + mx.popPose(); + }); + + // Done with layer + mx.popPose(); + } + + private void renderComponent(PoseStack mx, MultiBufferSource.BufferSource buffers, IRecipeBlockComponent state, BlockPos filledPos) { + // TODO - Render switching at fixed interval + if (state.didErrorRendering()) + return; + + BlockState state1 = state.getRenderState(); + + ModelData data = ModelData.EMPTY; + if (previewLevel != null && state1.hasBlockEntity()) { + // create fake world instance + // get tile entity - extend EmptyBlockReader with impl + BlockEntity be = previewLevel.getBlockEntity(filledPos); + if (be != null) + data = be.getModelData(); + } + + try { + // TODO: Revisit render types + blocks.renderSingleBlock(state1, + mx, + buffers, + LightTexture.FULL_SKY, + OverlayTexture.NO_OVERLAY, + data, null); + } catch (Exception e) { + state.markRenderingErrored(); + + CompactCrafting.LOGGER.warn("Error rendering block in preview: {}", state1); + CompactCrafting.LOGGER.error("Stack Trace", e); + } + } +} \ No newline at end of file diff --git a/neoforge-main/src/main/java/dev/compactmods/crafting/compat/jei/JeiMiniaturizationPlugin.java b/neoforge-main/src/main/java/dev/compactmods/crafting/compat/jei/JeiMiniaturizationPlugin.java index acbe8b5..0b46a01 100644 --- a/neoforge-main/src/main/java/dev/compactmods/crafting/compat/jei/JeiMiniaturizationPlugin.java +++ b/neoforge-main/src/main/java/dev/compactmods/crafting/compat/jei/JeiMiniaturizationPlugin.java @@ -1,51 +1,52 @@ -//package dev.compactmods.crafting.compat.jei; -// -//import dev.compactmods.crafting.CompactCrafting; -//import dev.compactmods.crafting.core.CCItems; -//import dev.compactmods.crafting.core.CCMiniaturizationRecipes; -//import mezz.jei.api.IModPlugin; -//import mezz.jei.api.JeiPlugin; -//import mezz.jei.api.registration.IGuiHandlerRegistration; -//import mezz.jei.api.registration.IRecipeCatalystRegistration; -//import mezz.jei.api.registration.IRecipeCategoryRegistration; -//import mezz.jei.api.registration.IRecipeRegistration; -//import net.minecraft.client.Minecraft; -//import net.minecraft.client.multiplayer.ClientLevel; -//import net.minecraft.resources.ResourceLocation; -//import net.minecraft.world.item.ItemStack; -//import net.minecraft.world.item.crafting.RecipeManager; -// -//@JeiPlugin -//public class JeiMiniaturizationPlugin implements IModPlugin { -// @Override -// public ResourceLocation getPluginUid() { -// return new ResourceLocation(CompactCrafting.MOD_ID, "miniaturization_crafting"); -// } -// -// @Override -// public void registerCategories(IRecipeCategoryRegistration registration) { -// registration.addRecipeCategories(new JeiMiniaturizationCraftingCategory(registration.getJeiHelpers().getGuiHelper())); -// } -// -// @Override -// public void registerGuiHandlers(IGuiHandlerRegistration registration) { -// } -// -// @Override -// public void registerRecipeCatalysts(IRecipeCatalystRegistration registration) { -// registration.addRecipeCatalyst( -// new ItemStack(CCItems.FIELD_PROJECTOR_ITEM.get(), 4), -// JeiMiniaturizationCraftingCategory.RECIPE_TYPE); -// -// } -// -// @Override -// public void registerRecipes(IRecipeRegistration registration) { -// ClientLevel w = Minecraft.getInstance().level; -// RecipeManager rm = w == null ? null : w.getRecipeManager(); -// if(rm != null) { -// final var miniRecipes = rm.getAllRecipesFor(CCMiniaturizationRecipes.MINIATURIZATION_RECIPE.get()); -// registration.addRecipes(JeiMiniaturizationCraftingCategory.RECIPE_TYPE, miniRecipes); -// } -// } -//} +package dev.compactmods.crafting.compat.jei; + +import dev.compactmods.crafting.CompactCrafting; +import dev.compactmods.crafting.core.CCItems; +import dev.compactmods.crafting.core.CCMiniaturizationRecipes; +import mezz.jei.api.IModPlugin; +import mezz.jei.api.JeiPlugin; +import mezz.jei.api.registration.IGuiHandlerRegistration; +import mezz.jei.api.registration.IRecipeCatalystRegistration; +import mezz.jei.api.registration.IRecipeCategoryRegistration; +import mezz.jei.api.registration.IRecipeRegistration; +import net.minecraft.client.Minecraft; +import net.minecraft.client.multiplayer.ClientLevel; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.crafting.RecipeManager; + +@JeiPlugin +public class JeiMiniaturizationPlugin implements IModPlugin { + @Override + public ResourceLocation getPluginUid() { + return ResourceLocation.fromNamespaceAndPath(CompactCrafting.MOD_ID, "miniaturization_crafting"); + } + + @Override + public void registerCategories(IRecipeCategoryRegistration registration) { + registration.addRecipeCategories(new JeiMiniaturizationCraftingCategory(registration.getJeiHelpers().getGuiHelper())); + } + + @Override + public void registerGuiHandlers(IGuiHandlerRegistration registration) { + } + + @Override + public void registerRecipeCatalysts(IRecipeCatalystRegistration registration) { + registration.addRecipeCatalyst( + new ItemStack(CCItems.FIELD_PROJECTOR_ITEM.get(), 4), + JeiMiniaturizationCraftingCategory.RECIPE_TYPE); + + } + + @Override + public void registerRecipes(IRecipeRegistration registration) { + ClientLevel w = Minecraft.getInstance().level; + RecipeManager rm = w == null ? null : w.getRecipeManager(); + if(rm != null) { + final var miniRecipeHolders = rm.getAllRecipesFor(CCMiniaturizationRecipes.MINIATURIZATION_RECIPE.get()); + final var miniRecipes = miniRecipeHolders.stream().map(holder -> holder.value()).toList(); + registration.addRecipes(JeiMiniaturizationCraftingCategory.RECIPE_TYPE, miniRecipes); + } + } +} diff --git a/neoforge-main/src/main/java/dev/compactmods/crafting/fakeworld/RecipeChunk.java b/neoforge-main/src/main/java/dev/compactmods/crafting/fakeworld/RecipeChunk.java index ee32a2b..793e16d 100644 --- a/neoforge-main/src/main/java/dev/compactmods/crafting/fakeworld/RecipeChunk.java +++ b/neoforge-main/src/main/java/dev/compactmods/crafting/fakeworld/RecipeChunk.java @@ -1,86 +1,85 @@ -//package dev.compactmods.crafting.client.fakeworld; -// -//import dev.compactmods.crafting.api.components.IRecipeBlockComponent; -//import dev.compactmods.crafting.api.recipe.layers.IRecipeLayer; -//import dev.compactmods.crafting.recipes.MiniaturizationRecipe; -//import dev.compactmods.crafting.util.BlockSpaceUtil; -//import net.minecraft.core.BlockPos; -//import net.minecraft.core.registries.Registries; -//import net.minecraft.world.level.ChunkPos; -//import net.minecraft.world.level.biome.Biomes; -//import net.minecraft.world.level.block.Blocks; -//import net.minecraft.world.level.block.EntityBlock; -//import net.minecraft.world.level.block.entity.BlockEntity; -//import net.minecraft.world.level.block.state.BlockState; -//import net.minecraft.world.level.chunk.EmptyLevelChunk; -//import net.minecraft.world.level.material.FluidState; -// -//import org.jetbrains.annotations.Nullable; -//import java.util.HashMap; -//import java.util.Map; -//import java.util.Optional; -// -//public class RecipeChunk extends EmptyLevelChunk { -// private final MiniaturizationRecipe recipe; -// private final Map blockCache; -// private final Map tileCache; -// -// public RecipeChunk(RenderingWorld renderingLevel, ChunkPos chunkPos, MiniaturizationRecipe recipe) { -// super(renderingLevel, chunkPos, renderingLevel.registryAccess().registryOrThrow(Registries.BIOME).getHolderOrThrow(Biomes.THE_VOID)); -// this.recipe = recipe; -// -// this.blockCache = new HashMap<>(); -// this.tileCache = new HashMap<>(); -// -// BlockSpaceUtil.getBlocksIn(recipe.getDimensions()).forEach(pos -> { -// int y = pos.getY(); -// Optional layer = recipe.getLayer(y); -// -// if(!layer.isPresent()) -// return; -// -// IRecipeLayer rLayer = layer.get(); -// Optional componentForPosition = rLayer.getComponentForPosition(pos.below(y)); -// -// BlockState posState = componentForPosition -// .flatMap(recipe.getComponents()::getBlock) -// .map(IRecipeBlockComponent::getRenderState) -// .orElse(Blocks.VOID_AIR.defaultBlockState()); -// -// blockCache.put(pos, posState); -// -// if(posState.getBlock() instanceof EntityBlock eb) { -// BlockEntity tile = eb.newBlockEntity(pos.immutable(), posState); -// if(tile != null) { -// tile.setLevel(renderingLevel); -// tileCache.put(pos.immutable(), tile); -// } -// } -// }); -// } -// -// @Override -// public BlockState getBlockState(BlockPos pos) { -// if(blockCache.containsKey(pos)) -// return blockCache.get(pos); -// -// return Blocks.VOID_AIR.defaultBlockState(); -// } -// -// @Override -// public FluidState getFluidState(BlockPos pos) { -// return getBlockState(pos).getFluidState(); -// } -// -// @Nullable -// @Override -// public BlockEntity getBlockEntity(BlockPos pos) { -// return tileCache.get(pos); -// } -// -// @Nullable -// @Override -// public BlockEntity getBlockEntity(BlockPos pos, EntityCreationType createType) { -// return tileCache.get(pos); -// } -//} +package dev.compactmods.crafting.fakeworld; + +import javax.annotation.Nullable; +import java.util.HashMap; +import java.util.Map; +import java.util.Optional; +import dev.compactmods.crafting.api.components.IRecipeBlockComponent; +import dev.compactmods.crafting.api.recipe.layers.IRecipeLayer; +import dev.compactmods.crafting.recipes.MiniaturizationRecipe; +import dev.compactmods.crafting.util.BlockSpaceUtil; +import net.minecraft.core.BlockPos; +import net.minecraft.world.level.ChunkPos; +import net.minecraft.world.level.biome.Biomes; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.block.EntityBlock; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.chunk.EmptyLevelChunk; +import net.minecraft.world.level.material.FluidState; +import net.minecraft.core.registries.Registries; + +public class RecipeChunk extends EmptyLevelChunk { + private final MiniaturizationRecipe recipe; + private final Map blockCache; + private final Map tileCache; + + public RecipeChunk(RenderingWorld renderingLevel, ChunkPos chunkPos, MiniaturizationRecipe recipe) { + super(renderingLevel, chunkPos, renderingLevel.registryAccess().registryOrThrow(Registries.BIOME).getHolderOrThrow(Biomes.THE_VOID)); + this.recipe = recipe; + + this.blockCache = new HashMap<>(); + this.tileCache = new HashMap<>(); + + BlockSpaceUtil.getBlocksIn(recipe.getDimensions()).forEach(pos -> { + int y = pos.getY(); + Optional layer = recipe.getLayer(y); + + if(!layer.isPresent()) + return; + + IRecipeLayer rLayer = layer.get(); + Optional componentForPosition = rLayer.getComponentForPosition(pos.below(y)); + + BlockState posState = componentForPosition + .flatMap(recipe.getComponents()::getBlock) + .map(IRecipeBlockComponent::getRenderState) + .orElse(Blocks.VOID_AIR.defaultBlockState()); + + blockCache.put(pos, posState); + + if(posState.getBlock() instanceof EntityBlock eb) { + BlockEntity tile = eb.newBlockEntity(pos.immutable(), posState); + if(tile != null) { + tile.setLevel(renderingLevel); + tileCache.put(pos.immutable(), tile); + } + } + }); + } + + @Override + public BlockState getBlockState(BlockPos pos) { + if(blockCache.containsKey(pos)) + return blockCache.get(pos); + + return Blocks.VOID_AIR.defaultBlockState(); + } + + @Override + public FluidState getFluidState(BlockPos pos) { + return getBlockState(pos).getFluidState(); + } + + @Nullable + @Override + public BlockEntity getBlockEntity(BlockPos pos) { + return tileCache.get(pos); + } + + @Nullable + @Override + public BlockEntity getBlockEntity(BlockPos pos, EntityCreationType createType) { + return tileCache.get(pos); + } +} \ No newline at end of file diff --git a/neoforge-main/src/main/java/dev/compactmods/crafting/fakeworld/RenderingChunkProvider.java b/neoforge-main/src/main/java/dev/compactmods/crafting/fakeworld/RenderingChunkProvider.java index 8170d3f..6661e1c 100644 --- a/neoforge-main/src/main/java/dev/compactmods/crafting/fakeworld/RenderingChunkProvider.java +++ b/neoforge-main/src/main/java/dev/compactmods/crafting/fakeworld/RenderingChunkProvider.java @@ -1,83 +1,83 @@ -//package dev.compactmods.crafting.client.fakeworld; -// -//import java.util.ArrayList; -//import java.util.HashMap; -//import java.util.List; -//import java.util.Map; -//import java.util.function.BooleanSupplier; -//import java.util.stream.Collectors; -//import com.mojang.datafixers.util.Pair; -//import dev.compactmods.crafting.recipes.MiniaturizationRecipe; -//import net.minecraft.core.BlockPos; -//import net.minecraft.core.Holder; -//import net.minecraft.world.level.BlockGetter; -//import net.minecraft.world.level.ChunkPos; -//import net.minecraft.world.level.biome.Biome; -//import net.minecraft.world.level.biome.Biomes; -//import net.minecraft.world.level.chunk.ChunkAccess; -//import net.minecraft.world.level.chunk.ChunkSource; -//import net.minecraft.world.level.chunk.ChunkStatus; -//import net.minecraft.world.level.chunk.EmptyLevelChunk; -//import net.minecraft.world.level.lighting.LevelLightEngine; -//import net.minecraftforge.registries.ForgeRegistries; -//import org.jetbrains.annotations.Nullable; -// -//public class RenderingChunkProvider extends ChunkSource { -// private final Holder VOID; -// private final MiniaturizationRecipe recipe; -// -// private final Map chunks; -// private final RenderingWorld renderingLevel; -// private final LevelLightEngine lightManager; -// -// public RenderingChunkProvider(RenderingWorld renderingLevel, MiniaturizationRecipe recipe) { -// VOID = ForgeRegistries.BIOMES.getHolder(Biomes.THE_VOID).get(); -// -// this.recipe = recipe; -// -// this.renderingLevel = renderingLevel; -// this.lightManager = new LevelLightEngine(this, true, true); -// -// Map> byChunk = new HashMap<>(); -// BlockPos.betweenClosedStream(this.recipe.getDimensions()) -// .map(BlockPos::immutable) -// .forEach(pos -> { -// byChunk.computeIfAbsent(new ChunkPos(pos), $ -> new ArrayList<>()).add(pos); -// }); -// -// chunks = byChunk.keySet().stream() -// .map(chunkPos -> Pair.of(chunkPos, new RecipeChunk(this.renderingLevel, chunkPos, recipe))) -// .collect(Collectors.toMap(Pair::getFirst, Pair::getSecond)); -// } -// -// @Nullable -// @Override -// public ChunkAccess getChunk(int cx, int cz, ChunkStatus status, boolean load) { -// return chunks.computeIfAbsent(new ChunkPos(cx, cz), p -> new EmptyLevelChunk(renderingLevel, p, VOID)); -// } -// -// @Override -// public void tick(BooleanSupplier bool, boolean bool2) { -// -// } -// -// @Override -// public String gatherStats() { -// return "?"; -// } -// -// @Override -// public int getLoadedChunksCount() { -// return chunks.size(); -// } -// -// @Override -// public LevelLightEngine getLightEngine() { -// return lightManager; -// } -// -// @Override -// public BlockGetter getLevel() { -// return renderingLevel; -// } -//} +package dev.compactmods.crafting.fakeworld; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.function.BooleanSupplier; +import java.util.stream.Collectors; +import com.mojang.datafixers.util.Pair; +import dev.compactmods.crafting.recipes.MiniaturizationRecipe; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Holder; +import net.minecraft.world.level.BlockGetter; +import net.minecraft.world.level.ChunkPos; +import net.minecraft.world.level.biome.Biome; +import net.minecraft.world.level.biome.Biomes; +import net.minecraft.world.level.chunk.ChunkAccess; +import net.minecraft.world.level.chunk.ChunkSource; +import net.minecraft.world.level.chunk.EmptyLevelChunk; +import net.minecraft.world.level.chunk.status.ChunkStatus; +import net.minecraft.world.level.lighting.LevelLightEngine; +import net.minecraft.core.registries.Registries; +import org.jetbrains.annotations.Nullable; + +public class RenderingChunkProvider extends ChunkSource { + private final Holder VOID; + private final MiniaturizationRecipe recipe; + + private final Map chunks; + private final RenderingWorld renderingLevel; + private final LevelLightEngine lightManager; + + public RenderingChunkProvider(RenderingWorld renderingLevel, MiniaturizationRecipe recipe) { + VOID = renderingLevel.registryAccess().registryOrThrow(Registries.BIOME).getHolderOrThrow(Biomes.THE_VOID); + + this.recipe = recipe; + + this.renderingLevel = renderingLevel; + this.lightManager = new LevelLightEngine(this, true, true); + + Map> byChunk = new HashMap<>(); + BlockPos.betweenClosedStream(this.recipe.getDimensions()) + .map(BlockPos::immutable) + .forEach(pos -> { + byChunk.computeIfAbsent(new ChunkPos(pos), $ -> new ArrayList<>()).add(pos); + }); + + chunks = byChunk.keySet().stream() + .map(chunkPos -> Pair.of(chunkPos, new RecipeChunk(this.renderingLevel, chunkPos, recipe))) + .collect(Collectors.toMap(Pair::getFirst, Pair::getSecond)); + } + + @Nullable + @Override + public ChunkAccess getChunk(int cx, int cz, ChunkStatus status, boolean load) { + return chunks.computeIfAbsent(new ChunkPos(cx, cz), p -> new EmptyLevelChunk(renderingLevel, p, VOID)); + } + + @Override + public void tick(BooleanSupplier bool, boolean bool2) { + + } + + @Override + public String gatherStats() { + return "?"; + } + + @Override + public int getLoadedChunksCount() { + return chunks.size(); + } + + @Override + public LevelLightEngine getLightEngine() { + return lightManager; + } + + @Override + public BlockGetter getLevel() { + return renderingLevel; + } +} diff --git a/neoforge-main/src/main/java/dev/compactmods/crafting/fakeworld/RenderingSpawnInfo.java b/neoforge-main/src/main/java/dev/compactmods/crafting/fakeworld/RenderingSpawnInfo.java index ded6706..cb97f24 100644 --- a/neoforge-main/src/main/java/dev/compactmods/crafting/fakeworld/RenderingSpawnInfo.java +++ b/neoforge-main/src/main/java/dev/compactmods/crafting/fakeworld/RenderingSpawnInfo.java @@ -1,116 +1,82 @@ -//package dev.compactmods.crafting.client.fakeworld; -// -//import net.minecraft.world.Difficulty; -//import net.minecraft.world.level.GameRules; -//import net.minecraft.world.level.storage.WritableLevelData; -// -//public class RenderingSpawnInfo implements WritableLevelData { -// private static final GameRules RULES = new GameRules(); -// -// private int spawnX; -// private int spawnY; -// private int spawnZ; -// private float spawnAngle; -// -// @Override -// public void setXSpawn(int x) -// { -// spawnX = x; -// } -// -// @Override -// public void setYSpawn(int y) -// { -// spawnY = y; -// } -// -// @Override -// public void setZSpawn(int z) -// { -// spawnZ = z; -// } -// -// @Override -// public void setSpawnAngle(float angle) -// { -// spawnAngle = angle; -// } -// -// @Override -// public int getXSpawn() -// { -// return spawnX; -// } -// -// @Override -// public int getYSpawn() -// { -// return spawnY; -// } -// -// -// @Override -// public int getZSpawn() -// { -// return spawnZ; -// } -// -// @Override -// public float getSpawnAngle() -// { -// return spawnAngle; -// } -// -// @Override -// public long getGameTime() -// { -// return 0; -// } -// -// @Override -// public long getDayTime() -// { -// return 0; -// } -// -// @Override -// public boolean isThundering() -// { -// return false; -// } -// -// @Override -// public boolean isRaining() -// { -// return false; -// } -// -// @Override -// public void setRaining(boolean isRaining) -// { -// -// } -// -// @Override -// public boolean isHardcore() -// { -// return false; -// } -// -// @Override -// public GameRules getGameRules() { -// return RULES; -// } -// -// @Override -// public Difficulty getDifficulty() -// { -// return Difficulty.PEACEFUL; -// } -// -// @Override -// public boolean isDifficultyLocked() -// { -// return false; -// } -//} +package dev.compactmods.crafting.fakeworld; + +import net.minecraft.core.BlockPos; +import net.minecraft.world.Difficulty; +import net.minecraft.world.level.GameRules; +import net.minecraft.world.level.storage.WritableLevelData; + +public class RenderingSpawnInfo implements WritableLevelData { + private static final GameRules RULES = new GameRules(); + + private BlockPos spawnPos = BlockPos.ZERO; + private float spawnAngle; + + @Override + public void setSpawn(BlockPos pos, float angle) { + this.spawnPos = pos; + this.spawnAngle = angle; + } + + @Override + public BlockPos getSpawnPos() { + return spawnPos; + } + + @Override + public float getSpawnAngle() { + return spawnAngle; + } + + @Override + public long getGameTime() + { + return 0; + } + + @Override + public long getDayTime() + { + return 0; + } + + @Override + public boolean isThundering() + { + return false; + } + + @Override + public boolean isRaining() + { + return false; + } + + @Override + public void setRaining(boolean isRaining) + { + + } + + @Override + public boolean isHardcore() + { + return false; + } + + @Override + public GameRules getGameRules() { + return RULES; + } + + @Override + public Difficulty getDifficulty() + { + return Difficulty.PEACEFUL; + } + + @Override + public boolean isDifficultyLocked() + { + return false; + } +} diff --git a/neoforge-main/src/main/java/dev/compactmods/crafting/fakeworld/RenderingWorld.java b/neoforge-main/src/main/java/dev/compactmods/crafting/fakeworld/RenderingWorld.java index dbe0c0c..4b863fb 100644 --- a/neoforge-main/src/main/java/dev/compactmods/crafting/fakeworld/RenderingWorld.java +++ b/neoforge-main/src/main/java/dev/compactmods/crafting/fakeworld/RenderingWorld.java @@ -1,191 +1,213 @@ package dev.compactmods.crafting.fakeworld; -// -//import dev.compactmods.crafting.recipes.MiniaturizationRecipe; -//import net.minecraft.client.Minecraft; -//import net.minecraft.core.*; -//import net.minecraft.core.registries.BuiltInRegistries; -//import net.minecraft.core.registries.Registries; -//import net.minecraft.sounds.SoundEvent; -//import net.minecraft.sounds.SoundSource; -//import net.minecraft.util.profiling.InactiveProfiler; -//import net.minecraft.world.TickRateManager; -//import net.minecraft.world.entity.Entity; -//import net.minecraft.world.entity.player.Player; -//import net.minecraft.world.flag.FeatureFlagSet; -//import net.minecraft.world.item.crafting.RecipeManager; -//import net.minecraft.world.level.Level; -//import net.minecraft.world.level.biome.Biome; -//import net.minecraft.world.level.biome.Biomes; -//import net.minecraft.world.level.block.Block; -//import net.minecraft.world.level.block.state.BlockState; -//import net.minecraft.world.level.chunk.ChunkSource; -//import net.minecraft.world.level.dimension.BuiltinDimensionTypes; -//import net.minecraft.world.level.dimension.DimensionType; -//import net.minecraft.world.level.entity.LevelEntityGetter; -//import net.minecraft.world.level.gameevent.GameEvent; -//import net.minecraft.world.level.material.Fluid; -//import net.minecraft.world.level.saveddata.maps.MapItemSavedData; -//import net.minecraft.world.phys.Vec3; -//import net.minecraft.world.scores.Scoreboard; -//import net.minecraft.world.ticks.BlackholeTickAccess; -//import net.minecraft.world.ticks.LevelTickAccess; -// -//import org.jetbrains.annotations.Nullable; -//import java.util.Collections; -//import java.util.List; -// -//public class RenderingWorld extends Level { -// -// private final MiniaturizationRecipe recipe; -// -// private final Scoreboard scoreboard = new Scoreboard(); -// private final RecipeManager recipeManager = new RecipeManager(); -// private final RenderingChunkProvider chunkProvider; -// -// public RenderingWorld(MiniaturizationRecipe recipe) { -// super(new RenderingSpawnInfo(), Level.OVERWORLD, -// Minecraft.getInstance().level.registryAccess(), -// Minecraft.getInstance().level.registryAccess().registryOrThrow(Registries.DIMENSION_TYPE).getHolderOrThrow(BuiltinDimensionTypes.OVERWORLD), -// () -> InactiveProfiler.INSTANCE, true, false, 0, 1000000); -// -// this.recipe = recipe; -// this.chunkProvider = new RenderingChunkProvider(this, recipe); -// } -// -// @Override -// public void sendBlockUpdated(BlockPos p_184138_1_, BlockState p_184138_2_, BlockState p_184138_3_, int p_184138_4_) { -// -// } -// -// @Override -// public void playSeededSound(@Nullable Player p_262953_, double p_263004_, double p_263398_, double p_263376_, Holder p_263359_, SoundSource p_263020_, float p_263055_, float p_262914_, long p_262991_) { -// -// } -// -// @Override -// public void playSeededSound(@org.jetbrains.annotations.Nullable Player p_220363_, double p_220364_, double p_220365_, double p_220366_, SoundEvent p_220367_, SoundSource p_220368_, float p_220369_, float p_220370_, long p_220371_) { -// -// } -// -// @Override -// public void playSeededSound(@Nullable Player p_220372_, Entity p_220373_, Holder p_263500_, SoundSource p_220375_, float p_220376_, float p_220377_, long p_220378_) { -// -// } -// -// @Override -// public void playSound(@Nullable Player p_184148_1_, double p_184148_2_, double p_184148_4_, double p_184148_6_, SoundEvent p_184148_8_, SoundSource p_184148_9_, float p_184148_10_, float p_184148_11_) { -// -// } -// -// @Override -// public void playSound(@Nullable Player p_217384_1_, Entity p_217384_2_, SoundEvent p_217384_3_, SoundSource p_217384_4_, float p_217384_5_, float p_217384_6_) { -// -// } -// -// @Override -// public String gatherChunkSourceStats() { -// return null; -// } -// -// @Nullable -// @Override -// public Entity getEntity(int p_73045_1_) { -// return null; -// } -// -// @Override -// public TickRateManager tickRateManager() { -// return null; -// } -// -// @Nullable -// @Override -// public MapItemSavedData getMapData(String p_217406_1_) { -// return null; -// } -// -// @Override -// public void setMapData(String p_151533_, MapItemSavedData p_151534_) { -// -// } -// -// @Override -// public int getFreeMapId() { -// return 0; -// } -// -// @Override -// public void destroyBlockProgress(int p_175715_1_, BlockPos p_175715_2_, int p_175715_3_) { -// -// } -// -// @Override -// public Scoreboard getScoreboard() { -// return scoreboard; -// } -// -// @Override -// public RecipeManager getRecipeManager() { -// return recipeManager; -// } -// -// @Override -// protected LevelEntityGetter getEntities() { -// return null; -// } -// -// @Override -// public LevelTickAccess getBlockTicks() { -// return BlackholeTickAccess.emptyLevelList(); -// } -// -// @Override -// public LevelTickAccess getFluidTicks() { -// return BlackholeTickAccess.emptyLevelList(); -// } -// -// @Override -// public ChunkSource getChunkSource() { -// return chunkProvider; -// } -// -// @Override -// public void levelEvent(@Nullable Player p_217378_1_, int p_217378_2_, BlockPos p_217378_3_, int p_217378_4_) { -// -// } -// -// @Override -// public void gameEvent(GameEvent p_220404_, Vec3 p_220405_, GameEvent.Context p_220406_) { -// -// } -// -// @Override -// public void gameEvent(@Nullable Entity p_151549_, GameEvent p_151550_, BlockPos p_151551_) { -// -// } -// -// @Override -// public RegistryAccess registryAccess() { -// return Minecraft.getInstance().level.registryAccess(); -// } -// -// @Override -// public FeatureFlagSet enabledFeatures() { -// return null; -// } -// -// @Override -// public float getShade(Direction p_230487_1_, boolean p_230487_2_) { -// return 0; -// } -// -// @Override -// public List players() { -// return Collections.emptyList(); -// } -// -// @Override -// public Holder getUncachedNoiseBiome(int p_225604_1_, int p_225604_2_, int p_225604_3_) { -// // return registryAccess().registryOrThrow(Registry.BIOME_REGISTRY).getHolderOrThrow(Biomes.THE_VOID); -// } -//} + +import dev.compactmods.crafting.recipes.MiniaturizationRecipe; +import net.minecraft.client.Minecraft; +import net.minecraft.core.*; +import net.minecraft.core.registries.Registries; +import net.minecraft.sounds.SoundEvent; +import net.minecraft.sounds.SoundSource; +import net.minecraft.util.profiling.InactiveProfiler; +import net.minecraft.world.TickRateManager; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.flag.FeatureFlagSet; +import net.minecraft.world.flag.FeatureFlags; +import net.minecraft.world.item.crafting.RecipeManager; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.biome.Biome; +import net.minecraft.world.level.biome.Biomes; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.chunk.ChunkSource; +import net.minecraft.world.level.dimension.BuiltinDimensionTypes; +import net.minecraft.world.level.entity.LevelEntityGetter; +import net.minecraft.world.level.gameevent.GameEvent; +import net.minecraft.world.level.material.Fluid; +import net.minecraft.world.level.saveddata.maps.MapId; +import net.minecraft.world.level.saveddata.maps.MapItemSavedData; +import net.minecraft.world.item.alchemy.PotionBrewing; +import net.minecraft.world.phys.Vec3; +import net.minecraft.world.scores.Scoreboard; +import net.minecraft.world.ticks.BlackholeTickAccess; +import net.minecraft.world.ticks.LevelTickAccess; + +import org.jetbrains.annotations.Nullable; +import java.util.Collections; +import java.util.List; + +public class RenderingWorld extends Level { + + private final MiniaturizationRecipe recipe; + + private final Scoreboard scoreboard = new Scoreboard(); + private final RecipeManager recipeManager; + private final RenderingChunkProvider chunkProvider; + + public RenderingWorld(MiniaturizationRecipe recipe) { + super(new RenderingSpawnInfo(), Level.OVERWORLD, + Minecraft.getInstance().level.registryAccess(), + Minecraft.getInstance().level.registryAccess().registryOrThrow(Registries.DIMENSION_TYPE).getHolderOrThrow(BuiltinDimensionTypes.OVERWORLD), + () -> InactiveProfiler.INSTANCE, true, false, 0, 1000000); + + this.recipe = recipe; + this.recipeManager = new RecipeManager(Minecraft.getInstance().level.registryAccess()); + this.chunkProvider = new RenderingChunkProvider(this, recipe); + } + + @Override + public void sendBlockUpdated(BlockPos p_184138_1_, BlockState p_184138_2_, BlockState p_184138_3_, int p_184138_4_) { + + } + + @Override + public void playSeededSound(@Nullable Player p_262953_, double p_263004_, double p_263398_, double p_263376_, Holder p_263359_, SoundSource p_263020_, float p_263055_, float p_262914_, long p_262991_) { + + } + + @Override + public void playSeededSound(@org.jetbrains.annotations.Nullable Player p_220363_, double p_220364_, double p_220365_, double p_220366_, SoundEvent p_220367_, SoundSource p_220368_, float p_220369_, float p_220370_, long p_220371_) { + + } + + @Override + public void playSeededSound(@Nullable Player p_220372_, Entity p_220373_, Holder p_263500_, SoundSource p_220375_, float p_220376_, float p_220377_, long p_220378_) { + + } + + @Override + public void playSound(@Nullable Player p_184148_1_, double p_184148_2_, double p_184148_4_, double p_184148_6_, SoundEvent p_184148_8_, SoundSource p_184148_9_, float p_184148_10_, float p_184148_11_) { + + } + + @Override + public void playSound(@Nullable Player p_217384_1_, Entity p_217384_2_, SoundEvent p_217384_3_, SoundSource p_217384_4_, float p_217384_5_, float p_217384_6_) { + + } + + @Override + public String gatherChunkSourceStats() { + return null; + } + + @Nullable + @Override + public Entity getEntity(int p_73045_1_) { + return null; + } + + @Override + public TickRateManager tickRateManager() { + return null; + } + + @Nullable + @Override + public MapItemSavedData getMapData(MapId mapId) { + return null; + } + + @Override + public void setMapData(MapId mapId, MapItemSavedData mapData) { + + } + + @Override + public MapId getFreeMapId() { + return new MapId(0); + } + + @Override + public void destroyBlockProgress(int p_175715_1_, BlockPos p_175715_2_, int p_175715_3_) { + + } + + @Override + public Scoreboard getScoreboard() { + return scoreboard; + } + + @Override + public RecipeManager getRecipeManager() { + return recipeManager; + } + + @Override + protected LevelEntityGetter getEntities() { + return null; + } + + @Override + public LevelTickAccess getBlockTicks() { + return BlackholeTickAccess.emptyLevelList(); + } + + @Override + public LevelTickAccess getFluidTicks() { + return BlackholeTickAccess.emptyLevelList(); + } + + @Override + public ChunkSource getChunkSource() { + return chunkProvider; + } + + @Override + public void levelEvent(@Nullable Player p_217378_1_, int p_217378_2_, BlockPos p_217378_3_, int p_217378_4_) { + + } + + @Override + public void gameEvent(Holder holder, Vec3 vec3, GameEvent.Context context) { + + } + + @Override + public RegistryAccess registryAccess() { + return Minecraft.getInstance().level.registryAccess(); + } + + @Override + public FeatureFlagSet enabledFeatures() { + return FeatureFlags.DEFAULT_FLAGS; + } + + @Override + public float getShade(Direction p_230487_1_, boolean p_230487_2_) { + return 0; + } + + @Override + public List players() { + return Collections.emptyList(); + } + + @Override + public Holder getUncachedNoiseBiome(int x, int y, int z) { + return registryAccess().registryOrThrow(net.minecraft.core.registries.Registries.BIOME).getHolderOrThrow(Biomes.THE_VOID); + } + + @Override + public PotionBrewing potionBrewing() { + return PotionBrewing.EMPTY; + } + + @Override + public void setDayTimeFraction(float dayTimeFraction) { + // No-op for rendering world + } + + @Override + public float getDayTimeFraction() { + return 0.0f; + } + + @Override + public float getDayTimePerTick() { + return 0.0f; + } + + @Override + public void setDayTimePerTick(float dayTimePerTick) { + // No-op for rendering world + } +} diff --git a/neoforge-main/src/main/java/dev/compactmods/crafting/field/MiniaturizationField.java b/neoforge-main/src/main/java/dev/compactmods/crafting/field/MiniaturizationField.java index f659623..beb728d 100644 --- a/neoforge-main/src/main/java/dev/compactmods/crafting/field/MiniaturizationField.java +++ b/neoforge-main/src/main/java/dev/compactmods/crafting/field/MiniaturizationField.java @@ -118,6 +118,12 @@ private MiniaturizationField(Level level, CompoundTag nbt) { } }); } + + // if we're in CRAFTING/MATCHED state but have no recipe, reset to NOT_MATCHED + if ((this.craftingState == EnumCraftingState.CRAFTING || this.craftingState == EnumCraftingState.MATCHED) && this.currentRecipe == null) { + this.craftingState = EnumCraftingState.NOT_MATCHED; + this.craftingProgress = 0; + } if (nbt.contains("matchedBlocks")) { StructureTemplate t = new StructureTemplate(); diff --git a/neoforge-main/src/main/java/dev/compactmods/crafting/field/render/CraftingPreviewRenderer.java b/neoforge-main/src/main/java/dev/compactmods/crafting/field/render/CraftingPreviewRenderer.java index 37177eb..fb5629f 100644 --- a/neoforge-main/src/main/java/dev/compactmods/crafting/field/render/CraftingPreviewRenderer.java +++ b/neoforge-main/src/main/java/dev/compactmods/crafting/field/render/CraftingPreviewRenderer.java @@ -5,6 +5,8 @@ import dev.compactmods.crafting.api.components.IRecipeBlockComponent; import dev.compactmods.crafting.api.recipe.IMiniaturizationRecipe; import dev.compactmods.crafting.api.recipe.layers.IRecipeLayer; +import dev.compactmods.crafting.client.render.CCRenderTypes; +import dev.compactmods.crafting.client.render.GhostRenderer; import dev.compactmods.crafting.util.BlockSpaceUtil; import dev.compactmods.crafting.util.MathUtil; import net.minecraft.client.Minecraft; @@ -13,6 +15,9 @@ import net.minecraft.client.renderer.block.BlockRenderDispatcher; import net.minecraft.client.renderer.texture.OverlayTexture; import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.util.FastColor; +import net.minecraft.util.Mth; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.phys.AABB; import net.neoforged.neoforge.client.model.data.ModelData; @@ -25,6 +30,10 @@ public static void render(IMiniaturizationRecipe recipe, double progress, PoseSt if(recipe == null) return; + + if(progress >= recipe.getCraftingTime()) { + return; + } stack.pushPose(); @@ -63,7 +72,7 @@ public static void render(IMiniaturizationRecipe recipe, double progress, PoseSt BlockPos zeroedPos = filledPos.below(finalY); l.getComponentForPosition(zeroedPos) .flatMap(recipe.getComponents()::getBlock) - .ifPresent(comp -> renderSingleBlock(stack, buffers, blockRenderer, comp)); + .ifPresent(comp -> renderSingleBlock(stack, buffers, blockRenderer, comp, craftProgress, recipe.getCraftingTime())); stack.popPose(); }); @@ -80,11 +89,63 @@ public static void render(IMiniaturizationRecipe recipe, double progress, PoseSt stack.popPose(); } - private static void renderSingleBlock(PoseStack stack, MultiBufferSource buffers, BlockRenderDispatcher blockRenderer, IRecipeBlockComponent comp) { - // TODO - Render switching - BlockState state1 = comp.getRenderState(); - - // TODO - Revisit render type - blockRenderer.renderSingleBlock(state1, stack, buffers, LightTexture.FULL_SKY, OverlayTexture.NO_OVERLAY, ModelData.EMPTY, null); + private static void renderSingleBlock(PoseStack stack, MultiBufferSource buffers, BlockRenderDispatcher blockRenderer, IRecipeBlockComponent comp, double progress, double craftingTime) { + BlockState state = comp.getRenderState(); + + double progressPercent = Math.min(progress / craftingTime, 1.0); + + stack.pushPose(); + + stack.translate(0.5, 0.5, 0.5); + + long gameTime = Minecraft.getInstance().level.getGameTime(); + double spinSpeed = 2.0d + (progressPercent * 8.0d); + double blockAngle = (gameTime % 360.0) * spinSpeed; + stack.mulPose(Axis.YP.rotationDegrees((float) blockAngle)); + + double individualScale = 1.0 - (progressPercent * 0.3); + stack.scale((float) individualScale, (float) individualScale, (float) individualScale); + + stack.translate(-0.5, -0.5, -0.5); + + final var mc = Minecraft.getInstance(); + final var colors = mc.getBlockColors(); + final var builder = buffers.getBuffer(CCRenderTypes.PHANTOM); + final var dispatcher = mc.getBlockRenderer(); + final var model = dispatcher.getBlockModel(state); + + if (model != mc.getModelManager().getMissingModel()) { + final float alpha = 0.9f; + for (var dir : Direction.values()) { + model.getQuads(state, dir, mc.level.random, ModelData.EMPTY, null) + .forEach(quad -> { + int color = quad.isTinted() ? colors.getColor(state, mc.level, BlockPos.ZERO, quad.getTintIndex()) : + FastColor.ARGB32.color(255, 255, 255, 255); + + final float red = FastColor.ARGB32.red(color) / 255f; + final float green = FastColor.ARGB32.green(color) / 255f; + final float blue = FastColor.ARGB32.blue(color) / 255f; + final float trueAlpha = Mth.clamp(0.01f, alpha, 0.9f); + + builder.putBulkData(stack.last(), quad, red, green, blue, trueAlpha, + LightTexture.FULL_SKY, OverlayTexture.NO_OVERLAY, false); + }); + } + + model.getQuads(state, null, mc.level.random, ModelData.EMPTY, null) + .forEach(quad -> { + int color = quad.isTinted() ? colors.getColor(state, mc.level, BlockPos.ZERO, quad.getTintIndex()) : + FastColor.ARGB32.color(255, 255, 255, 255); + + final float red = FastColor.ARGB32.red(color) / 255f; + final float green = FastColor.ARGB32.green(color) / 255f; + final float blue = FastColor.ARGB32.blue(color) / 255f; + final float trueAlpha = Mth.clamp(0.01f, alpha, 0.9f); + + builder.putBulkData(stack.last(), quad, red, green, blue, trueAlpha, + LightTexture.FULL_SKY, OverlayTexture.NO_OVERLAY, false); + }); + } + stack.popPose(); } } diff --git a/neoforge-main/src/main/java/dev/compactmods/crafting/projector/FieldProjectorBlock.java b/neoforge-main/src/main/java/dev/compactmods/crafting/projector/FieldProjectorBlock.java index 758f6ea..0122551 100644 --- a/neoforge-main/src/main/java/dev/compactmods/crafting/projector/FieldProjectorBlock.java +++ b/neoforge-main/src/main/java/dev/compactmods/crafting/projector/FieldProjectorBlock.java @@ -221,8 +221,9 @@ public void onPlace(BlockState state, Level level, BlockPos pos, BlockState oldS field.fieldContentsChanged(); // Send activation packet to clients + CompoundTag fieldData = field instanceof MiniaturizationField mf ? mf.serverData() : new CompoundTag(); PacketDistributor.sendToPlayersTrackingChunk(sl, new ChunkPos(field.getCenter()), - new FieldActivatedPacket(field, new CompoundTag())); + new FieldActivatedPacket(field, fieldData)); } } } diff --git a/neoforge-main/src/main/java/dev/compactmods/crafting/recipes/MiniaturizationRecipe.java b/neoforge-main/src/main/java/dev/compactmods/crafting/recipes/MiniaturizationRecipe.java index 72ab712..d5be238 100644 --- a/neoforge-main/src/main/java/dev/compactmods/crafting/recipes/MiniaturizationRecipe.java +++ b/neoforge-main/src/main/java/dev/compactmods/crafting/recipes/MiniaturizationRecipe.java @@ -26,10 +26,12 @@ import dev.compactmods.crafting.util.BlockSpaceUtil; import dev.compactmods.crafting.util.CodecExtensions; import net.minecraft.advancements.critereon.ItemPredicate; +import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.network.RegistryFriendlyByteBuf; import net.minecraft.network.codec.ByteBufCodecs; import net.minecraft.network.codec.StreamCodec; import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.crafting.Recipe; import net.minecraft.world.item.crafting.RecipeHolder; @@ -54,6 +56,7 @@ public record MiniaturizationRecipe( TreeMap layers, ItemPredicate catalystMatcher, + List catalystItems, ItemStack[] outputs, AABB dimensions, int requiredTime, @@ -70,6 +73,22 @@ public record MiniaturizationRecipe( public static final Codec COMPONENT_CODEC = RecipeComponentTypeCodec.INSTANCE.dispatchStable(IRecipeComponent::getType, RecipeComponentType::getCodec); + private record CatalystData(ItemPredicate predicate, List items) {} + + private static final Codec CATALYST_CODEC = RecordCodecBuilder.create(instance -> instance.group( + ResourceLocation.CODEC.listOf().fieldOf("items").forGetter(data -> data.items.stream().map(stack -> net.minecraft.core.registries.BuiltInRegistries.ITEM.getKey(stack.getItem())).toList()) + ).apply(instance, itemIds -> { + List itemStacks = itemIds.stream() + .map(id -> new ItemStack(BuiltInRegistries.ITEM.get(id))) + .toList(); + + ItemPredicate predicate = ItemPredicate.Builder.item() + .of(itemStacks.stream().map(ItemStack::getItem).toArray(Item[]::new)) + .build(); + + return new CatalystData(predicate, itemStacks); + })); + public static final MapCodec CODEC = RecordCodecBuilder.mapCodec(i -> i.group( Codec.INT.optionalFieldOf("craftingTime", 200) .forGetter(MiniaturizationRecipe::getCraftingTime), @@ -86,8 +105,8 @@ public record MiniaturizationRecipe( ItemStack.STRICT_CODEC.listOf().fieldOf("outputs") .forGetter(MiniaturizationRecipe::codecOutputs), - ItemPredicate.CODEC.fieldOf("catalyst") - .forGetter(MiniaturizationRecipe::catalystTest) + CATALYST_CODEC.fieldOf("catalyst") + .forGetter(recipe -> new CatalystData(recipe.catalystTest(), recipe.catalystItems())) ).apply(i, MiniaturizationRecipe::fromCodec)); @@ -97,7 +116,7 @@ public record MiniaturizationRecipe( ByteBufCodecs.fromCodec(LAYER_CODEC).apply(ByteBufCodecs.list()), MiniaturizationRecipe::codecLayerList, MiniaturizationRecipeComponents.STREAM_CODEC, MiniaturizationRecipe::components, ItemStack.LIST_STREAM_CODEC, MiniaturizationRecipe::codecOutputs, - ByteBufCodecs.fromCodecWithRegistries(ItemPredicate.CODEC), MiniaturizationRecipe::catalystMatcher, + ByteBufCodecs.fromCodecWithRegistries(CATALYST_CODEC), recipe -> new CatalystData(recipe.catalystMatcher, recipe.catalystItems), MiniaturizationRecipe::fromCodec ); @@ -109,7 +128,7 @@ public record MiniaturizationRecipe( public static MiniaturizationRecipe fromCodec(int craftTime, int recipeSize, List layers, MiniaturizationRecipeComponents components, List outputs, - ItemPredicate catalyst) { + CatalystData catalystData) { var layers1 = new TreeMap(); // region Layers @@ -173,7 +192,7 @@ public static MiniaturizationRecipe fromCodec(int craftTime, int recipeSize, Lis componentTotals.put(comp, count); }); - var recipe = new MiniaturizationRecipe(layers1, catalyst, outputs.toArray(new ItemStack[0]), + var recipe = new MiniaturizationRecipe(layers1, catalystData.predicate(), catalystData.items(), outputs.toArray(new ItemStack[0]), recipeDims, craftTime, hasFixedFootprint, componentTotals, components); diff --git a/neoforge-main/src/main/resources/data/compactcrafting/recipe/oak_door.json b/neoforge-main/src/main/resources/data/compactcrafting/recipe/oak_door.json index 7092c4d..c6281dc 100644 --- a/neoforge-main/src/main/resources/data/compactcrafting/recipe/oak_door.json +++ b/neoforge-main/src/main/resources/data/compactcrafting/recipe/oak_door.json @@ -13,7 +13,7 @@ } ], "catalyst": { - "id": "minecraft:iron_ingot" + "items": ["minecraft:iron_ingot"] }, "components": { "P": { From 1ae9497a8cd70d0ca527ca4e96aaaf93e0f2390f Mon Sep 17 00:00:00 2001 From: Leclowndu93150 Date: Wed, 24 Sep 2025 01:13:22 +0200 Subject: [PATCH 04/20] fix required blocks calculations --- .../crafting/recipes/MiniaturizationRecipe.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/neoforge-main/src/main/java/dev/compactmods/crafting/recipes/MiniaturizationRecipe.java b/neoforge-main/src/main/java/dev/compactmods/crafting/recipes/MiniaturizationRecipe.java index d5be238..1fa414d 100644 --- a/neoforge-main/src/main/java/dev/compactmods/crafting/recipes/MiniaturizationRecipe.java +++ b/neoforge-main/src/main/java/dev/compactmods/crafting/recipes/MiniaturizationRecipe.java @@ -186,6 +186,12 @@ public static MiniaturizationRecipe fromCodec(int craftTime, int recipeSize, Lis recipeDims = new AABB(Vec3.ZERO, new Vec3(x, height, z)); } + final AABB footprint = BlockSpaceUtil.getLayerBounds(recipeDims, 0); + layers1.values() + .stream() + .filter(l -> l instanceof IDynamicSizedRecipeLayer) + .forEach(dl -> ((IDynamicSizedRecipeLayer) dl).setRecipeDimensions(footprint)); + HashMap componentTotals = new HashMap<>(); components.getAllComponents().keySet().forEach(comp -> { int count = getComponentRequiredCount(comp, components, layers1); @@ -196,7 +202,6 @@ public static MiniaturizationRecipe fromCodec(int craftTime, int recipeSize, Lis recipeDims, craftTime, hasFixedFootprint, componentTotals, components); - recipe.updateFluidLayerDimensions(); return recipe; } From cf2aa44ad0a83aae0fb0103b057f9ee9d6518173 Mon Sep 17 00:00:00 2001 From: Leclowndu93150 Date: Wed, 24 Sep 2025 01:21:18 +0200 Subject: [PATCH 05/20] lighting kinda --- .../compat/jei/JeiMiniaturizationCraftingCategory.java | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/neoforge-main/src/main/java/dev/compactmods/crafting/compat/jei/JeiMiniaturizationCraftingCategory.java b/neoforge-main/src/main/java/dev/compactmods/crafting/compat/jei/JeiMiniaturizationCraftingCategory.java index 01acef2..e8d74b3 100644 --- a/neoforge-main/src/main/java/dev/compactmods/crafting/compat/jei/JeiMiniaturizationCraftingCategory.java +++ b/neoforge-main/src/main/java/dev/compactmods/crafting/compat/jei/JeiMiniaturizationCraftingCategory.java @@ -53,6 +53,7 @@ import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.phys.AABB; import net.minecraft.world.phys.Vec3; +import org.joml.Vector3f; import org.lwjgl.BufferUtils; import org.joml.Matrix4f; import org.joml.Quaternionf; @@ -383,6 +384,13 @@ private void renderRecipe(MiniaturizationRecipe recipe, GuiGraphics guiGraphics, float previewScale = (float) ((3 + Math.exp(3 - (recipeAvgDim / 5))) / explodeMulti); mx.scale(previewScale, -previewScale, previewScale); + Vector3f light0 = new Vector3f(0.2f, 1.0f, -0.7f); + Vector3f light1 = new Vector3f(-0.2f, 1.0f, 0.7f); + light0.normalize(); + light1.normalize(); + + RenderSystem.setShaderLights(light0, light1); + drawActualRecipe(recipe, mx, dims, buffers); mx.popPose(); @@ -506,7 +514,7 @@ private void renderComponent(PoseStack mx, MultiBufferSource.BufferSource buffer blocks.renderSingleBlock(state1, mx, buffers, - LightTexture.FULL_SKY, + 0xF000F0, OverlayTexture.NO_OVERLAY, data, null); } catch (Exception e) { From e23b968179645410be162d812209a86453a3787a Mon Sep 17 00:00:00 2001 From: Leclowndu93150 Date: Wed, 24 Sep 2025 01:23:32 +0200 Subject: [PATCH 06/20] proper lighting actually --- .../jei/JeiMiniaturizationCraftingCategory.java | 9 +-------- .../crafting/fakeworld/RenderingWorld.java | 13 ++++++++++++- 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/neoforge-main/src/main/java/dev/compactmods/crafting/compat/jei/JeiMiniaturizationCraftingCategory.java b/neoforge-main/src/main/java/dev/compactmods/crafting/compat/jei/JeiMiniaturizationCraftingCategory.java index e8d74b3..f6aac60 100644 --- a/neoforge-main/src/main/java/dev/compactmods/crafting/compat/jei/JeiMiniaturizationCraftingCategory.java +++ b/neoforge-main/src/main/java/dev/compactmods/crafting/compat/jei/JeiMiniaturizationCraftingCategory.java @@ -384,13 +384,6 @@ private void renderRecipe(MiniaturizationRecipe recipe, GuiGraphics guiGraphics, float previewScale = (float) ((3 + Math.exp(3 - (recipeAvgDim / 5))) / explodeMulti); mx.scale(previewScale, -previewScale, previewScale); - Vector3f light0 = new Vector3f(0.2f, 1.0f, -0.7f); - Vector3f light1 = new Vector3f(-0.2f, 1.0f, 0.7f); - light0.normalize(); - light1.normalize(); - - RenderSystem.setShaderLights(light0, light1); - drawActualRecipe(recipe, mx, dims, buffers); mx.popPose(); @@ -514,7 +507,7 @@ private void renderComponent(PoseStack mx, MultiBufferSource.BufferSource buffer blocks.renderSingleBlock(state1, mx, buffers, - 0xF000F0, + LightTexture.FULL_BRIGHT, OverlayTexture.NO_OVERLAY, data, null); } catch (Exception e) { diff --git a/neoforge-main/src/main/java/dev/compactmods/crafting/fakeworld/RenderingWorld.java b/neoforge-main/src/main/java/dev/compactmods/crafting/fakeworld/RenderingWorld.java index 4b863fb..2383fa1 100644 --- a/neoforge-main/src/main/java/dev/compactmods/crafting/fakeworld/RenderingWorld.java +++ b/neoforge-main/src/main/java/dev/compactmods/crafting/fakeworld/RenderingWorld.java @@ -14,6 +14,7 @@ import net.minecraft.world.flag.FeatureFlags; import net.minecraft.world.item.crafting.RecipeManager; import net.minecraft.world.level.Level; +import net.minecraft.world.level.LightLayer; import net.minecraft.world.level.biome.Biome; import net.minecraft.world.level.biome.Biomes; import net.minecraft.world.level.block.Block; @@ -173,7 +174,17 @@ public FeatureFlagSet enabledFeatures() { @Override public float getShade(Direction p_230487_1_, boolean p_230487_2_) { - return 0; + return 1.0f; + } + + @Override + public int getBrightness(LightLayer lightType, BlockPos blockPos) { + return 15; + } + + @Override + public int getRawBrightness(BlockPos pos, int maxValue) { + return 15; } @Override From a88bef30103ea2c552d07420876a9024b9ec2db7 Mon Sep 17 00:00:00 2001 From: Leclowndu93150 Date: Wed, 24 Sep 2025 09:27:48 +0200 Subject: [PATCH 07/20] compiles --- gradle/libs.versions.toml | 4 ++-- .../dev/compactmods/crafting/events/WorldEventHandler.java | 1 - 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index af05e61..1d74421 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -7,5 +7,5 @@ module = "io.reactivex.rxjava3:rxjava" version = "3.1.5" [libraries.reactivestreams] -module = "io.reactivex.rxjava3:reactive-streams" -version = "[1.0.4,)" \ No newline at end of file +module = "org.reactivestreams:reactive-streams" +version = "1.0.4" \ No newline at end of file diff --git a/neoforge-main/src/main/java/dev/compactmods/crafting/events/WorldEventHandler.java b/neoforge-main/src/main/java/dev/compactmods/crafting/events/WorldEventHandler.java index f3373a9..5e93d3e 100644 --- a/neoforge-main/src/main/java/dev/compactmods/crafting/events/WorldEventHandler.java +++ b/neoforge-main/src/main/java/dev/compactmods/crafting/events/WorldEventHandler.java @@ -7,7 +7,6 @@ import dev.compactmods.crafting.network.ClientFieldWatchPacket; import dev.compactmods.crafting.network.ClientFieldUnwatchPacket; import dev.compactmods.crafting.network.FieldActivatedPacket; -import dev.compactmods.crafting.network.NetworkHandler; import io.reactivex.rxjava3.subjects.PublishSubject; import io.reactivex.rxjava3.subjects.Subject; import net.minecraft.server.level.ServerLevel; From 0efd367cabd30fa1601047d8694342f6aa3fb358 Mon Sep 17 00:00:00 2001 From: Leclowndu93150 Date: Wed, 24 Sep 2025 12:41:40 +0200 Subject: [PATCH 08/20] rendering works ! --- .../crafting/client/render/CCRenderTypes.java | 3 +++ .../render/field/MiniaturizationFieldRenderer.java | 3 +++ .../field/render/CraftingPreviewRenderer.java | 13 ++++++------- 3 files changed, 12 insertions(+), 7 deletions(-) diff --git a/neoforge-main/src/main/java/dev/compactmods/crafting/client/render/CCRenderTypes.java b/neoforge-main/src/main/java/dev/compactmods/crafting/client/render/CCRenderTypes.java index 36c282b..c26a681 100644 --- a/neoforge-main/src/main/java/dev/compactmods/crafting/client/render/CCRenderTypes.java +++ b/neoforge-main/src/main/java/dev/compactmods/crafting/client/render/CCRenderTypes.java @@ -28,5 +28,8 @@ public class CCRenderTypes { .setLightmapState(RenderStateShard.LIGHTMAP) .setTextureState(RenderStateShard.BLOCK_SHEET_MIPPED) .setTransparencyState(RenderStateShard.TRANSLUCENT_TRANSPARENCY) + .setDepthTestState(RenderStateShard.LEQUAL_DEPTH_TEST) + .setCullState(RenderStateShard.NO_CULL) + .setWriteMaskState(RenderStateShard.COLOR_DEPTH_WRITE) .createCompositeState(true)); } diff --git a/neoforge-main/src/main/java/dev/compactmods/crafting/client/render/field/MiniaturizationFieldRenderer.java b/neoforge-main/src/main/java/dev/compactmods/crafting/client/render/field/MiniaturizationFieldRenderer.java index cb86cc1..ae0975a 100644 --- a/neoforge-main/src/main/java/dev/compactmods/crafting/client/render/field/MiniaturizationFieldRenderer.java +++ b/neoforge-main/src/main/java/dev/compactmods/crafting/client/render/field/MiniaturizationFieldRenderer.java @@ -64,7 +64,10 @@ public static void render(Level level, IMiniaturizationField { @@ -125,10 +126,9 @@ private static void renderSingleBlock(PoseStack stack, MultiBufferSource buffers final float red = FastColor.ARGB32.red(color) / 255f; final float green = FastColor.ARGB32.green(color) / 255f; final float blue = FastColor.ARGB32.blue(color) / 255f; - final float trueAlpha = Mth.clamp(0.01f, alpha, 0.9f); - builder.putBulkData(stack.last(), quad, red, green, blue, trueAlpha, - LightTexture.FULL_SKY, OverlayTexture.NO_OVERLAY, false); + builder.putBulkData(stack.last(), quad, red, green, blue, alpha, + LightTexture.FULL_BRIGHT, OverlayTexture.NO_OVERLAY, false); }); } @@ -140,10 +140,9 @@ private static void renderSingleBlock(PoseStack stack, MultiBufferSource buffers final float red = FastColor.ARGB32.red(color) / 255f; final float green = FastColor.ARGB32.green(color) / 255f; final float blue = FastColor.ARGB32.blue(color) / 255f; - final float trueAlpha = Mth.clamp(0.01f, alpha, 0.9f); - builder.putBulkData(stack.last(), quad, red, green, blue, trueAlpha, - LightTexture.FULL_SKY, OverlayTexture.NO_OVERLAY, false); + builder.putBulkData(stack.last(), quad, red, green, blue, alpha, + LightTexture.FULL_BRIGHT, OverlayTexture.NO_OVERLAY, false); }); } stack.popPose(); From 22b1ff785e3f68fc7d9fb9e0e2a4b32fea98e1e2 Mon Sep 17 00:00:00 2001 From: Leclowndu93150 Date: Wed, 24 Sep 2025 14:37:18 +0200 Subject: [PATCH 09/20] fix all RL references --- .../compat/jei/JeiMiniaturizationCraftingCategory.java | 10 +++++----- .../crafting/compat/jei/JeiMiniaturizationPlugin.java | 2 +- .../theoneprobe/providers/FieldProjectorProvider.java | 4 ++-- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/neoforge-main/src/main/java/dev/compactmods/crafting/compat/jei/JeiMiniaturizationCraftingCategory.java b/neoforge-main/src/main/java/dev/compactmods/crafting/compat/jei/JeiMiniaturizationCraftingCategory.java index f6aac60..5d785e5 100644 --- a/neoforge-main/src/main/java/dev/compactmods/crafting/compat/jei/JeiMiniaturizationCraftingCategory.java +++ b/neoforge-main/src/main/java/dev/compactmods/crafting/compat/jei/JeiMiniaturizationCraftingCategory.java @@ -61,7 +61,7 @@ public class JeiMiniaturizationCraftingCategory implements IRecipeCategory { - public static final ResourceLocation UID = ResourceLocation.fromNamespaceAndPath(CompactCrafting.MOD_ID, "miniaturization"); + public static final ResourceLocation UID = CompactCrafting.modRL("miniaturization"); public static final RecipeType RECIPE_TYPE = new RecipeType<>(UID, MiniaturizationRecipe.class); private final IDrawable icon; @@ -108,7 +108,7 @@ public JeiMiniaturizationCraftingCategory(IGuiHelper guiHelper) { this.background = guiHelper.createBlankDrawable(width, height); this.slotDrawable = guiHelper.getSlotDrawable(); this.icon = guiHelper.createDrawableIngredient(VanillaTypes.ITEM_STACK, new ItemStack(CCBlocks.FIELD_PROJECTOR_BLOCK.get())); - this.arrowOutputs = guiHelper.createDrawable(ResourceLocation.fromNamespaceAndPath(CompactCrafting.MOD_ID, "textures/gui/jei-arrow-outputs.png"), 0, 0, 24, 19); + this.arrowOutputs = guiHelper.createDrawable(CompactCrafting.modRL("textures/gui/jei-arrow-outputs.png"), 0, 0, 24, 19); this.blocks = Minecraft.getInstance().getBlockRenderer(); this.previewLevel = null; @@ -315,12 +315,12 @@ public void draw(MiniaturizationRecipe recipe, IRecipeSlotsView slots, GuiGraphi Window mainWindow = Minecraft.getInstance().getWindow(); drawScaledTexture(guiGraphics, - ResourceLocation.fromNamespaceAndPath(CompactCrafting.MOD_ID, "textures/gui/jei-arrow-field.png"), + CompactCrafting.modRL("textures/gui/jei-arrow-field.png"), new ScreenArea(7, 20, 17, 22), 0, 0, 17, 22, 17, 22); drawScaledTexture(guiGraphics, - ResourceLocation.fromNamespaceAndPath(CompactCrafting.MOD_ID, "textures/gui/jei-arrow-outputs.png"), + CompactCrafting.modRL("textures/gui/jei-arrow-outputs.png"), new ScreenArea(100, 25, 24, 19), 0, 0, 24, 19, 24, 19); @@ -433,7 +433,7 @@ private void renderPreviewControls(GuiGraphics guiGraphics, AABB dims) { mx.pushPose(); mx.translate(0, 0, 10); - ResourceLocation sprites = ResourceLocation.fromNamespaceAndPath(CompactCrafting.MOD_ID, "textures/gui/jei-sprites.png"); + ResourceLocation sprites = CompactCrafting.modRL("textures/gui/jei-sprites.png"); if (exploded) { drawScaledTexture(guiGraphics, sprites, explodeToggle, 20, 0, 20, 20, 120, 20); diff --git a/neoforge-main/src/main/java/dev/compactmods/crafting/compat/jei/JeiMiniaturizationPlugin.java b/neoforge-main/src/main/java/dev/compactmods/crafting/compat/jei/JeiMiniaturizationPlugin.java index 0b46a01..d0aead8 100644 --- a/neoforge-main/src/main/java/dev/compactmods/crafting/compat/jei/JeiMiniaturizationPlugin.java +++ b/neoforge-main/src/main/java/dev/compactmods/crafting/compat/jei/JeiMiniaturizationPlugin.java @@ -19,7 +19,7 @@ public class JeiMiniaturizationPlugin implements IModPlugin { @Override public ResourceLocation getPluginUid() { - return ResourceLocation.fromNamespaceAndPath(CompactCrafting.MOD_ID, "miniaturization_crafting"); + return CompactCrafting.modRL("miniaturization_crafting"); } @Override diff --git a/neoforge-main/src/main/java/dev/compactmods/crafting/compat/theoneprobe/providers/FieldProjectorProvider.java b/neoforge-main/src/main/java/dev/compactmods/crafting/compat/theoneprobe/providers/FieldProjectorProvider.java index b4e0090..53316da 100644 --- a/neoforge-main/src/main/java/dev/compactmods/crafting/compat/theoneprobe/providers/FieldProjectorProvider.java +++ b/neoforge-main/src/main/java/dev/compactmods/crafting/compat/theoneprobe/providers/FieldProjectorProvider.java @@ -26,7 +26,7 @@ public class FieldProjectorProvider implements IProbeInfoProvider { - private static final ResourceLocation ID = ResourceLocation.fromNamespaceAndPath(CompactCrafting.MOD_ID, "field_projector"); + private static final ResourceLocation ID = CompactCrafting.modRL("field_projector"); @Override public ResourceLocation getID() { return ID; @@ -64,7 +64,7 @@ public void addProbeInfo(ProbeMode mode, IProbeInfo info, Player player, Level l group.item(new ItemStack(Items.REDSTONE)); // placeholder group.icon( - ResourceLocation.fromNamespaceAndPath(CompactCrafting.MOD_ID, "textures/gui/jei-arrow-outputs.png"), + CompactCrafting.modRL( "textures/gui/jei-arrow-outputs.png"), 0, 0, 24, 19, info.defaultIconStyle().textureHeight(19) .textureWidth(24) .height(19).width(24)); From b2c12f328cfc1e93d8b4571dedcd41233562d830 Mon Sep 17 00:00:00 2001 From: Leclowndu93150 Date: Wed, 24 Sep 2025 14:49:43 +0200 Subject: [PATCH 10/20] things --- .../crafting/client/render/GhostRenderer.java | 1 - .../crafting/recipes/MiniaturizationRecipe.java | 13 +++++-------- 2 files changed, 5 insertions(+), 9 deletions(-) diff --git a/neoforge-main/src/main/java/dev/compactmods/crafting/client/render/GhostRenderer.java b/neoforge-main/src/main/java/dev/compactmods/crafting/client/render/GhostRenderer.java index 6f5e410..6020854 100644 --- a/neoforge-main/src/main/java/dev/compactmods/crafting/client/render/GhostRenderer.java +++ b/neoforge-main/src/main/java/dev/compactmods/crafting/client/render/GhostRenderer.java @@ -68,7 +68,6 @@ public static void renderTransparentBlock(BlockState state, @Nullable BlockPos p } public static void renderTransparentBlock(BlockState state, @Nullable BlockPos pos, PoseStack matrix, MultiBufferSource buffer, int ticksLeft) { - System.out.println("Rendering ghost block: " + state); final Minecraft mc = Minecraft.getInstance(); final BlockColors colors = mc.getBlockColors(); diff --git a/neoforge-main/src/main/java/dev/compactmods/crafting/recipes/MiniaturizationRecipe.java b/neoforge-main/src/main/java/dev/compactmods/crafting/recipes/MiniaturizationRecipe.java index 1fa414d..aba4309 100644 --- a/neoforge-main/src/main/java/dev/compactmods/crafting/recipes/MiniaturizationRecipe.java +++ b/neoforge-main/src/main/java/dev/compactmods/crafting/recipes/MiniaturizationRecipe.java @@ -126,6 +126,8 @@ private record CatalystData(ItemPredicate predicate, List items) {} RecipeHolder::new ); + + public static MiniaturizationRecipe fromCodec(int craftTime, int recipeSize, List layers, MiniaturizationRecipeComponents components, List outputs, CatalystData catalystData) { @@ -186,11 +188,7 @@ public static MiniaturizationRecipe fromCodec(int craftTime, int recipeSize, Lis recipeDims = new AABB(Vec3.ZERO, new Vec3(x, height, z)); } - final AABB footprint = BlockSpaceUtil.getLayerBounds(recipeDims, 0); - layers1.values() - .stream() - .filter(l -> l instanceof IDynamicSizedRecipeLayer) - .forEach(dl -> ((IDynamicSizedRecipeLayer) dl).setRecipeDimensions(footprint)); + updateFluidLayerDimensions(layers1, recipeDims); HashMap componentTotals = new HashMap<>(); components.getAllComponents().keySet().forEach(comp -> { @@ -205,10 +203,9 @@ public static MiniaturizationRecipe fromCodec(int craftTime, int recipeSize, Lis return recipe; } - private void updateFluidLayerDimensions() { - // Update all the dynamic recipe layers + private static void updateFluidLayerDimensions(TreeMap layers, AABB dimensions) { final AABB footprint = BlockSpaceUtil.getLayerBounds(dimensions, 0); - this.layers.values() + layers.values() .stream() .filter(l -> l instanceof IDynamicSizedRecipeLayer) .forEach(dl -> ((IDynamicSizedRecipeLayer) dl).setRecipeDimensions(footprint)); From 2de45af4f042c600b9e185cf93cc90a2fa3920ff Mon Sep 17 00:00:00 2001 From: Leclowndu93150 Date: Wed, 24 Sep 2025 14:58:44 +0200 Subject: [PATCH 11/20] fix codec like before but making sure JEI can get it --- .../JeiMiniaturizationCraftingCategory.java | 6 ++-- .../recipes/MiniaturizationRecipe.java | 33 ++++++------------- .../data/compactcrafting/recipe/oak_door.json | 30 ----------------- 3 files changed, 13 insertions(+), 56 deletions(-) delete mode 100644 neoforge-main/src/main/resources/data/compactcrafting/recipe/oak_door.json diff --git a/neoforge-main/src/main/java/dev/compactmods/crafting/compat/jei/JeiMiniaturizationCraftingCategory.java b/neoforge-main/src/main/java/dev/compactmods/crafting/compat/jei/JeiMiniaturizationCraftingCategory.java index 5d785e5..ad9c9f8 100644 --- a/neoforge-main/src/main/java/dev/compactmods/crafting/compat/jei/JeiMiniaturizationCraftingCategory.java +++ b/neoforge-main/src/main/java/dev/compactmods/crafting/compat/jei/JeiMiniaturizationCraftingCategory.java @@ -159,9 +159,9 @@ private IRecipeSlotBuilder addCatalystSlots(MiniaturizationRecipe recipe, IRecip final var catalystSlot = layout.addSlot(RecipeIngredientRole.CATALYST, 1, 1) .setBackground(slotDrawable, -1, -1); - List catalystItems = recipe.catalystItems(); - if (!catalystItems.isEmpty()) { - catalystSlot.addItemStacks(catalystItems).addTooltipCallback((slots, c) -> c.add(CATALYST)); + ItemStack catalyst = recipe.catalyst(); + if (!catalyst.isEmpty()) { + catalystSlot.addItemStack(catalyst).addTooltipCallback((slots, c) -> c.add(CATALYST)); } return catalystSlot; diff --git a/neoforge-main/src/main/java/dev/compactmods/crafting/recipes/MiniaturizationRecipe.java b/neoforge-main/src/main/java/dev/compactmods/crafting/recipes/MiniaturizationRecipe.java index aba4309..c6b51e5 100644 --- a/neoforge-main/src/main/java/dev/compactmods/crafting/recipes/MiniaturizationRecipe.java +++ b/neoforge-main/src/main/java/dev/compactmods/crafting/recipes/MiniaturizationRecipe.java @@ -26,12 +26,10 @@ import dev.compactmods.crafting.util.BlockSpaceUtil; import dev.compactmods.crafting.util.CodecExtensions; import net.minecraft.advancements.critereon.ItemPredicate; -import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.network.RegistryFriendlyByteBuf; import net.minecraft.network.codec.ByteBufCodecs; import net.minecraft.network.codec.StreamCodec; import net.minecraft.resources.ResourceLocation; -import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.crafting.Recipe; import net.minecraft.world.item.crafting.RecipeHolder; @@ -56,7 +54,7 @@ public record MiniaturizationRecipe( TreeMap layers, ItemPredicate catalystMatcher, - List catalystItems, + ItemStack catalyst, ItemStack[] outputs, AABB dimensions, int requiredTime, @@ -73,21 +71,6 @@ public record MiniaturizationRecipe( public static final Codec COMPONENT_CODEC = RecipeComponentTypeCodec.INSTANCE.dispatchStable(IRecipeComponent::getType, RecipeComponentType::getCodec); - private record CatalystData(ItemPredicate predicate, List items) {} - - private static final Codec CATALYST_CODEC = RecordCodecBuilder.create(instance -> instance.group( - ResourceLocation.CODEC.listOf().fieldOf("items").forGetter(data -> data.items.stream().map(stack -> net.minecraft.core.registries.BuiltInRegistries.ITEM.getKey(stack.getItem())).toList()) - ).apply(instance, itemIds -> { - List itemStacks = itemIds.stream() - .map(id -> new ItemStack(BuiltInRegistries.ITEM.get(id))) - .toList(); - - ItemPredicate predicate = ItemPredicate.Builder.item() - .of(itemStacks.stream().map(ItemStack::getItem).toArray(Item[]::new)) - .build(); - - return new CatalystData(predicate, itemStacks); - })); public static final MapCodec CODEC = RecordCodecBuilder.mapCodec(i -> i.group( Codec.INT.optionalFieldOf("craftingTime", 200) @@ -105,8 +88,8 @@ private record CatalystData(ItemPredicate predicate, List items) {} ItemStack.STRICT_CODEC.listOf().fieldOf("outputs") .forGetter(MiniaturizationRecipe::codecOutputs), - CATALYST_CODEC.fieldOf("catalyst") - .forGetter(recipe -> new CatalystData(recipe.catalystTest(), recipe.catalystItems())) + ItemStack.STRICT_CODEC.fieldOf("catalyst") + .forGetter(MiniaturizationRecipe::catalyst) ).apply(i, MiniaturizationRecipe::fromCodec)); @@ -116,7 +99,7 @@ private record CatalystData(ItemPredicate predicate, List items) {} ByteBufCodecs.fromCodec(LAYER_CODEC).apply(ByteBufCodecs.list()), MiniaturizationRecipe::codecLayerList, MiniaturizationRecipeComponents.STREAM_CODEC, MiniaturizationRecipe::components, ItemStack.LIST_STREAM_CODEC, MiniaturizationRecipe::codecOutputs, - ByteBufCodecs.fromCodecWithRegistries(CATALYST_CODEC), recipe -> new CatalystData(recipe.catalystMatcher, recipe.catalystItems), + ItemStack.STREAM_CODEC, MiniaturizationRecipe::catalyst, MiniaturizationRecipe::fromCodec ); @@ -130,7 +113,7 @@ private record CatalystData(ItemPredicate predicate, List items) {} public static MiniaturizationRecipe fromCodec(int craftTime, int recipeSize, List layers, MiniaturizationRecipeComponents components, List outputs, - CatalystData catalystData) { + ItemStack catalyst) { var layers1 = new TreeMap(); // region Layers @@ -196,7 +179,11 @@ public static MiniaturizationRecipe fromCodec(int craftTime, int recipeSize, Lis componentTotals.put(comp, count); }); - var recipe = new MiniaturizationRecipe(layers1, catalystData.predicate(), catalystData.items(), outputs.toArray(new ItemStack[0]), + ItemPredicate catalystPredicate = ItemPredicate.Builder.item() + .of(catalyst.getItem()) + .build(); + + var recipe = new MiniaturizationRecipe(layers1, catalystPredicate, catalyst, outputs.toArray(new ItemStack[0]), recipeDims, craftTime, hasFixedFootprint, componentTotals, components); diff --git a/neoforge-main/src/main/resources/data/compactcrafting/recipe/oak_door.json b/neoforge-main/src/main/resources/data/compactcrafting/recipe/oak_door.json deleted file mode 100644 index c6281dc..0000000 --- a/neoforge-main/src/main/resources/data/compactcrafting/recipe/oak_door.json +++ /dev/null @@ -1,30 +0,0 @@ -{ - "type": "compactcrafting:miniaturization", - "version": 1, - "recipeSize": 1, - "layers": [ - { - "type": "compactcrafting:filled", - "component": "P" - }, - { - "type": "compactcrafting:filled", - "component": "P" - } - ], - "catalyst": { - "items": ["minecraft:iron_ingot"] - }, - "components": { - "P": { - "type": "compactcrafting:block", - "block": "minecraft:oak_planks" - } - }, - "outputs": [ - { - "id": "minecraft:oak_door", - "Count": 1 - } - ] -} \ No newline at end of file From 715503701f0009da6bc6d2c533bdab19a4792b08 Mon Sep 17 00:00:00 2001 From: Leclowndu93150 Date: Wed, 24 Sep 2025 15:18:09 +0200 Subject: [PATCH 12/20] fix server crash --- .../dev/compactmods/crafting/client/CompactCraftingClient.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/neoforge-main/src/main/java/dev/compactmods/crafting/client/CompactCraftingClient.java b/neoforge-main/src/main/java/dev/compactmods/crafting/client/CompactCraftingClient.java index 58e3a7b..0ae650c 100644 --- a/neoforge-main/src/main/java/dev/compactmods/crafting/client/CompactCraftingClient.java +++ b/neoforge-main/src/main/java/dev/compactmods/crafting/client/CompactCraftingClient.java @@ -2,11 +2,12 @@ import dev.compactmods.crafting.CompactCrafting; import dev.compactmods.crafting.client.render.field.MiniaturizationFieldRenderer; +import net.neoforged.api.distmarker.Dist; import net.neoforged.bus.api.IEventBus; import net.neoforged.fml.common.Mod; import net.neoforged.neoforge.common.NeoForge; -@Mod(CompactCrafting.MOD_ID) +@Mod(value = CompactCrafting.MOD_ID, dist = Dist.CLIENT) public class CompactCraftingClient { public CompactCraftingClient(IEventBus modBus) { From cff92eac5646337c731f6253f33e6ea850a5de47 Mon Sep 17 00:00:00 2001 From: Leclowndu93150 Date: Thu, 25 Sep 2025 03:23:12 +0200 Subject: [PATCH 13/20] get rid of the placeholder since we fixed the codec --- .../compat/theoneprobe/providers/FieldProjectorProvider.java | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/neoforge-main/src/main/java/dev/compactmods/crafting/compat/theoneprobe/providers/FieldProjectorProvider.java b/neoforge-main/src/main/java/dev/compactmods/crafting/compat/theoneprobe/providers/FieldProjectorProvider.java index 53316da..f68ac37 100644 --- a/neoforge-main/src/main/java/dev/compactmods/crafting/compat/theoneprobe/providers/FieldProjectorProvider.java +++ b/neoforge-main/src/main/java/dev/compactmods/crafting/compat/theoneprobe/providers/FieldProjectorProvider.java @@ -58,10 +58,7 @@ public void addProbeInfo(ProbeMode mode, IProbeInfo info, Player player, Level l if(recipe != null) { int progress = field.getProgress(); - // Get catalyst from recipe - var catalystTest = recipe.catalystTest(); - // For display, show the first possible catalyst (simplified) - group.item(new ItemStack(Items.REDSTONE)); // placeholder + group.item(recipe.catalyst()); group.icon( CompactCrafting.modRL( "textures/gui/jei-arrow-outputs.png"), From 702acdece7047eaeb170097641bb118683de2a3f Mon Sep 17 00:00:00 2001 From: Leclowndu93150 Date: Thu, 25 Sep 2025 17:15:53 +0200 Subject: [PATCH 14/20] implement proxies and fix DataGeneration --- .../crafting/datagen/BlockLootGenerator.java | 19 +++- .../crafting/datagen/DataGeneration.java | 2 +- .../crafting/datagen/ProxyStateGenerator.java | 100 +++++++++--------- .../crafting/datagen/RecipeGenerator.java | 23 ++-- .../proxies/data/BaseFieldProxyEntity.java | 45 -------- .../proxies/data/MatchFieldProxyEntity.java | 13 --- .../compactmods/crafting/CompactCrafting.java | 2 + .../JeiMiniaturizationCraftingCategory.java | 8 -- .../crafting/compat/theoneprobe/TOPMain.java | 2 + .../providers/FieldProxyProvider.java | 47 ++++++++ .../compactmods/crafting/core/CCBlocks.java | 26 ++++- .../crafting/core/CCDataComponents.java | 47 ++++++++ .../compactmods/crafting/core/CCItems.java | 11 +- .../crafting/core/CreativeTabs.java | 4 + .../crafting/field/MiniaturizationField.java | 50 ++++++--- .../crafting}/proxies/ProxyMode.java | 0 .../proxies/block/FieldProxyBlock.java | 38 ++----- .../proxies/block/MatchFieldProxyBlock.java | 17 +-- .../proxies/block/RescanFieldProxyBlock.java | 16 +-- .../proxies/data/BaseFieldProxyEntity.java | 83 +++++++++++++++ .../proxies/data/MatchFieldProxyEntity.java | 37 +++++++ .../proxies/data/RescanFieldProxyEntity.java | 2 +- .../proxies/item/FieldProxyItem.java | 60 +++++------ .../listener/MatchModeProxyFieldListener.java | 30 +++++- .../proxies/render/FieldProxyColors.java | 7 +- .../proxies/render/ProxyRenderSetup.java | 22 ++-- .../assets/compactcrafting/lang/en_us.json | 7 +- 27 files changed, 463 insertions(+), 255 deletions(-) delete mode 100644 neoforge-main/gtfo/proxies/data/BaseFieldProxyEntity.java delete mode 100644 neoforge-main/gtfo/proxies/data/MatchFieldProxyEntity.java create mode 100644 neoforge-main/src/main/java/dev/compactmods/crafting/compat/theoneprobe/providers/FieldProxyProvider.java create mode 100644 neoforge-main/src/main/java/dev/compactmods/crafting/core/CCDataComponents.java rename neoforge-main/{gtfo => src/main/java/dev/compactmods/crafting}/proxies/ProxyMode.java (100%) rename neoforge-main/{gtfo => src/main/java/dev/compactmods/crafting}/proxies/block/FieldProxyBlock.java (64%) rename neoforge-main/{gtfo => src/main/java/dev/compactmods/crafting}/proxies/block/MatchFieldProxyBlock.java (77%) rename neoforge-main/{gtfo => src/main/java/dev/compactmods/crafting}/proxies/block/RescanFieldProxyBlock.java (76%) create mode 100644 neoforge-main/src/main/java/dev/compactmods/crafting/proxies/data/BaseFieldProxyEntity.java create mode 100644 neoforge-main/src/main/java/dev/compactmods/crafting/proxies/data/MatchFieldProxyEntity.java rename neoforge-main/{gtfo => src/main/java/dev/compactmods/crafting}/proxies/data/RescanFieldProxyEntity.java (99%) rename neoforge-main/{gtfo => src/main/java/dev/compactmods/crafting}/proxies/item/FieldProxyItem.java (61%) rename neoforge-main/{gtfo => src/main/java/dev/compactmods/crafting}/proxies/listener/MatchModeProxyFieldListener.java (66%) rename neoforge-main/{gtfo => src/main/java/dev/compactmods/crafting}/proxies/render/FieldProxyColors.java (89%) rename neoforge-main/{gtfo => src/main/java/dev/compactmods/crafting}/proxies/render/ProxyRenderSetup.java (52%) diff --git a/neoforge-datagen/src/main/java/dev/compactmods/crafting/datagen/BlockLootGenerator.java b/neoforge-datagen/src/main/java/dev/compactmods/crafting/datagen/BlockLootGenerator.java index a1efaeb..2a92da1 100644 --- a/neoforge-datagen/src/main/java/dev/compactmods/crafting/datagen/BlockLootGenerator.java +++ b/neoforge-datagen/src/main/java/dev/compactmods/crafting/datagen/BlockLootGenerator.java @@ -24,9 +24,9 @@ public BlockLootGenerator(HolderLookup.Provider holderLookup) { @Override protected Iterable getKnownBlocks() { return ImmutableList.of( - CCBlocks.FIELD_PROJECTOR_BLOCK.get() -// CCBlocks.MATCH_FIELD_PROXY_BLOCK.get(), -// CCBlocks.RESCAN_FIELD_PROXY_BLOCK.get() + CCBlocks.FIELD_PROJECTOR_BLOCK.get(), + CCBlocks.MATCH_FIELD_PROXY_BLOCK.get(), + CCBlocks.RESCAN_FIELD_PROXY_BLOCK.get() ); } @@ -38,5 +38,18 @@ protected void generate() { .setRolls(ConstantValue.exactly(1)) .when(ExplosionCondition.survivesExplosion()) .add(LootItem.lootTableItem(CCItems.FIELD_PROJECTOR_ITEM.get())))); + + this.add(CCBlocks.MATCH_FIELD_PROXY_BLOCK.get(), LootTable.lootTable().withPool(LootPool + .lootPool() + .name(CCBlocks.MATCH_FIELD_PROXY_BLOCK.getId().toString()) + .setRolls(ConstantValue.exactly(1)) + .when(ExplosionCondition.survivesExplosion()) + .add(LootItem.lootTableItem(CCItems.MATCH_PROXY_ITEM.get())))); + this.add(CCBlocks.RESCAN_FIELD_PROXY_BLOCK.get(), LootTable.lootTable().withPool(LootPool + .lootPool() + .name(CCBlocks.RESCAN_FIELD_PROXY_BLOCK.getId().toString()) + .setRolls(ConstantValue.exactly(1)) + .when(ExplosionCondition.survivesExplosion()) + .add(LootItem.lootTableItem(CCItems.RESCAN_PROXY_ITEM.get())))); } } diff --git a/neoforge-datagen/src/main/java/dev/compactmods/crafting/datagen/DataGeneration.java b/neoforge-datagen/src/main/java/dev/compactmods/crafting/datagen/DataGeneration.java index c4fdbe1..98a72f2 100644 --- a/neoforge-datagen/src/main/java/dev/compactmods/crafting/datagen/DataGeneration.java +++ b/neoforge-datagen/src/main/java/dev/compactmods/crafting/datagen/DataGeneration.java @@ -42,6 +42,6 @@ private static void registerClientProviders(DataGenerator generator, GatherDataE generator.addProvider(event.includeClient(), new SharedStateGenerator(pack, event.getExistingFileHelper())); generator.addProvider(event.includeClient(), new ProjectorStateGenerator(pack, event.getExistingFileHelper())); -// generator.addProvider(event.includeClient(), new ProxyStateGenerator(generator, event.getExistingFileHelper())); + generator.addProvider(event.includeClient(), new ProxyStateGenerator(pack, event.getExistingFileHelper())); } } diff --git a/neoforge-datagen/src/main/java/dev/compactmods/crafting/datagen/ProxyStateGenerator.java b/neoforge-datagen/src/main/java/dev/compactmods/crafting/datagen/ProxyStateGenerator.java index 2fb0a04..9f04fc5 100644 --- a/neoforge-datagen/src/main/java/dev/compactmods/crafting/datagen/ProxyStateGenerator.java +++ b/neoforge-datagen/src/main/java/dev/compactmods/crafting/datagen/ProxyStateGenerator.java @@ -1,50 +1,50 @@ -//package dev.compactmods.crafting.datagen; -// -//import dev.compactmods.crafting.CompactCrafting; -//import dev.compactmods.crafting.core.CCBlocks; -//import net.minecraft.client.renderer.block.model.ItemTransforms; -//import net.minecraft.data.DataGenerator; -//import net.minecraft.data.PackOutput; -//import net.neoforged.neoforge.client.model.generators.BlockStateProvider; -//import net.neoforged.neoforge.common.data.ExistingFileHelper; -// -//public class ProxyStateGenerator extends BlockStateProvider { -// -// public ProxyStateGenerator(PackOutput pack, ExistingFileHelper files) { -// super(pack, CompactCrafting.MOD_ID, files); -// } -// -// @Override -// protected void registerStatesAndModels() { -// getVariantBuilder(CCBlocks.MATCH_FIELD_PROXY_BLOCK.get()) -// .forAllStates(state -> ConfiguredModel.builder() -// .modelFile(models().getExistingFile(modLoc("block/base"))) -// .build()); -// -// getVariantBuilder(CCBlocks.RESCAN_FIELD_PROXY_BLOCK.get()) -// .forAllStates(state -> ConfiguredModel.builder() -// .modelFile(models().getExistingFile(modLoc("block/base"))) -// .build()); -// -// SharedStateGenerator.addProjectorBase(models().getBuilder("match_proxy")); -// SharedStateGenerator.addProjectorBase(models().getBuilder("rescan_proxy")); -// -// itemModels() -// .withExistingParent("match_proxy", modLoc("block/match_proxy")) -// .transforms() -// .transform(ItemTransforms.TransformType.GUI) -// .rotation(33.75f, 45f, 0) -// .translation(0, 1, 0) -// .scale(0.6f, 0.6f, 0.6f) -// .end(); -// -// itemModels() -// .withExistingParent("rescan_proxy", modLoc("block/rescan_proxy")) -// .transforms() -// .transform(ItemTransforms.TransformType.GUI) -// .rotation(33.75f, 45f, 0) -// .translation(0, 1, 0) -// .scale(0.6f, 0.6f, 0.6f) -// .end(); -// } -//} +package dev.compactmods.crafting.datagen; + +import dev.compactmods.crafting.CompactCrafting; +import dev.compactmods.crafting.core.CCBlocks; +import net.minecraft.data.PackOutput; +import net.minecraft.world.item.ItemDisplayContext; +import net.neoforged.neoforge.client.model.generators.BlockStateProvider; +import net.neoforged.neoforge.client.model.generators.ConfiguredModel; +import net.neoforged.neoforge.common.data.ExistingFileHelper; + +public class ProxyStateGenerator extends BlockStateProvider { + + public ProxyStateGenerator(PackOutput pack, ExistingFileHelper files) { + super(pack, CompactCrafting.MOD_ID, files); + } + + @Override + protected void registerStatesAndModels() { + getVariantBuilder(CCBlocks.MATCH_FIELD_PROXY_BLOCK.get()) + .forAllStates(state -> ConfiguredModel.builder() + .modelFile(models().getExistingFile(modLoc("block/base"))) + .build()); + + getVariantBuilder(CCBlocks.RESCAN_FIELD_PROXY_BLOCK.get()) + .forAllStates(state -> ConfiguredModel.builder() + .modelFile(models().getExistingFile(modLoc("block/base"))) + .build()); + + SharedStateGenerator.addProjectorBase(models().getBuilder("match_proxy")); + SharedStateGenerator.addProjectorBase(models().getBuilder("rescan_proxy")); + + itemModels() + .withExistingParent("match_proxy", modLoc("block/match_proxy")) + .transforms() + .transform(ItemDisplayContext.GUI) + .rotation(33.75f, 45f, 0) + .translation(0, 1, 0) + .scale(0.6f, 0.6f, 0.6f) + .end(); + + itemModels() + .withExistingParent("rescan_proxy", modLoc("block/rescan_proxy")) + .transforms() + .transform(ItemDisplayContext.GUI) + .rotation(33.75f, 45f, 0) + .translation(0, 1, 0) + .scale(0.6f, 0.6f, 0.6f) + .end(); + } +} diff --git a/neoforge-datagen/src/main/java/dev/compactmods/crafting/datagen/RecipeGenerator.java b/neoforge-datagen/src/main/java/dev/compactmods/crafting/datagen/RecipeGenerator.java index 89036ec..3464882 100644 --- a/neoforge-datagen/src/main/java/dev/compactmods/crafting/datagen/RecipeGenerator.java +++ b/neoforge-datagen/src/main/java/dev/compactmods/crafting/datagen/RecipeGenerator.java @@ -47,16 +47,17 @@ protected void buildRecipes(RecipeOutput output, HolderLookup.Provider provider) .unlockedBy("got_ender_eye", has(Items.ENDER_EYE)) .save(output); -// ShapelessRecipeBuilder.shapeless(CCItems.MATCH_PROXY_ITEM.get()) -// .requires(CCItems.BASE_ITEM.get()) -// .requires(Items.REDSTONE) -// .unlockedBy("got_redstone", has(Items.REDSTONE)) -// .save(consumer); -// -// ShapelessRecipeBuilder.shapeless(CCItems.RESCAN_PROXY_ITEM.get()) -// .requires(CCItems.BASE_ITEM.get()) -// .requires(Items.CRAFTING_TABLE) -// .unlockedBy("got_crafting_table", has(Items.CRAFTING_TABLE)) -// .save(consumer); + ShapelessRecipeBuilder.shapeless(RecipeCategory.MISC,CCItems.MATCH_PROXY_ITEM.get()) + .requires(CCItems.BASE_ITEM.get()) + .requires(Items.REDSTONE) + .unlockedBy("got_redstone", has(Items.REDSTONE)) + .save(output); + + + ShapelessRecipeBuilder.shapeless(RecipeCategory.MISC,CCItems.RESCAN_PROXY_ITEM.get()) + .requires(CCItems.BASE_ITEM.get()) + .requires(Items.CRAFTING_TABLE) + .unlockedBy("got_crafting_table", has(Items.CRAFTING_TABLE)) + .save(output); } } diff --git a/neoforge-main/gtfo/proxies/data/BaseFieldProxyEntity.java b/neoforge-main/gtfo/proxies/data/BaseFieldProxyEntity.java deleted file mode 100644 index bbc78de..0000000 --- a/neoforge-main/gtfo/proxies/data/BaseFieldProxyEntity.java +++ /dev/null @@ -1,45 +0,0 @@ -package dev.compactmods.crafting.proxies.data; - -import net.minecraft.core.BlockPos; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.nbt.NbtUtils; -import net.minecraft.world.level.block.entity.BlockEntity; -import net.minecraft.world.level.block.entity.BlockEntityType; -import net.minecraft.world.level.block.state.BlockState; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -public abstract class BaseFieldProxyEntity extends BlockEntity { - - @Nullable - protected BlockPos fieldCenter; - - public BaseFieldProxyEntity(BlockEntityType type, BlockPos pos, BlockState state) { - super(type, pos, state); - } - - public void updateField(BlockPos fieldCenter) { - if (level == null) - return; - - this.fieldCenter = null; - setChanged(); - } - - @Override - protected void saveAdditional(@NotNull CompoundTag tag) { - super.saveAdditional(tag); - - if(this.fieldCenter != null) - tag.put("center", NbtUtils.writeBlockPos(this.fieldCenter)); - } - - @Override - public void load(CompoundTag tag) { - super.load(tag); - - if(tag.contains("center")) { - this.fieldCenter = NbtUtils.readBlockPos(tag.getCompound("center")); - } - } -} diff --git a/neoforge-main/gtfo/proxies/data/MatchFieldProxyEntity.java b/neoforge-main/gtfo/proxies/data/MatchFieldProxyEntity.java deleted file mode 100644 index bc72f61..0000000 --- a/neoforge-main/gtfo/proxies/data/MatchFieldProxyEntity.java +++ /dev/null @@ -1,13 +0,0 @@ -package dev.compactmods.crafting.proxies.data; - -import dev.compactmods.crafting.core.CCBlocks; -import net.minecraft.core.BlockPos; -import net.minecraft.world.level.block.state.BlockState; - -public class MatchFieldProxyEntity extends BaseFieldProxyEntity { - - public MatchFieldProxyEntity(BlockPos pos, BlockState state) { - super(CCBlocks.MATCH_PROXY_ENTITY.get(), pos, state); - } - -} diff --git a/neoforge-main/src/main/java/dev/compactmods/crafting/CompactCrafting.java b/neoforge-main/src/main/java/dev/compactmods/crafting/CompactCrafting.java index ca664cd..487222f 100644 --- a/neoforge-main/src/main/java/dev/compactmods/crafting/CompactCrafting.java +++ b/neoforge-main/src/main/java/dev/compactmods/crafting/CompactCrafting.java @@ -2,6 +2,7 @@ import dev.compactmods.crafting.client.ClientConfig; import dev.compactmods.crafting.core.CCBlocks; +import dev.compactmods.crafting.core.CCDataComponents; import dev.compactmods.crafting.core.CCItems; import dev.compactmods.crafting.core.CCLayerTypes; import dev.compactmods.crafting.core.CCMiniaturizationRecipes; @@ -32,6 +33,7 @@ public CompactCrafting(IEventBus modBus, ModContainer modContainer) { CCBlocks.init(modBus); CCItems.init(modBus); + CCDataComponents.init(modBus); CCLayerTypes.init(modBus); CCMiniaturizationRecipes.init(modBus); ComponentRegistration.init(modBus); diff --git a/neoforge-main/src/main/java/dev/compactmods/crafting/compat/jei/JeiMiniaturizationCraftingCategory.java b/neoforge-main/src/main/java/dev/compactmods/crafting/compat/jei/JeiMiniaturizationCraftingCategory.java index ad9c9f8..72a3245 100644 --- a/neoforge-main/src/main/java/dev/compactmods/crafting/compat/jei/JeiMiniaturizationCraftingCategory.java +++ b/neoforge-main/src/main/java/dev/compactmods/crafting/compat/jei/JeiMiniaturizationCraftingCategory.java @@ -25,7 +25,6 @@ import mezz.jei.api.gui.drawable.IDrawable; import mezz.jei.api.gui.drawable.IDrawableStatic; import mezz.jei.api.gui.ingredient.IRecipeSlotsView; -import mezz.jei.api.gui.widgets.IRecipeExtrasBuilder; import mezz.jei.api.helpers.IGuiHelper; import mezz.jei.api.recipe.IFocusGroup; import mezz.jei.api.recipe.RecipeIngredientRole; @@ -34,7 +33,6 @@ import net.minecraft.ChatFormatting; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.GuiGraphics; -import net.minecraft.client.renderer.GameRenderer; import net.minecraft.client.renderer.LightTexture; import net.minecraft.client.renderer.MultiBufferSource; import net.minecraft.client.renderer.block.BlockRenderDispatcher; @@ -53,7 +51,6 @@ import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.phys.AABB; import net.minecraft.world.phys.Vec3; -import org.joml.Vector3f; import org.lwjgl.BufferUtils; import org.joml.Matrix4f; import org.joml.Quaternionf; @@ -249,11 +246,6 @@ public void getTooltip(ITooltipBuilder tooltip, MiniaturizationRecipe recipe, IR } } - @Override - public void createRecipeExtras(IRecipeExtrasBuilder builder, MiniaturizationRecipe recipe, IFocusGroup focuses) { - // Input handling moved to new system - will be implemented separately if needed - } - @Override public boolean handleInput(MiniaturizationRecipe recipe, double mouseX, double mouseY, InputConstants.Key input) { if (input.getType() == InputConstants.Type.MOUSE && input.getValue() == 0) { diff --git a/neoforge-main/src/main/java/dev/compactmods/crafting/compat/theoneprobe/TOPMain.java b/neoforge-main/src/main/java/dev/compactmods/crafting/compat/theoneprobe/TOPMain.java index f5ff785..adf441a 100644 --- a/neoforge-main/src/main/java/dev/compactmods/crafting/compat/theoneprobe/TOPMain.java +++ b/neoforge-main/src/main/java/dev/compactmods/crafting/compat/theoneprobe/TOPMain.java @@ -1,6 +1,7 @@ package dev.compactmods.crafting.compat.theoneprobe; import dev.compactmods.crafting.compat.theoneprobe.providers.FieldProjectorProvider; +import dev.compactmods.crafting.compat.theoneprobe.providers.FieldProxyProvider; import mcjty.theoneprobe.api.ITheOneProbe; import java.util.function.Function; @@ -12,6 +13,7 @@ class TOPMain implements Function { public Void apply(Object o) { PROBE = (ITheOneProbe) o; PROBE.registerProvider(new FieldProjectorProvider()); + PROBE.registerProvider(new FieldProxyProvider()); return null; } diff --git a/neoforge-main/src/main/java/dev/compactmods/crafting/compat/theoneprobe/providers/FieldProxyProvider.java b/neoforge-main/src/main/java/dev/compactmods/crafting/compat/theoneprobe/providers/FieldProxyProvider.java new file mode 100644 index 0000000..3b4a7ae --- /dev/null +++ b/neoforge-main/src/main/java/dev/compactmods/crafting/compat/theoneprobe/providers/FieldProxyProvider.java @@ -0,0 +1,47 @@ +package dev.compactmods.crafting.compat.theoneprobe.providers; + +import dev.compactmods.crafting.CompactCrafting; +import dev.compactmods.crafting.data.CCAttachments; +import dev.compactmods.crafting.proxies.block.FieldProxyBlock; +import dev.compactmods.crafting.proxies.data.BaseFieldProxyEntity; +import mcjty.theoneprobe.api.IProbeHitData; +import mcjty.theoneprobe.api.IProbeInfo; +import mcjty.theoneprobe.api.IProbeInfoProvider; +import mcjty.theoneprobe.api.ProbeMode; +import net.minecraft.core.BlockPos; +import net.minecraft.network.chat.Component; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.state.BlockState; + +public class FieldProxyProvider implements IProbeInfoProvider { + private static final ResourceLocation ID = CompactCrafting.modRL("field_proxy"); + + @Override + public ResourceLocation getID() { + return ID; + } + + @Override + public void addProbeInfo(ProbeMode mode, IProbeInfo info, Player player, Level level, BlockState state, IProbeHitData hitData) { + if (!(state.getBlock() instanceof FieldProxyBlock)) + return; + + BaseFieldProxyEntity tile = (BaseFieldProxyEntity) level.getBlockEntity(hitData.getPos()); + if(tile == null || tile.fieldCenter == null) + return; + + var fields = level.getData(CCAttachments.ACTIVE_FIELDS); + fields.get(tile.fieldCenter).ifPresent(field -> { + BlockPos fieldCenter = field.getCenter(); + info.text(Component.translatable("compactcrafting.top.proxy_bound", fieldCenter.toString())); + + if (field.currentRecipe() != null) { + info.text(Component.translatable("compactcrafting.top.proxy_has_recipe")); + } else { + info.text(Component.translatable("compactcrafting.top.proxy_no_recipe")); + } + }); + } +} diff --git a/neoforge-main/src/main/java/dev/compactmods/crafting/core/CCBlocks.java b/neoforge-main/src/main/java/dev/compactmods/crafting/core/CCBlocks.java index d090ff4..d21cd83 100644 --- a/neoforge-main/src/main/java/dev/compactmods/crafting/core/CCBlocks.java +++ b/neoforge-main/src/main/java/dev/compactmods/crafting/core/CCBlocks.java @@ -3,6 +3,10 @@ import dev.compactmods.crafting.CompactCrafting; import dev.compactmods.crafting.projector.FieldProjectorBlock; import dev.compactmods.crafting.projector.FieldProjectorEntity; +import dev.compactmods.crafting.proxies.block.MatchFieldProxyBlock; +import dev.compactmods.crafting.proxies.block.RescanFieldProxyBlock; +import dev.compactmods.crafting.proxies.data.MatchFieldProxyEntity; +import dev.compactmods.crafting.proxies.data.RescanFieldProxyEntity; import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.world.level.block.entity.BlockEntityType; import net.minecraft.world.level.block.state.BlockBehaviour; @@ -23,15 +27,31 @@ public class CCBlocks { .requiresCorrectToolForDrops() )); -// static final Supplier PROXY_PROPS = () -> BlockBehaviour.Properties.of() -// .strength(8, 20) -// .requiresCorrectToolForDrops(); + public static final DeferredBlock RESCAN_FIELD_PROXY_BLOCK = BLOCKS.register("rescan_proxy", () -> + new RescanFieldProxyBlock(BlockBehaviour.Properties.of() + .strength(8, 20) + .requiresCorrectToolForDrops())); + + public static final DeferredBlock MATCH_FIELD_PROXY_BLOCK = BLOCKS.register("match_proxy", () -> + new MatchFieldProxyBlock(BlockBehaviour.Properties.of() + .strength(8, 20) + .requiresCorrectToolForDrops())); public static final DeferredHolder, BlockEntityType> FIELD_PROJECTOR_TILE = BLOCK_ENTITIES.register("field_projector", () -> BlockEntityType.Builder .of(FieldProjectorEntity::new, FIELD_PROJECTOR_BLOCK.get()) .build(null)); + public static final DeferredHolder, BlockEntityType> RESCAN_PROXY_ENTITY = BLOCK_ENTITIES.register("rescan_proxy", () -> + BlockEntityType.Builder + .of(RescanFieldProxyEntity::new, RESCAN_FIELD_PROXY_BLOCK.get()) + .build(null)); + + public static final DeferredHolder, BlockEntityType> MATCH_PROXY_ENTITY = BLOCK_ENTITIES.register("match_proxy", () -> + BlockEntityType.Builder + .of(MatchFieldProxyEntity::new, MATCH_FIELD_PROXY_BLOCK.get()) + .build(null)); + public static void init(IEventBus bus) { BLOCKS.register(bus); BLOCK_ENTITIES.register(bus); diff --git a/neoforge-main/src/main/java/dev/compactmods/crafting/core/CCDataComponents.java b/neoforge-main/src/main/java/dev/compactmods/crafting/core/CCDataComponents.java new file mode 100644 index 0000000..aa17fbf --- /dev/null +++ b/neoforge-main/src/main/java/dev/compactmods/crafting/core/CCDataComponents.java @@ -0,0 +1,47 @@ +package dev.compactmods.crafting.core; + +import com.mojang.serialization.Codec; +import com.mojang.serialization.codecs.RecordCodecBuilder; +import dev.compactmods.crafting.CompactCrafting; +import net.minecraft.core.BlockPos; +import net.minecraft.core.component.DataComponentType; +import net.minecraft.core.registries.Registries; +import net.minecraft.network.RegistryFriendlyByteBuf; +import net.minecraft.network.codec.ByteBufCodecs; +import net.minecraft.network.codec.StreamCodec; +import net.neoforged.bus.api.IEventBus; +import net.neoforged.neoforge.registries.DeferredHolder; +import net.neoforged.neoforge.registries.DeferredRegister; + +public class CCDataComponents { + + private static final DeferredRegister.DataComponents DATA_COMPONENTS = + DeferredRegister.createDataComponents(CompactCrafting.MOD_ID); + + public record FieldCenter(BlockPos center) { + } + + public static final Codec FIELD_CENTER_CODEC = RecordCodecBuilder.create(instance -> + instance.group( + BlockPos.CODEC.fieldOf("center").forGetter(FieldCenter::center) + ).apply(instance, FieldCenter::new) + ); + + public static final StreamCodec FIELD_CENTER_STREAM_CODEC = + StreamCodec.composite( + BlockPos.STREAM_CODEC, FieldCenter::center, + FieldCenter::new + ); + + public static final DeferredHolder, DataComponentType> FIELD_CENTER = + DATA_COMPONENTS.registerComponentType( + "field_center", + builder -> builder + .persistent(FIELD_CENTER_CODEC) + .networkSynchronized(FIELD_CENTER_STREAM_CODEC) + ); + + public static void init(IEventBus bus) { + DATA_COMPONENTS.register(bus); + } +} \ No newline at end of file diff --git a/neoforge-main/src/main/java/dev/compactmods/crafting/core/CCItems.java b/neoforge-main/src/main/java/dev/compactmods/crafting/core/CCItems.java index 901c332..ee66fe1 100644 --- a/neoforge-main/src/main/java/dev/compactmods/crafting/core/CCItems.java +++ b/neoforge-main/src/main/java/dev/compactmods/crafting/core/CCItems.java @@ -2,6 +2,7 @@ import dev.compactmods.crafting.CompactCrafting; import dev.compactmods.crafting.items.FieldProjectorItem; +import dev.compactmods.crafting.proxies.item.FieldProxyItem; import net.minecraft.world.item.Item; import net.neoforged.bus.api.IEventBus; import net.neoforged.neoforge.registries.DeferredItem; @@ -26,11 +27,11 @@ public class CCItems { public static final DeferredItem BASE_ITEM = ITEMS.register("base", () -> new Item(BASE_ITEM_PROPS.get())); -// public static final DeferredItem RESCAN_PROXY_ITEM = ITEMS.register("rescan_proxy", () -> -// new FieldProxyItem(CCBlocks.RESCAN_FIELD_PROXY_BLOCK.get(), BASE_ITEM_PROPS.get())); -// -// public static final DeferredItem MATCH_PROXY_ITEM = ITEMS.register("match_proxy", () -> -// new FieldProxyItem(CCBlocks.MATCH_FIELD_PROXY_BLOCK.get(), BASE_ITEM_PROPS.get())); + public static final DeferredItem RESCAN_PROXY_ITEM = ITEMS.register("rescan_proxy", () -> + new FieldProxyItem(CCBlocks.RESCAN_FIELD_PROXY_BLOCK.get(), BASE_ITEM_PROPS.get())); + + public static final DeferredItem MATCH_PROXY_ITEM = ITEMS.register("match_proxy", () -> + new FieldProxyItem(CCBlocks.MATCH_FIELD_PROXY_BLOCK.get(), BASE_ITEM_PROPS.get())); // ================================================================================================================ diff --git a/neoforge-main/src/main/java/dev/compactmods/crafting/core/CreativeTabs.java b/neoforge-main/src/main/java/dev/compactmods/crafting/core/CreativeTabs.java index 8853bc3..214ac07 100644 --- a/neoforge-main/src/main/java/dev/compactmods/crafting/core/CreativeTabs.java +++ b/neoforge-main/src/main/java/dev/compactmods/crafting/core/CreativeTabs.java @@ -18,6 +18,10 @@ public interface CreativeTabs { .title(Component.translatable("itemGroup.compactcrafting")) .displayItems((params, out) -> { out.accept(CCItems.FIELD_PROJECTOR_ITEM.get()); + out.accept(CCItems.RESCAN_PROXY_ITEM.get()); + out.accept(CCItems.MATCH_PROXY_ITEM.get()); + out.accept(CCItems.PROJECTOR_DISH_ITEM.get()); + out.accept(CCItems.BASE_ITEM.get()); }) .build()); diff --git a/neoforge-main/src/main/java/dev/compactmods/crafting/field/MiniaturizationField.java b/neoforge-main/src/main/java/dev/compactmods/crafting/field/MiniaturizationField.java index beb728d..f7491a2 100644 --- a/neoforge-main/src/main/java/dev/compactmods/crafting/field/MiniaturizationField.java +++ b/neoforge-main/src/main/java/dev/compactmods/crafting/field/MiniaturizationField.java @@ -2,6 +2,7 @@ import dev.compactmods.crafting.CompactCrafting; import dev.compactmods.crafting.api.EnumCraftingState; +import dev.compactmods.crafting.api.field.IFieldListener; import dev.compactmods.crafting.api.field.IMiniaturizationField; import dev.compactmods.crafting.api.field.ITickingMiniaturizationField; import dev.compactmods.crafting.api.field.MiniaturizationFieldSize; @@ -49,9 +50,11 @@ import java.lang.ref.WeakReference; import java.util.Comparator; +import java.util.HashSet; import java.util.List; import java.util.Optional; import java.util.Set; +import java.util.concurrent.CopyOnWriteArraySet; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -77,6 +80,9 @@ public class MiniaturizationField implements IMiniaturizationField listeners = new CopyOnWriteArraySet<>(); private static Disposable CHUNK_LISTENER; @@ -242,10 +248,10 @@ public void setRecipe(RecipeHolder recipe) { if (craftingState == EnumCraftingState.NOT_MATCHED) setCraftingState(EnumCraftingState.MATCHED); -// this.listeners.forEach(li -> li.ifPresent(l -> { -// l.onRecipeChanged(this, this.currentRecipe); -// l.onRecipeMatched(this, this.currentRecipe); -// })); + this.listeners.forEach(l -> { + l.onRecipeChanged(this, this.currentRecipe.value()); + l.onRecipeMatched(this, this.currentRecipe.value()); + }); } @Override @@ -254,10 +260,10 @@ public void clearRecipe() { this.craftingProgress = 0; setCraftingState(EnumCraftingState.NOT_MATCHED); -// listeners.forEach(l -> l.ifPresent(listener -> { -// listener.onRecipeChanged(this, this.currentRecipe); -// listener.onRecipeCleared(this); -// })); + listeners.forEach(listener -> { + listener.onRecipeChanged(this, null); + listener.onRecipeCleared(this); + }); } @Override @@ -338,7 +344,7 @@ private void tickCrafting() { IMiniaturizationRecipe completed = this.currentRecipe.value(); clearRecipe(); -// listeners.forEach(l -> l.ifPresent(listener -> listener.onRecipeCompleted(this, completed))); + listeners.forEach(listener -> listener.onRecipeCompleted(this, completed)); } } @@ -436,12 +442,12 @@ public void doRecipeScan() { // Update all listeners as well final var finalMatchedRecipe = this.currentRecipe; -// listeners.forEach(l -> l.ifPresent(fl -> { -// fl.onRecipeChanged(this, finalMatchedRecipe); -// -// if (craftingState == EnumCraftingState.MATCHED) -// fl.onRecipeMatched(this, finalMatchedRecipe); -// })); + listeners.forEach(fl -> { + fl.onRecipeChanged(this, finalMatchedRecipe != null ? finalMatchedRecipe.value() : null); + + if (craftingState == EnumCraftingState.MATCHED && finalMatchedRecipe != null) + fl.onRecipeMatched(this, finalMatchedRecipe.value()); + }); } @Override @@ -465,7 +471,7 @@ public void checkLoaded() { this.areaLoaded = level.isAreaLoaded(center, size.getProjectorDistance() + 3); if (areaLoaded) { -// listeners.forEach(l -> l.ifPresent(fl -> fl.onFieldActivated(this))); + listeners.forEach(fl -> fl.onFieldActivated(this)); } } @@ -477,6 +483,16 @@ public void fieldContentsChanged() { // set a distant rescan duration to make the field revalidate itself after a second or two this.rescanTime = level.getGameTime() + 30; } + + public void registerListener(IFieldListener listener) { + this.listeners.add(listener); + CompactCrafting.LOGGER.debug("Registered field listener: {}", listener); + } + + public void unregisterListener(IFieldListener listener) { + this.listeners.remove(listener); + CompactCrafting.LOGGER.debug("Unregistered field listener: {}", listener); + } // @Override // public void registerListener(LazyOptional listener) { @@ -614,7 +630,7 @@ public RecipeHolder recipeHolder() { @Override public MiniaturizationRecipe currentRecipe() { - return currentRecipe.value(); + return currentRecipe != null ? currentRecipe.value() : null; } public CompoundTag serverData() { diff --git a/neoforge-main/gtfo/proxies/ProxyMode.java b/neoforge-main/src/main/java/dev/compactmods/crafting/proxies/ProxyMode.java similarity index 100% rename from neoforge-main/gtfo/proxies/ProxyMode.java rename to neoforge-main/src/main/java/dev/compactmods/crafting/proxies/ProxyMode.java diff --git a/neoforge-main/gtfo/proxies/block/FieldProxyBlock.java b/neoforge-main/src/main/java/dev/compactmods/crafting/proxies/block/FieldProxyBlock.java similarity index 64% rename from neoforge-main/gtfo/proxies/block/FieldProxyBlock.java rename to neoforge-main/src/main/java/dev/compactmods/crafting/proxies/block/FieldProxyBlock.java index aa65f01..1fe7058 100644 --- a/neoforge-main/gtfo/proxies/block/FieldProxyBlock.java +++ b/neoforge-main/src/main/java/dev/compactmods/crafting/proxies/block/FieldProxyBlock.java @@ -1,11 +1,10 @@ package dev.compactmods.crafting.proxies.block; import org.jetbrains.annotations.Nullable; +import dev.compactmods.crafting.core.CCDataComponents; import dev.compactmods.crafting.proxies.data.BaseFieldProxyEntity; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.nbt.NbtUtils; import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.BlockGetter; @@ -28,6 +27,7 @@ public abstract class FieldProxyBlock extends Block { public FieldProxyBlock(Properties props) { super(props); + this.registerDefaultState(this.stateDefinition.any().setValue(SIGNAL, 0)); } @Override @@ -47,41 +47,15 @@ protected void createBlockStateDefinition(StateDefinition.Builder { -// CompoundTag fieldInfo = stack.getOrCreateTagElement("field"); -// fieldInfo.put("center", NbtUtils.writeBlockPos(field.getCenter())); -// }); -// } -// -// return stack; -// } - @Override public void setPlacedBy(Level level, BlockPos placedAt, BlockState state, @Nullable LivingEntity entity, ItemStack stack) { super.setPlacedBy(level, placedAt, state, entity, stack); BaseFieldProxyEntity tile = (BaseFieldProxyEntity) level.getBlockEntity(placedAt); - if (stack.hasTag()) { - CompoundTag nbt = stack.getTag(); - - if (nbt != null && nbt.contains("field")) { - CompoundTag fieldData = nbt.getCompound("field"); - if (fieldData.contains("center")) { - BlockPos center = NbtUtils.readBlockPos(fieldData.getCompound("center")); - - if (tile != null) - tile.updateField(center); - } - } + var fieldCenter = stack.get(CCDataComponents.FIELD_CENTER.get()); + if (fieldCenter != null && tile != null) { + tile.updateField(fieldCenter.center()); } } @@ -89,4 +63,4 @@ public void setPlacedBy(Level level, BlockPos placedAt, BlockState state, @Nulla public boolean canConnectRedstone(BlockState state, BlockGetter world, BlockPos pos, @Nullable Direction side) { return true; } -} +} \ No newline at end of file diff --git a/neoforge-main/gtfo/proxies/block/MatchFieldProxyBlock.java b/neoforge-main/src/main/java/dev/compactmods/crafting/proxies/block/MatchFieldProxyBlock.java similarity index 77% rename from neoforge-main/gtfo/proxies/block/MatchFieldProxyBlock.java rename to neoforge-main/src/main/java/dev/compactmods/crafting/proxies/block/MatchFieldProxyBlock.java index d466f7c..5d02000 100644 --- a/neoforge-main/gtfo/proxies/block/MatchFieldProxyBlock.java +++ b/neoforge-main/src/main/java/dev/compactmods/crafting/proxies/block/MatchFieldProxyBlock.java @@ -1,7 +1,7 @@ package dev.compactmods.crafting.proxies.block; import org.jetbrains.annotations.Nullable; -import dev.compactmods.crafting.core.CCCapabilities; +import dev.compactmods.crafting.data.CCAttachments; import dev.compactmods.crafting.proxies.data.MatchFieldProxyEntity; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; @@ -23,12 +23,12 @@ public void onPlace(BlockState currState, Level level, BlockPos placedAt, BlockS super.onPlace(currState, level, placedAt, prevState, update); MatchFieldProxyEntity tile = (MatchFieldProxyEntity) level.getBlockEntity(placedAt); - if (tile != null) { - tile.getCapability(CCCapabilities.MINIATURIZATION_FIELD) - .ifPresent(field -> { - int signal = field.getCurrentRecipe().isPresent() ? 15 : 0; - level.setBlock(placedAt, currState.setValue(SIGNAL, signal), Block.UPDATE_ALL); - }); + if (tile != null && tile.fieldCenter != null && !level.isClientSide) { + var fields = level.getData(CCAttachments.ACTIVE_FIELDS); + fields.get(tile.fieldCenter).ifPresent(field -> { + int signal = field.currentRecipe() != null ? 15 : 0; + level.setBlock(placedAt, currState.setValue(SIGNAL, signal), Block.UPDATE_ALL); + }); } } @@ -52,4 +52,5 @@ public int getSignal(BlockState state, BlockGetter level, BlockPos pos, Directio public BlockEntity newBlockEntity(BlockPos pos, BlockState state) { return new MatchFieldProxyEntity(pos, state); } -} + +} \ No newline at end of file diff --git a/neoforge-main/gtfo/proxies/block/RescanFieldProxyBlock.java b/neoforge-main/src/main/java/dev/compactmods/crafting/proxies/block/RescanFieldProxyBlock.java similarity index 76% rename from neoforge-main/gtfo/proxies/block/RescanFieldProxyBlock.java rename to neoforge-main/src/main/java/dev/compactmods/crafting/proxies/block/RescanFieldProxyBlock.java index de668a3..26148e4 100644 --- a/neoforge-main/gtfo/proxies/block/RescanFieldProxyBlock.java +++ b/neoforge-main/src/main/java/dev/compactmods/crafting/proxies/block/RescanFieldProxyBlock.java @@ -2,7 +2,7 @@ import org.jetbrains.annotations.Nullable; import dev.compactmods.crafting.api.EnumCraftingState; -import dev.compactmods.crafting.core.CCCapabilities; +import dev.compactmods.crafting.data.CCAttachments; import dev.compactmods.crafting.proxies.data.BaseFieldProxyEntity; import dev.compactmods.crafting.proxies.data.RescanFieldProxyEntity; import net.minecraft.core.BlockPos; @@ -33,13 +33,13 @@ public void neighborChanged(BlockState thisState, Level level, BlockPos thisPos, if (level.hasNeighborSignal(thisPos)) { // call recipe scan - if (tile != null) { - tile.getCapability(CCCapabilities.MINIATURIZATION_FIELD) - .ifPresent(field -> { - if(field.getCraftingState() != EnumCraftingState.CRAFTING) - field.fieldContentsChanged(); - }); + if (tile != null && tile.fieldCenter != null) { + var fields = level.getData(CCAttachments.ACTIVE_FIELDS); + fields.get(tile.fieldCenter).ifPresent(field -> { + if(field.getCraftingState() != EnumCraftingState.CRAFTING) + field.fieldContentsChanged(); + }); } } } -} +} \ No newline at end of file diff --git a/neoforge-main/src/main/java/dev/compactmods/crafting/proxies/data/BaseFieldProxyEntity.java b/neoforge-main/src/main/java/dev/compactmods/crafting/proxies/data/BaseFieldProxyEntity.java new file mode 100644 index 0000000..a3859e0 --- /dev/null +++ b/neoforge-main/src/main/java/dev/compactmods/crafting/proxies/data/BaseFieldProxyEntity.java @@ -0,0 +1,83 @@ +package dev.compactmods.crafting.proxies.data; + +import dev.compactmods.crafting.api.field.IMiniaturizationField; +import dev.compactmods.crafting.data.CCAttachments; +import dev.compactmods.crafting.recipes.MiniaturizationRecipe; +import net.minecraft.core.BlockPos; +import net.minecraft.core.HolderLookup; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.NbtUtils; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockState; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.Optional; + +public abstract class BaseFieldProxyEntity extends BlockEntity { + + @Nullable + public BlockPos fieldCenter; + + @Nullable + protected IMiniaturizationField field = null; + + public BaseFieldProxyEntity(BlockEntityType type, BlockPos pos, BlockState state) { + super(type, pos, state); + } + + @Override + public void onLoad() { + super.onLoad(); + + if(fieldCenter != null && level != null) { + var fields = level.getData(CCAttachments.ACTIVE_FIELDS); + fields.get(fieldCenter).ifPresent(this::fieldChanged); + } + } + + public void updateField(BlockPos fieldCenter) { + if (level == null) + return; + + if(fieldCenter == null) { + this.field = null; + this.fieldCenter = null; + return; + } + + var fields = level.getData(CCAttachments.ACTIVE_FIELDS); + fields.get(fieldCenter).ifPresent(f -> { + this.fieldCenter = fieldCenter; + fieldChanged(f); + }); + + setChanged(); + } + + protected void fieldChanged(IMiniaturizationField f) { + this.field = f; + } + + public Optional> getField() { + return Optional.ofNullable(field); + } + + @Override + protected void saveAdditional(@NotNull CompoundTag tag, HolderLookup.Provider registries) { + super.saveAdditional(tag, registries); + + if(this.fieldCenter != null) + tag.put("center", NbtUtils.writeBlockPos(this.fieldCenter)); + } + + @Override + protected void loadAdditional(CompoundTag tag, HolderLookup.Provider registries) { + super.loadAdditional(tag, registries); + + if(tag.contains("center")) { + this.fieldCenter = NbtUtils.readBlockPos(tag, "center").orElse(null); + } + } +} \ No newline at end of file diff --git a/neoforge-main/src/main/java/dev/compactmods/crafting/proxies/data/MatchFieldProxyEntity.java b/neoforge-main/src/main/java/dev/compactmods/crafting/proxies/data/MatchFieldProxyEntity.java new file mode 100644 index 0000000..816fa64 --- /dev/null +++ b/neoforge-main/src/main/java/dev/compactmods/crafting/proxies/data/MatchFieldProxyEntity.java @@ -0,0 +1,37 @@ +package dev.compactmods.crafting.proxies.data; + +import dev.compactmods.crafting.api.field.IMiniaturizationField; +import dev.compactmods.crafting.core.CCBlocks; +import dev.compactmods.crafting.field.MiniaturizationField; +import dev.compactmods.crafting.proxies.listener.MatchModeProxyFieldListener; +import dev.compactmods.crafting.recipes.MiniaturizationRecipe; +import net.minecraft.core.BlockPos; +import net.minecraft.world.level.block.state.BlockState; + +public class MatchFieldProxyEntity extends BaseFieldProxyEntity { + + protected MatchModeProxyFieldListener listener; + + public MatchFieldProxyEntity(BlockPos pos, BlockState state) { + super(CCBlocks.MATCH_PROXY_ENTITY.get(), pos, state); + } + + @Override + protected void fieldChanged(IMiniaturizationField f) { + super.fieldChanged(f); + + this.listener = new MatchModeProxyFieldListener(level, worldPosition); + + if (f instanceof MiniaturizationField mf) { + mf.registerListener(this.listener); + } + } + + @Override + public void setRemoved() { + if (field instanceof MiniaturizationField mf && listener != null) { + mf.unregisterListener(this.listener); + } + super.setRemoved(); + } +} \ No newline at end of file diff --git a/neoforge-main/gtfo/proxies/data/RescanFieldProxyEntity.java b/neoforge-main/src/main/java/dev/compactmods/crafting/proxies/data/RescanFieldProxyEntity.java similarity index 99% rename from neoforge-main/gtfo/proxies/data/RescanFieldProxyEntity.java rename to neoforge-main/src/main/java/dev/compactmods/crafting/proxies/data/RescanFieldProxyEntity.java index 7c6e96a..e4bcc06 100644 --- a/neoforge-main/gtfo/proxies/data/RescanFieldProxyEntity.java +++ b/neoforge-main/src/main/java/dev/compactmods/crafting/proxies/data/RescanFieldProxyEntity.java @@ -8,4 +8,4 @@ public class RescanFieldProxyEntity extends BaseFieldProxyEntity { public RescanFieldProxyEntity(BlockPos pos, BlockState state) { super(CCBlocks.RESCAN_PROXY_ENTITY.get(), pos, state); } -} +} \ No newline at end of file diff --git a/neoforge-main/gtfo/proxies/item/FieldProxyItem.java b/neoforge-main/src/main/java/dev/compactmods/crafting/proxies/item/FieldProxyItem.java similarity index 61% rename from neoforge-main/gtfo/proxies/item/FieldProxyItem.java rename to neoforge-main/src/main/java/dev/compactmods/crafting/proxies/item/FieldProxyItem.java index 5a765e5..1a49c27 100644 --- a/neoforge-main/gtfo/proxies/item/FieldProxyItem.java +++ b/neoforge-main/src/main/java/dev/compactmods/crafting/proxies/item/FieldProxyItem.java @@ -1,19 +1,19 @@ package dev.compactmods.crafting.proxies.item; import java.util.List; -import dev.compactmods.crafting.core.CCCapabilities; +import dev.compactmods.crafting.core.CCDataComponents; +import dev.compactmods.crafting.data.CCAttachments; import dev.compactmods.crafting.projector.FieldProjectorBlock; import dev.compactmods.crafting.projector.FieldProjectorEntity; import net.minecraft.ChatFormatting; import net.minecraft.core.BlockPos; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.nbt.NbtUtils; import net.minecraft.network.chat.Component; import net.minecraft.world.InteractionHand; import net.minecraft.world.InteractionResult; import net.minecraft.world.InteractionResultHolder; import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.BlockItem; +import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.TooltipFlag; import net.minecraft.world.item.context.UseOnContext; @@ -28,18 +28,15 @@ public FieldProxyItem(Block block, Properties props) { } @Override - public void appendHoverText(ItemStack stack, @Nullable Level level, List text, TooltipFlag flags) { - - boolean isLinked = false; - if(stack.hasTag()) { - CompoundTag field = stack.getOrCreateTagElement("field"); - if(field.contains("center")) { - isLinked = true; - - BlockPos linkedCenter = NbtUtils.readBlockPos(field.getCompound("center")); - text.add(Component.translatable("tooltip.compactcrafting.proxy_bound", linkedCenter) - .withStyle(ChatFormatting.ITALIC).withStyle(ChatFormatting.AQUA)); - } + public void appendHoverText(ItemStack stack, Item.@Nullable TooltipContext context, List text, TooltipFlag flags) { + + var fieldCenter = stack.get(CCDataComponents.FIELD_CENTER.get()); + boolean isLinked = fieldCenter != null; + + if(isLinked) { + BlockPos linkedCenter = fieldCenter.center(); + text.add(Component.translatable("tooltip.compactcrafting.proxy_bound", linkedCenter.toString()) + .withStyle(ChatFormatting.ITALIC).withStyle(ChatFormatting.AQUA)); } if(!isLinked) { @@ -52,18 +49,16 @@ public void appendHoverText(ItemStack stack, @Nullable Level level, List use(Level level, Player player, InteractionHand hand) { ItemStack stack = player.getItemInHand(hand); if(player.isDiscrete() && hand == InteractionHand.MAIN_HAND) { - // used in the air while sneaking - player.displayClientMessage(Component.literal("clearing field data"), true); + player.displayClientMessage(Component.translatable("compactcrafting.unbinding_proxy"), true); - // clear field position - stack.removeTagKey("field"); + stack.remove(CCDataComponents.FIELD_CENTER.get()); return InteractionResultHolder.success(stack); } @@ -83,20 +78,23 @@ public InteractionResult useOn(UseOnContext context) { BlockPos usedAt = context.getClickedPos(); BlockState usedState = level.getBlockState(usedAt); - // if used on a projector while sneaking if (usedState.getBlock() instanceof FieldProjectorBlock) { - player.displayClientMessage(Component.literal("copying field position"), true); + + player.displayClientMessage(Component.translatable("compactcrafting.binding_proxy", usedAt.toString()), true); FieldProjectorEntity tile = (FieldProjectorEntity) level.getBlockEntity(usedAt); if (tile != null) { - tile.getCapability(CCCapabilities.MINIATURIZATION_FIELD) - .ifPresent(field -> { - BlockPos fieldCenter = field.getCenter(); - - // write field center - stack.getOrCreateTagElement("field") - .put("center", NbtUtils.writeBlockPos(fieldCenter)); - }); + var fields = level.getData(CCAttachments.ACTIVE_FIELDS); + + // Search through all fields to find one whose projectors include this position + fields.getFields() + .filter(field -> field.getProjectors().locations().contains(usedAt)) + .findFirst() + .ifPresent(field -> { + BlockPos fieldCenter = field.getCenter(); + + stack.set(CCDataComponents.FIELD_CENTER.get(), new CCDataComponents.FieldCenter(fieldCenter)); + }); } return InteractionResult.sidedSuccess(level.isClientSide); @@ -105,4 +103,4 @@ public InteractionResult useOn(UseOnContext context) { return super.useOn(context); } -} +} \ No newline at end of file diff --git a/neoforge-main/gtfo/proxies/listener/MatchModeProxyFieldListener.java b/neoforge-main/src/main/java/dev/compactmods/crafting/proxies/listener/MatchModeProxyFieldListener.java similarity index 66% rename from neoforge-main/gtfo/proxies/listener/MatchModeProxyFieldListener.java rename to neoforge-main/src/main/java/dev/compactmods/crafting/proxies/listener/MatchModeProxyFieldListener.java index f2edcf1..f736af8 100644 --- a/neoforge-main/gtfo/proxies/listener/MatchModeProxyFieldListener.java +++ b/neoforge-main/src/main/java/dev/compactmods/crafting/proxies/listener/MatchModeProxyFieldListener.java @@ -22,11 +22,33 @@ public MatchModeProxyFieldListener(Level level, BlockPos location) { @Override public void onRecipeChanged(IMiniaturizationField field, @Nullable IMiniaturizationRecipe recipe) { - if (level != null) { + updateProxySignal(recipe != null); + } + + @Override + public void onRecipeMatched(IMiniaturizationField field, IMiniaturizationRecipe recipe) { + updateProxySignal(true); + } + + @Override + public void onRecipeCleared(IMiniaturizationField field) { + updateProxySignal(false); + } + + @Override + public void onRecipeCompleted(IMiniaturizationField field, IMiniaturizationRecipe recipe) { + updateProxySignal(false); + } + + @Override + public void onFieldActivated(IMiniaturizationField field) { + updateProxySignal(field.currentRecipe() != null); + } + + private void updateProxySignal(boolean hasRecipe) { + if (level != null && !level.isClientSide) { BlockState currentState = level.getBlockState(location); if (currentState.getBlock() instanceof FieldProxyBlock) { - boolean hasRecipe = recipe != null; - int newPower = hasRecipe ? 15 : 0; if (currentState.getValue(FieldProxyBlock.SIGNAL) != newPower) { @@ -36,4 +58,4 @@ public void onRecipeChanged(IMiniaturizationField field, @Nullable IMiniaturizat } } } -} +} \ No newline at end of file diff --git a/neoforge-main/gtfo/proxies/render/FieldProxyColors.java b/neoforge-main/src/main/java/dev/compactmods/crafting/proxies/render/FieldProxyColors.java similarity index 89% rename from neoforge-main/gtfo/proxies/render/FieldProxyColors.java rename to neoforge-main/src/main/java/dev/compactmods/crafting/proxies/render/FieldProxyColors.java index 7090a46..e809381 100644 --- a/neoforge-main/gtfo/proxies/render/FieldProxyColors.java +++ b/neoforge-main/src/main/java/dev/compactmods/crafting/proxies/render/FieldProxyColors.java @@ -12,6 +12,7 @@ public class FieldProxyColors { private static final int MATCH = 0xFF319a3b; private static final int RESCAN = 0xFFf062de; + public static class MatchBlock implements BlockColor { @Override public int getColor(BlockState state, @Nullable BlockAndTintGetter level, @Nullable BlockPos pos, int tintIndex) { @@ -21,7 +22,7 @@ public int getColor(BlockState state, @Nullable BlockAndTintGetter level, @Nulla public static class MatchItem implements ItemColor { @Override - public int getColor(ItemStack p_getColor_1_, int p_getColor_2_) { + public int getColor(ItemStack stack, int tintIndex) { return MATCH; } } @@ -35,8 +36,8 @@ public int getColor(BlockState state, @Nullable BlockAndTintGetter level, @Nulla public static class RescanItem implements ItemColor { @Override - public int getColor(ItemStack p_getColor_1_, int p_getColor_2_) { + public int getColor(ItemStack stack, int tintIndex) { return RESCAN; } } -} +} \ No newline at end of file diff --git a/neoforge-main/gtfo/proxies/render/ProxyRenderSetup.java b/neoforge-main/src/main/java/dev/compactmods/crafting/proxies/render/ProxyRenderSetup.java similarity index 52% rename from neoforge-main/gtfo/proxies/render/ProxyRenderSetup.java rename to neoforge-main/src/main/java/dev/compactmods/crafting/proxies/render/ProxyRenderSetup.java index 079d8c7..e9ee594 100644 --- a/neoforge-main/gtfo/proxies/render/ProxyRenderSetup.java +++ b/neoforge-main/src/main/java/dev/compactmods/crafting/proxies/render/ProxyRenderSetup.java @@ -5,14 +5,14 @@ import dev.compactmods.crafting.core.CCItems; import net.minecraft.client.renderer.ItemBlockRenderTypes; import net.minecraft.client.renderer.RenderType; -import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.client.event.RegisterColorHandlersEvent; -import net.minecraftforge.eventbus.api.SubscribeEvent; -import net.minecraftforge.fml.common.Mod; -import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent; +import net.neoforged.api.distmarker.Dist; +import net.neoforged.bus.api.SubscribeEvent; +import net.neoforged.fml.common.EventBusSubscriber; +import net.neoforged.fml.event.lifecycle.FMLClientSetupEvent; +import net.neoforged.neoforge.client.event.RegisterColorHandlersEvent; @SuppressWarnings("unused") -@Mod.EventBusSubscriber(modid = CompactCrafting.MOD_ID, value = Dist.CLIENT, bus = Mod.EventBusSubscriber.Bus.MOD) +@EventBusSubscriber(modid = CompactCrafting.MOD_ID, value = Dist.CLIENT, bus = EventBusSubscriber.Bus.MOD) public class ProxyRenderSetup { @SubscribeEvent @@ -24,13 +24,13 @@ public static void init(final FMLClientSetupEvent event) { @SubscribeEvent public static void onBlockColors(final RegisterColorHandlersEvent.Block colors) { // color the ring at the base of the proxy poles - colors.getBlockColors().register(new FieldProxyColors.MatchBlock(), CCBlocks.MATCH_FIELD_PROXY_BLOCK.get()); - colors.getBlockColors().register(new FieldProxyColors.RescanBlock(), CCBlocks.RESCAN_FIELD_PROXY_BLOCK.get()); + colors.register(new FieldProxyColors.MatchBlock(), CCBlocks.MATCH_FIELD_PROXY_BLOCK.get()); + colors.register(new FieldProxyColors.RescanBlock(), CCBlocks.RESCAN_FIELD_PROXY_BLOCK.get()); } @SubscribeEvent public static void onItemColors(final RegisterColorHandlersEvent.Item itemColors) { - itemColors.getItemColors().register(new FieldProxyColors.MatchItem(), CCItems.MATCH_PROXY_ITEM.get()); - itemColors.getItemColors().register(new FieldProxyColors.RescanItem(), CCItems.RESCAN_PROXY_ITEM.get()); + itemColors.register(new FieldProxyColors.MatchItem(), CCItems.MATCH_PROXY_ITEM.get()); + itemColors.register(new FieldProxyColors.RescanItem(), CCItems.RESCAN_PROXY_ITEM.get()); } -} +} \ No newline at end of file diff --git a/neoforge-main/src/main/resources/assets/compactcrafting/lang/en_us.json b/neoforge-main/src/main/resources/assets/compactcrafting/lang/en_us.json index 664504e..1db4a21 100644 --- a/neoforge-main/src/main/resources/assets/compactcrafting/lang/en_us.json +++ b/neoforge-main/src/main/resources/assets/compactcrafting/lang/en_us.json @@ -5,6 +5,9 @@ "block.compactcrafting.rescan_proxy": "Field Proxy (Rescan)", "block.compactcrafting.match_proxy": "Field Proxy (Match)", + "compactcrafting.binding_proxy": "Binding Proxy to field at %s", + "compactcrafting.unbinding_proxy": "Unbinding Proxy from field", + "item.compactcrafting.projector_dish": "Miniaturization Projector Dish", "item.compactcrafting.base": "Base", @@ -15,8 +18,10 @@ "compactcrafting.top.current_recipe": "Recipe: ", "compactcrafting.top.awaiting_catalyst": "Awaiting catalyst...", "compactcrafting.top.progress": "%s / %s", + "compactcrafting.top.proxy_no_recipe": "No recipe", + "compactcrafting.top.proxy_has_recipe": "Found valid recipe", + "compactcrafting.top.proxy_bound": "Bound to: %s", - "tooltip.compactcrafting.proxy_bound": "Bound to: %s", "tooltip.compactcrafting.proxy_hint": "Use proxies for field automation with redstone.", "tooltip.compactcrafting.proxy_bind_hint": "Shift-use on a projector to bind to a field.", "tooltip.compactcrafting.proxy_unbind_hint": "Shift-use in the air to unbind from field.", From 989f75816c73c0c20437f160a45075012c5d34a9 Mon Sep 17 00:00:00 2001 From: Leclowndu93150 Date: Thu, 25 Sep 2025 17:23:49 +0200 Subject: [PATCH 15/20] fix crash --- .../compactmods/crafting/field/MiniaturizationField.java | 6 ++++-- .../main/resources/assets/compactcrafting/lang/en_us.json | 1 + 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/neoforge-main/src/main/java/dev/compactmods/crafting/field/MiniaturizationField.java b/neoforge-main/src/main/java/dev/compactmods/crafting/field/MiniaturizationField.java index f7491a2..84356a0 100644 --- a/neoforge-main/src/main/java/dev/compactmods/crafting/field/MiniaturizationField.java +++ b/neoforge-main/src/main/java/dev/compactmods/crafting/field/MiniaturizationField.java @@ -110,10 +110,12 @@ private MiniaturizationField(Level level, CompoundTag nbt) { this.size = MiniaturizationFieldSize.valueOf(nbt.getString("size")); this.projectors = new FieldProjectorSet(new WeakReference<>(level), this.size.getProjectorLocations(this.center).collect(Collectors.toSet()), this.size); - setupChunkListener(); + if (level != null) { + setupChunkListener(); + } // temp load recipe - if (nbt.contains("recipe")) { + if (nbt.contains("recipe") && level != null) { ResourceLocation recipeId = ResourceLocation.parse(nbt.getString("recipe")); this.craftingProgress = nbt.getInt("progress"); diff --git a/neoforge-main/src/main/resources/assets/compactcrafting/lang/en_us.json b/neoforge-main/src/main/resources/assets/compactcrafting/lang/en_us.json index 1db4a21..ccfd88c 100644 --- a/neoforge-main/src/main/resources/assets/compactcrafting/lang/en_us.json +++ b/neoforge-main/src/main/resources/assets/compactcrafting/lang/en_us.json @@ -22,6 +22,7 @@ "compactcrafting.top.proxy_has_recipe": "Found valid recipe", "compactcrafting.top.proxy_bound": "Bound to: %s", + "tooltip.compactcrafting.proxy_bound": "Bound to field at %s", "tooltip.compactcrafting.proxy_hint": "Use proxies for field automation with redstone.", "tooltip.compactcrafting.proxy_bind_hint": "Shift-use on a projector to bind to a field.", "tooltip.compactcrafting.proxy_unbind_hint": "Shift-use in the air to unbind from field.", From 330b5d482b12ce6a3f5a507ea71aa2a63f5fc750 Mon Sep 17 00:00:00 2001 From: Leclowndu93150 Date: Thu, 25 Sep 2025 20:43:47 +0200 Subject: [PATCH 16/20] add highlighting + networking for it --- .../crafting/client/ClientEventHandler.java | 76 +++++++ .../crafting/client/ClientPacketHandler.java | 15 +- .../client/CompactCraftingClient.java | 2 + .../crafting/client/render/CCRenderTypes.java | 12 ++ .../render/ProxyProjectorHighlighter.java | 188 ++++++++++++++++++ .../crafting/field/ActiveWorldFields.java | 70 ++++++- .../crafting/network/NetworkHandler.java | 2 + .../proxies/data/BaseFieldProxyEntity.java | 30 ++- 8 files changed, 380 insertions(+), 15 deletions(-) create mode 100644 neoforge-main/src/main/java/dev/compactmods/crafting/client/render/ProxyProjectorHighlighter.java diff --git a/neoforge-main/src/main/java/dev/compactmods/crafting/client/ClientEventHandler.java b/neoforge-main/src/main/java/dev/compactmods/crafting/client/ClientEventHandler.java index d003e47..ecab7ec 100644 --- a/neoforge-main/src/main/java/dev/compactmods/crafting/client/ClientEventHandler.java +++ b/neoforge-main/src/main/java/dev/compactmods/crafting/client/ClientEventHandler.java @@ -2,16 +2,27 @@ import dev.compactmods.crafting.CompactCrafting; import dev.compactmods.crafting.client.render.GhostProjectorPlacementRenderer; +import dev.compactmods.crafting.client.render.ProxyProjectorHighlighter; +import dev.compactmods.crafting.core.CCBlocks; +import dev.compactmods.crafting.data.CCAttachments; +import dev.compactmods.crafting.proxies.data.BaseFieldProxyEntity; import net.minecraft.client.Camera; import net.minecraft.client.Minecraft; import net.minecraft.client.multiplayer.ClientLevel; import net.minecraft.client.renderer.MultiBufferSource; +import net.minecraft.core.BlockPos; +import net.minecraft.network.chat.Component; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.phys.BlockHitResult; import net.minecraft.world.phys.HitResult; import net.neoforged.api.distmarker.Dist; import net.neoforged.bus.api.SubscribeEvent; import net.neoforged.fml.common.EventBusSubscriber; import net.neoforged.neoforge.client.event.ClientTickEvent; +import net.neoforged.neoforge.client.event.RenderHighlightEvent; import net.neoforged.neoforge.client.event.RenderLevelStageEvent; +import net.neoforged.neoforge.event.entity.player.PlayerInteractEvent; import javax.annotation.Nonnull; @@ -21,6 +32,7 @@ public class ClientEventHandler { @SubscribeEvent public static void onTick(final ClientTickEvent.Post evt) { GhostProjectorPlacementRenderer.tick(); + ProxyProjectorHighlighter.cleanupExpiredBlinking(); ClientLevel level = Minecraft.getInstance().level; if (level != null && !Minecraft.getInstance().isPaused()) { @@ -39,6 +51,13 @@ public static void onWorldRender(final RenderLevelStageEvent event) { GhostProjectorPlacementRenderer.render(event.getPoseStack()); doFieldPreviewRender(event, mc); } + + if (event.getStage().equals(RenderLevelStageEvent.Stage.AFTER_TRANSLUCENT_BLOCKS)) { + final MultiBufferSource.BufferSource buffers = mc.renderBuffers().bufferSource(); + ProxyProjectorHighlighter.renderAllBlinkingProjectors(event.getPoseStack(), buffers, mc.level); + buffers.endBatch(); + } + } @Nonnull @@ -82,4 +101,61 @@ private static void doFieldPreviewRender(RenderLevelStageEvent event, Minecraft // }); buffers.endBatch(); } + + @SubscribeEvent + public static void onBlockHighlight(final RenderHighlightEvent.Block event) { + final Minecraft mc = Minecraft.getInstance(); + if (mc.level == null) return; + + BlockPos pos = event.getTarget().getBlockPos(); + Block block = mc.level.getBlockState(pos).getBlock(); + + if (block == CCBlocks.MATCH_FIELD_PROXY_BLOCK.get() || block == CCBlocks.RESCAN_FIELD_PROXY_BLOCK.get()) { + ProxyProjectorHighlighter.renderProjectorHighlight( + event.getPoseStack(), + event.getMultiBufferSource(), + pos, + mc.level + ); + } + } + + @SubscribeEvent + public static void onRightClickBlock(final PlayerInteractEvent.RightClickBlock event) { + if (!event.getLevel().isClientSide) return; + if (event.getHand() != InteractionHand.MAIN_HAND) return; + + BlockPos pos = event.getPos(); + Block block = event.getLevel().getBlockState(pos).getBlock(); + + if (block == CCBlocks.MATCH_FIELD_PROXY_BLOCK.get() || block == CCBlocks.RESCAN_FIELD_PROXY_BLOCK.get()) { + BlockPos fieldCenter = ClientPacketHandler.getProxyFieldCenter(pos); + if (fieldCenter == null) { + event.getEntity().sendSystemMessage(Component.literal("Proxy data not loaded yet, try again")); + return; + } + + var fields = event.getLevel().getData(CCAttachments.ACTIVE_FIELDS); + fields.get(fieldCenter).ifPresent(field -> { + boolean anyAdded = false; + int alreadyBlinking = 0; + + for (BlockPos projectorPos : field.getProjectors().locations()) { + if (ProxyProjectorHighlighter.addBlinkingProjector(projectorPos)) { + anyAdded = true; + } else { + alreadyBlinking++; + } + } + + if (anyAdded && alreadyBlinking == 0) { + event.getEntity().sendSystemMessage(Component.literal("Projectors highlighted for 10 seconds")); + } else if (alreadyBlinking > 0 && !anyAdded) { + event.getEntity().sendSystemMessage(Component.literal("Projectors are already highlighted")); + } else if (anyAdded && alreadyBlinking > 0) { + event.getEntity().sendSystemMessage(Component.literal("Some projectors highlighted for 10 seconds (others already active)")); + } + }); + } + } } diff --git a/neoforge-main/src/main/java/dev/compactmods/crafting/client/ClientPacketHandler.java b/neoforge-main/src/main/java/dev/compactmods/crafting/client/ClientPacketHandler.java index 798c39b..f07b7c9 100644 --- a/neoforge-main/src/main/java/dev/compactmods/crafting/client/ClientPacketHandler.java +++ b/neoforge-main/src/main/java/dev/compactmods/crafting/client/ClientPacketHandler.java @@ -14,9 +14,13 @@ import net.minecraft.nbt.CompoundTag; import net.minecraft.world.item.crafting.RecipeHolder; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; import java.util.stream.Stream; public abstract class ClientPacketHandler { + + private static final Map clientProxyToFieldMap = new ConcurrentHashMap<>(); public static void handleFieldActivation(IMiniaturizationField field, CompoundTag fieldClientData) { Minecraft mc = Minecraft.getInstance(); @@ -25,7 +29,6 @@ public static void handleFieldActivation(IMiniaturizationField " + fieldCenter); + } + + public static BlockPos getProxyFieldCenter(BlockPos proxyPos) { + return clientProxyToFieldMap.get(proxyPos); + } } diff --git a/neoforge-main/src/main/java/dev/compactmods/crafting/client/CompactCraftingClient.java b/neoforge-main/src/main/java/dev/compactmods/crafting/client/CompactCraftingClient.java index 0ae650c..f20c943 100644 --- a/neoforge-main/src/main/java/dev/compactmods/crafting/client/CompactCraftingClient.java +++ b/neoforge-main/src/main/java/dev/compactmods/crafting/client/CompactCraftingClient.java @@ -5,6 +5,7 @@ import net.neoforged.api.distmarker.Dist; import net.neoforged.bus.api.IEventBus; import net.neoforged.fml.common.Mod; +import net.neoforged.neoforge.client.event.RenderHighlightEvent; import net.neoforged.neoforge.common.NeoForge; @Mod(value = CompactCrafting.MOD_ID, dist = Dist.CLIENT) @@ -13,4 +14,5 @@ public class CompactCraftingClient { public CompactCraftingClient(IEventBus modBus) { NeoForge.EVENT_BUS.addListener(MiniaturizationFieldRenderer::onRenderStage); } + } diff --git a/neoforge-main/src/main/java/dev/compactmods/crafting/client/render/CCRenderTypes.java b/neoforge-main/src/main/java/dev/compactmods/crafting/client/render/CCRenderTypes.java index c26a681..e73515f 100644 --- a/neoforge-main/src/main/java/dev/compactmods/crafting/client/render/CCRenderTypes.java +++ b/neoforge-main/src/main/java/dev/compactmods/crafting/client/render/CCRenderTypes.java @@ -6,6 +6,8 @@ import net.minecraft.client.renderer.RenderStateShard; import net.minecraft.client.renderer.RenderType; +import java.util.OptionalDouble; + public class CCRenderTypes { protected static final RenderStateShard.ShaderStateShard BLOCK_SHADER = @@ -32,4 +34,14 @@ public class CCRenderTypes { .setCullState(RenderStateShard.NO_CULL) .setWriteMaskState(RenderStateShard.COLOR_DEPTH_WRITE) .createCompositeState(true)); + + public static final RenderType PROJECTOR_HIGHLIGHT = RenderType.create("projector_highlight", + DefaultVertexFormat.POSITION_COLOR, VertexFormat.Mode.QUADS, 256, + RenderType.CompositeState.builder() + .setShaderState(RenderStateShard.POSITION_COLOR_SHADER) + .setTransparencyState(RenderStateShard.TRANSLUCENT_TRANSPARENCY) + .setDepthTestState(RenderStateShard.NO_DEPTH_TEST) + .setCullState(RenderStateShard.NO_CULL) + .setWriteMaskState(RenderStateShard.COLOR_WRITE) + .createCompositeState(false)); } diff --git a/neoforge-main/src/main/java/dev/compactmods/crafting/client/render/ProxyProjectorHighlighter.java b/neoforge-main/src/main/java/dev/compactmods/crafting/client/render/ProxyProjectorHighlighter.java new file mode 100644 index 0000000..389cd16 --- /dev/null +++ b/neoforge-main/src/main/java/dev/compactmods/crafting/client/render/ProxyProjectorHighlighter.java @@ -0,0 +1,188 @@ +package dev.compactmods.crafting.client.render; + +import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.blaze3d.vertex.VertexConsumer; +import dev.compactmods.crafting.client.render.CCRenderTypes; +import dev.compactmods.crafting.client.ClientPacketHandler; +import dev.compactmods.crafting.data.CCAttachments; +import dev.compactmods.crafting.network.RequestProxyDataPacket; +import dev.compactmods.crafting.proxies.data.BaseFieldProxyEntity; +import net.neoforged.neoforge.network.PacketDistributor; +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.LevelRenderer; +import net.minecraft.client.renderer.MultiBufferSource; +import net.minecraft.client.renderer.RenderType; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.world.level.Level; +import net.minecraft.world.phys.AABB; +import net.minecraft.world.phys.Vec3; +import org.joml.Matrix4f; + +import java.util.HashSet; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; + +public class ProxyProjectorHighlighter { + private static final Map blinkingProjectors = new ConcurrentHashMap<>(); + private static final long BLINK_DURATION = 10000; + + public static boolean addBlinkingProjector(BlockPos projectorPos) { + long currentTime = System.currentTimeMillis(); + Long existingTime = blinkingProjectors.get(projectorPos); + + if (existingTime != null && (currentTime - existingTime) < BLINK_DURATION) { + return false; + } + + blinkingProjectors.put(projectorPos, currentTime); + return true; + } + + public static void renderProjectorHighlight(PoseStack poseStack, MultiBufferSource buffers, BlockPos proxyPos, Level level) { + if (level == null) return; + + BlockPos fieldCenter = ClientPacketHandler.getProxyFieldCenter(proxyPos); + if (fieldCenter == null) { + PacketDistributor.sendToServer(new RequestProxyDataPacket(proxyPos)); + return; + } + + var fields = level.getData(CCAttachments.ACTIVE_FIELDS); + var fieldOpt = fields.get(fieldCenter); + + if (fieldOpt.isEmpty()) { + return; + } + + fieldOpt.ifPresent(field -> { + Set projectorPositions = new HashSet<>(field.getProjectors().locations()); + + long currentTime = System.currentTimeMillis(); + + for (BlockPos projectorPos : projectorPositions) { + boolean shouldBlink = blinkingProjectors.containsKey(projectorPos); + Long blinkStartTime = blinkingProjectors.get(projectorPos); + + if (shouldBlink && blinkStartTime != null && (currentTime - blinkStartTime) > BLINK_DURATION) { + blinkingProjectors.remove(projectorPos); + shouldBlink = false; + } + + float alpha = 0.3f; + if (shouldBlink && blinkStartTime != null) { + float blinkProgress = (currentTime - blinkStartTime) / 500.0f; + alpha = 0.2f + 0.4f * (float) Math.abs(Math.sin(blinkProgress)); + } + + renderProjectorOutline(poseStack, buffers, projectorPos, alpha); + } + }); + } + + private static void renderProjectorOutline(PoseStack poseStack, MultiBufferSource buffers, BlockPos projectorPos, float alpha) { + Minecraft mc = Minecraft.getInstance(); + if (mc.level == null) return; + + Vec3 cameraPos = mc.gameRenderer.getMainCamera().getPosition(); + + poseStack.pushPose(); + poseStack.translate( + projectorPos.getX() - cameraPos.x, + projectorPos.getY() - cameraPos.y, + projectorPos.getZ() - cameraPos.z + ); + + VertexConsumer consumer = buffers.getBuffer(CCRenderTypes.PROJECTOR_HIGHLIGHT); + Matrix4f matrix = poseStack.last().pose(); + + float red = 1.0f, green = 0.0f, blue = 0.0f; + + renderCubeFaces(consumer, matrix, red, green, blue, alpha); + + poseStack.popPose(); + } + + private static void renderCubeFaces(VertexConsumer consumer, Matrix4f matrix, float red, float green, float blue, float alpha) { + float minX = -0.01f, minY = -0.01f, minZ = -0.01f; + float maxX = 1.01f, maxY = 1.01f, maxZ = 1.01f; + + consumer.addVertex(matrix, minX, minY, minZ).setColor(red, green, blue, alpha); + consumer.addVertex(matrix, maxX, minY, minZ).setColor(red, green, blue, alpha); + consumer.addVertex(matrix, maxX, maxY, minZ).setColor(red, green, blue, alpha); + consumer.addVertex(matrix, minX, maxY, minZ).setColor(red, green, blue, alpha); + + consumer.addVertex(matrix, minX, minY, maxZ).setColor(red, green, blue, alpha); + consumer.addVertex(matrix, minX, maxY, maxZ).setColor(red, green, blue, alpha); + consumer.addVertex(matrix, maxX, maxY, maxZ).setColor(red, green, blue, alpha); + consumer.addVertex(matrix, maxX, minY, maxZ).setColor(red, green, blue, alpha); + + consumer.addVertex(matrix, minX, minY, minZ).setColor(red, green, blue, alpha); + consumer.addVertex(matrix, minX, maxY, minZ).setColor(red, green, blue, alpha); + consumer.addVertex(matrix, minX, maxY, maxZ).setColor(red, green, blue, alpha); + consumer.addVertex(matrix, minX, minY, maxZ).setColor(red, green, blue, alpha); + + consumer.addVertex(matrix, maxX, minY, minZ).setColor(red, green, blue, alpha); + consumer.addVertex(matrix, maxX, minY, maxZ).setColor(red, green, blue, alpha); + consumer.addVertex(matrix, maxX, maxY, maxZ).setColor(red, green, blue, alpha); + consumer.addVertex(matrix, maxX, maxY, minZ).setColor(red, green, blue, alpha); + + consumer.addVertex(matrix, minX, minY, minZ).setColor(red, green, blue, alpha); + consumer.addVertex(matrix, minX, minY, maxZ).setColor(red, green, blue, alpha); + consumer.addVertex(matrix, maxX, minY, maxZ).setColor(red, green, blue, alpha); + consumer.addVertex(matrix, maxX, minY, minZ).setColor(red, green, blue, alpha); + + consumer.addVertex(matrix, minX, maxY, minZ).setColor(red, green, blue, alpha); + consumer.addVertex(matrix, maxX, maxY, minZ).setColor(red, green, blue, alpha); + consumer.addVertex(matrix, maxX, maxY, maxZ).setColor(red, green, blue, alpha); + consumer.addVertex(matrix, minX, maxY, maxZ).setColor(red, green, blue, alpha); + } + + public static void renderAllBlinkingProjectors(PoseStack poseStack, MultiBufferSource buffers, Level level) { + if (level == null || blinkingProjectors.isEmpty()) return; + + long currentTime = System.currentTimeMillis(); + + for (var entry : blinkingProjectors.entrySet()) { + BlockPos projectorPos = entry.getKey(); + Long blinkStartTime = entry.getValue(); + + if ((currentTime - blinkStartTime) <= BLINK_DURATION) { + float blinkProgress = (currentTime - blinkStartTime) / 500.0f; + float alpha = 0.2f + 0.4f * (float) Math.abs(Math.sin(blinkProgress)); + renderProjectorCube(poseStack, buffers, projectorPos, alpha); + } + } + } + + private static void renderProjectorCube(PoseStack poseStack, MultiBufferSource buffers, BlockPos projectorPos, float alpha) { + Minecraft mc = Minecraft.getInstance(); + if (mc.level == null) return; + + Vec3 cameraPos = mc.gameRenderer.getMainCamera().getPosition(); + + poseStack.pushPose(); + poseStack.translate( + projectorPos.getX() - cameraPos.x, + projectorPos.getY() - cameraPos.y, + projectorPos.getZ() - cameraPos.z + ); + + VertexConsumer consumer = buffers.getBuffer(CCRenderTypes.PROJECTOR_HIGHLIGHT); + Matrix4f matrix = poseStack.last().pose(); + + float red = 1.0f, green = 0.0f, blue = 0.0f; + + renderCubeFaces(consumer, matrix, red, green, blue, alpha); + + poseStack.popPose(); + } + + public static void cleanupExpiredBlinking() { + long currentTime = System.currentTimeMillis(); + blinkingProjectors.entrySet().removeIf(entry -> + (currentTime - entry.getValue()) > BLINK_DURATION); + } + +} \ No newline at end of file diff --git a/neoforge-main/src/main/java/dev/compactmods/crafting/field/ActiveWorldFields.java b/neoforge-main/src/main/java/dev/compactmods/crafting/field/ActiveWorldFields.java index 0285df7..8e70e81 100644 --- a/neoforge-main/src/main/java/dev/compactmods/crafting/field/ActiveWorldFields.java +++ b/neoforge-main/src/main/java/dev/compactmods/crafting/field/ActiveWorldFields.java @@ -6,6 +6,7 @@ import dev.compactmods.crafting.data.NbtListCollector; import dev.compactmods.crafting.network.FieldDeactivatedPacket; import dev.compactmods.crafting.projector.ProjectorHelper; +import dev.compactmods.crafting.proxies.data.BaseFieldProxyEntity; import dev.compactmods.crafting.recipes.MiniaturizationRecipe; import net.minecraft.core.BlockPos; import net.minecraft.nbt.CompoundTag; @@ -18,6 +19,7 @@ import org.jetbrains.annotations.NotNull; import java.util.HashMap; +import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Optional; @@ -29,10 +31,11 @@ public class ActiveWorldFields { private final Level level; - /** - * Holds a set of miniaturization fields that are active, referenced by their center point. - */ private final HashMap> fields = new HashMap<>(); + private final HashMap> pendingFields = new HashMap<>(); + private final Set disconnectedProxies = new HashSet<>(); + private final Map proxyToFieldMap = new HashMap<>(); + private int retryTicker = 0; private ActiveWorldFields(Level level) { this.level = level; @@ -47,6 +50,12 @@ public Stream> getFields() { } public void tickFields() { + retryTicker++; + + if (retryTicker % 20 == 0 && !pendingFields.isEmpty()) { + retryPendingFields(); + } + Set loaded = fields.values().stream() .filter(IMiniaturizationField::isAreaLoaded) .filter(field -> field instanceof ITickingMiniaturizationField) @@ -59,6 +68,46 @@ public void tickFields() { CompactCrafting.LOGGER.trace("Loaded count ({}): {}", level.dimension().location(), loaded.size()); loaded.forEach(ITickingMiniaturizationField::tick); } + + private void retryPendingFields() { + var iterator = pendingFields.entrySet().iterator(); + while (iterator.hasNext()) { + var entry = iterator.next(); + BlockPos center = entry.getKey(); + IMiniaturizationField field = entry.getValue(); + + final Optional anyMissing = ProjectorHelper + .getMissingProjectors(level, field.getFieldSize(), field.getCenter()) + .findFirst(); + + if (anyMissing.isEmpty()) { + addFieldInstance(field); + iterator.remove(); + CompactCrafting.LOGGER.debug("Successfully registered delayed field at center {}", center); + } + } + + retryProxyConnections(); + } + + private void retryProxyConnections() { + var iterator = disconnectedProxies.iterator(); + while (iterator.hasNext()) { + var proxy = iterator.next(); + if (proxy.isRemoved()) { + iterator.remove(); + continue; + } + + if (proxy.tryReconnectToField()) { + iterator.remove(); + } + } + } + + public void registerDisconnectedProxy(BaseFieldProxyEntity proxy) { + disconnectedProxies.add(proxy); + } public void addFieldInstance(IMiniaturizationField field) { BlockPos center = field.getCenter(); @@ -71,30 +120,29 @@ public IMiniaturizationField registerField(IMiniaturizati .findFirst(); if (anyMissing.isPresent()) { - CompactCrafting.LOGGER.warn("Trying to register an active field with missing projector at {}; real state: {}", anyMissing.get(), level.getBlockState(anyMissing.get())); + BlockPos center = field.getCenter(); + if (!pendingFields.containsKey(center)) { + pendingFields.put(center, field); + CompactCrafting.LOGGER.debug("Field registration delayed for center {} - projector at {} not ready yet", center, anyMissing.get()); + } return field; } addFieldInstance(field); - - // Projectors can find their field through the ActiveWorldFields attachment - // using the field center position, so no need to store back-references - return field; } public void unregisterField(BlockPos center) { if (fields.containsKey(center)) { var removedField = fields.remove(center); -// final LazyOptional removed = laziness.remove(center); -// removed.invalidate(); if (!level.isClientSide && removedField != null && level instanceof ServerLevel sl) { - // Send deactivation packet to clients PacketDistributor.sendToPlayersTrackingChunk(sl, new ChunkPos(removedField.getCenter()), new FieldDeactivatedPacket(removedField.getFieldSize(), removedField.getCenter(), List.copyOf(removedField.getProjectors().locations()))); } } + + pendingFields.remove(center); } public void unregisterField(IMiniaturizationField field) { diff --git a/neoforge-main/src/main/java/dev/compactmods/crafting/network/NetworkHandler.java b/neoforge-main/src/main/java/dev/compactmods/crafting/network/NetworkHandler.java index ec36c67..3c7643a 100644 --- a/neoforge-main/src/main/java/dev/compactmods/crafting/network/NetworkHandler.java +++ b/neoforge-main/src/main/java/dev/compactmods/crafting/network/NetworkHandler.java @@ -15,5 +15,7 @@ public static void onPacketRegistration(final RegisterPayloadHandlersEvent paylo main.playToClient(ClientFieldUnwatchPacket.TYPE, ClientFieldUnwatchPacket.STREAM_CODEC, ClientFieldUnwatchPacket.HANDLER); main.playToClient(FieldRecipeChangedPacket.TYPE, FieldRecipeChangedPacket.STREAM_CODEC, FieldRecipeChangedPacket.HANDLER); + main.playToServer(RequestProxyDataPacket.TYPE, RequestProxyDataPacket.STREAM_CODEC, RequestProxyDataPacket::handle); + main.playToClient(ProxyDataResponsePacket.TYPE, ProxyDataResponsePacket.STREAM_CODEC, ProxyDataResponsePacket::handle); } } diff --git a/neoforge-main/src/main/java/dev/compactmods/crafting/proxies/data/BaseFieldProxyEntity.java b/neoforge-main/src/main/java/dev/compactmods/crafting/proxies/data/BaseFieldProxyEntity.java index a3859e0..3d3f86f 100644 --- a/neoforge-main/src/main/java/dev/compactmods/crafting/proxies/data/BaseFieldProxyEntity.java +++ b/neoforge-main/src/main/java/dev/compactmods/crafting/proxies/data/BaseFieldProxyEntity.java @@ -32,9 +32,34 @@ public void onLoad() { super.onLoad(); if(fieldCenter != null && level != null) { + reconnectToField(); + } + } + + private void reconnectToField() { + if (fieldCenter == null || level == null) return; + + var fields = level.getData(CCAttachments.ACTIVE_FIELDS); + var fieldOpt = fields.get(fieldCenter); + + if (fieldOpt.isPresent()) { + fieldChanged(fieldOpt.get()); + } else { + fields.registerDisconnectedProxy(this); + } + } + + public boolean tryReconnectToField() { + if (field == null && fieldCenter != null) { var fields = level.getData(CCAttachments.ACTIVE_FIELDS); - fields.get(fieldCenter).ifPresent(this::fieldChanged); + var fieldOpt = fields.get(fieldCenter); + + if (fieldOpt.isPresent()) { + fieldChanged(fieldOpt.get()); + return true; + } } + return false; } public void updateField(BlockPos fieldCenter) { @@ -68,8 +93,9 @@ public Optional> getField() { protected void saveAdditional(@NotNull CompoundTag tag, HolderLookup.Provider registries) { super.saveAdditional(tag, registries); - if(this.fieldCenter != null) + if(this.fieldCenter != null) { tag.put("center", NbtUtils.writeBlockPos(this.fieldCenter)); + } } @Override From c0c21ba10f0696d5242403d11f3b57293f286fca Mon Sep 17 00:00:00 2001 From: Leclowndu93150 Date: Thu, 25 Sep 2025 20:57:09 +0200 Subject: [PATCH 17/20] doesn't uncache it on break for some reason ? --- .../crafting/client/ClientPacketHandler.java | 5 ++- .../network/ProxyDataResponsePacket.java | 29 +++++++++++++++ .../network/RequestProxyDataPacket.java | 35 +++++++++++++++++++ .../proxies/block/FieldProxyBlock.java | 12 +++++++ 4 files changed, 80 insertions(+), 1 deletion(-) create mode 100644 neoforge-main/src/main/java/dev/compactmods/crafting/network/ProxyDataResponsePacket.java create mode 100644 neoforge-main/src/main/java/dev/compactmods/crafting/network/RequestProxyDataPacket.java diff --git a/neoforge-main/src/main/java/dev/compactmods/crafting/client/ClientPacketHandler.java b/neoforge-main/src/main/java/dev/compactmods/crafting/client/ClientPacketHandler.java index f07b7c9..d13044f 100644 --- a/neoforge-main/src/main/java/dev/compactmods/crafting/client/ClientPacketHandler.java +++ b/neoforge-main/src/main/java/dev/compactmods/crafting/client/ClientPacketHandler.java @@ -101,10 +101,13 @@ public static FieldActivatedPacket createFieldActivationPacket(MiniaturizationFi public static void handleProxyData(BlockPos proxyPos, BlockPos fieldCenter) { clientProxyToFieldMap.put(proxyPos, fieldCenter); - System.out.println("Cached proxy data: " + proxyPos + " -> " + fieldCenter); } public static BlockPos getProxyFieldCenter(BlockPos proxyPos) { return clientProxyToFieldMap.get(proxyPos); } + + public static void removeProxyData(BlockPos proxyPos) { + clientProxyToFieldMap.remove(proxyPos); + } } diff --git a/neoforge-main/src/main/java/dev/compactmods/crafting/network/ProxyDataResponsePacket.java b/neoforge-main/src/main/java/dev/compactmods/crafting/network/ProxyDataResponsePacket.java new file mode 100644 index 0000000..9c0feb4 --- /dev/null +++ b/neoforge-main/src/main/java/dev/compactmods/crafting/network/ProxyDataResponsePacket.java @@ -0,0 +1,29 @@ +package dev.compactmods.crafting.network; + +import dev.compactmods.crafting.CompactCrafting; +import dev.compactmods.crafting.client.ClientPacketHandler; +import net.minecraft.core.BlockPos; +import net.minecraft.network.RegistryFriendlyByteBuf; +import net.minecraft.network.codec.StreamCodec; +import net.minecraft.network.protocol.common.custom.CustomPacketPayload; +import net.neoforged.neoforge.network.handling.IPayloadContext; + +public record ProxyDataResponsePacket(BlockPos proxyPos, BlockPos fieldCenter) implements CustomPacketPayload { + + public static final CustomPacketPayload.Type TYPE = new CustomPacketPayload.Type<>(CompactCrafting.modRL("proxy_data_response")); + + public static final StreamCodec STREAM_CODEC = StreamCodec.composite( + BlockPos.STREAM_CODEC, ProxyDataResponsePacket::proxyPos, + BlockPos.STREAM_CODEC, ProxyDataResponsePacket::fieldCenter, + ProxyDataResponsePacket::new + ); + + @Override + public Type type() { + return TYPE; + } + + public static void handle(ProxyDataResponsePacket packet, IPayloadContext context) { + ClientPacketHandler.handleProxyData(packet.proxyPos, packet.fieldCenter); + } +} \ No newline at end of file diff --git a/neoforge-main/src/main/java/dev/compactmods/crafting/network/RequestProxyDataPacket.java b/neoforge-main/src/main/java/dev/compactmods/crafting/network/RequestProxyDataPacket.java new file mode 100644 index 0000000..cb37247 --- /dev/null +++ b/neoforge-main/src/main/java/dev/compactmods/crafting/network/RequestProxyDataPacket.java @@ -0,0 +1,35 @@ +package dev.compactmods.crafting.network; + +import dev.compactmods.crafting.CompactCrafting; +import dev.compactmods.crafting.proxies.data.BaseFieldProxyEntity; +import net.minecraft.core.BlockPos; +import net.minecraft.network.RegistryFriendlyByteBuf; +import net.minecraft.network.codec.StreamCodec; +import net.minecraft.network.protocol.common.custom.CustomPacketPayload; +import net.minecraft.server.level.ServerPlayer; +import net.neoforged.neoforge.network.PacketDistributor; +import net.neoforged.neoforge.network.handling.IPayloadContext; + +public record RequestProxyDataPacket(BlockPos proxyPos) implements CustomPacketPayload { + + public static final CustomPacketPayload.Type TYPE = new CustomPacketPayload.Type<>(CompactCrafting.modRL("request_proxy_data")); + + public static final StreamCodec STREAM_CODEC = StreamCodec.composite( + BlockPos.STREAM_CODEC, RequestProxyDataPacket::proxyPos, + RequestProxyDataPacket::new + ); + + @Override + public Type type() { + return TYPE; + } + + public static void handle(RequestProxyDataPacket packet, IPayloadContext context) { + if (context.player() instanceof ServerPlayer serverPlayer) { + var blockEntity = serverPlayer.level().getBlockEntity(packet.proxyPos); + if (blockEntity instanceof BaseFieldProxyEntity proxy && proxy.fieldCenter != null) { + PacketDistributor.sendToPlayer(serverPlayer, new ProxyDataResponsePacket(packet.proxyPos, proxy.fieldCenter)); + } + } + } +} \ No newline at end of file diff --git a/neoforge-main/src/main/java/dev/compactmods/crafting/proxies/block/FieldProxyBlock.java b/neoforge-main/src/main/java/dev/compactmods/crafting/proxies/block/FieldProxyBlock.java index 1fe7058..edd88e2 100644 --- a/neoforge-main/src/main/java/dev/compactmods/crafting/proxies/block/FieldProxyBlock.java +++ b/neoforge-main/src/main/java/dev/compactmods/crafting/proxies/block/FieldProxyBlock.java @@ -1,6 +1,9 @@ package dev.compactmods.crafting.proxies.block; +import dev.compactmods.crafting.CompactCrafting; +import net.neoforged.fml.loading.FMLLoader; import org.jetbrains.annotations.Nullable; +import dev.compactmods.crafting.client.ClientPacketHandler; import dev.compactmods.crafting.core.CCDataComponents; import dev.compactmods.crafting.proxies.data.BaseFieldProxyEntity; import net.minecraft.core.BlockPos; @@ -63,4 +66,13 @@ public void setPlacedBy(Level level, BlockPos placedAt, BlockState state, @Nulla public boolean canConnectRedstone(BlockState state, BlockGetter world, BlockPos pos, @Nullable Direction side) { return true; } + + @Override + public void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean isMoving) { + if (level.isClientSide && !state.is(newState.getBlock())) { + ClientPacketHandler.removeProxyData(pos); + if(!FMLLoader.isProduction())CompactCrafting.LOGGER.debug("Removed proxy data for {}", pos); + } + super.onRemove(state, level, pos, newState, isMoving); + } } \ No newline at end of file From 54094598e55da3cbd84a8b2eaae19b01d2bac647 Mon Sep 17 00:00:00 2001 From: Leclowndu93150 Date: Thu, 25 Sep 2025 21:26:13 +0200 Subject: [PATCH 18/20] ok you need to right click to highlight --- .../crafting/client/ClientEventHandler.java | 18 ----------- .../crafting/client/ClientPacketHandler.java | 31 ++++++++++++++----- .../render/ProxyProjectorHighlighter.java | 10 +++++- .../network/ProxyDataResponsePacket.java | 31 ++++++++++++++----- .../network/RequestProxyDataPacket.java | 4 +-- .../proxies/block/FieldProxyBlock.java | 4 +++ .../proxies/data/BaseFieldProxyEntity.java | 11 +++++++ .../crafting/proxies/item/FieldProxyItem.java | 1 + .../assets/compactcrafting/lang/en_us.json | 1 + 9 files changed, 76 insertions(+), 35 deletions(-) diff --git a/neoforge-main/src/main/java/dev/compactmods/crafting/client/ClientEventHandler.java b/neoforge-main/src/main/java/dev/compactmods/crafting/client/ClientEventHandler.java index ecab7ec..7ccd8fe 100644 --- a/neoforge-main/src/main/java/dev/compactmods/crafting/client/ClientEventHandler.java +++ b/neoforge-main/src/main/java/dev/compactmods/crafting/client/ClientEventHandler.java @@ -102,24 +102,6 @@ private static void doFieldPreviewRender(RenderLevelStageEvent event, Minecraft buffers.endBatch(); } - @SubscribeEvent - public static void onBlockHighlight(final RenderHighlightEvent.Block event) { - final Minecraft mc = Minecraft.getInstance(); - if (mc.level == null) return; - - BlockPos pos = event.getTarget().getBlockPos(); - Block block = mc.level.getBlockState(pos).getBlock(); - - if (block == CCBlocks.MATCH_FIELD_PROXY_BLOCK.get() || block == CCBlocks.RESCAN_FIELD_PROXY_BLOCK.get()) { - ProxyProjectorHighlighter.renderProjectorHighlight( - event.getPoseStack(), - event.getMultiBufferSource(), - pos, - mc.level - ); - } - } - @SubscribeEvent public static void onRightClickBlock(final PlayerInteractEvent.RightClickBlock event) { if (!event.getLevel().isClientSide) return; diff --git a/neoforge-main/src/main/java/dev/compactmods/crafting/client/ClientPacketHandler.java b/neoforge-main/src/main/java/dev/compactmods/crafting/client/ClientPacketHandler.java index d13044f..96d092d 100644 --- a/neoforge-main/src/main/java/dev/compactmods/crafting/client/ClientPacketHandler.java +++ b/neoforge-main/src/main/java/dev/compactmods/crafting/client/ClientPacketHandler.java @@ -6,21 +6,24 @@ import dev.compactmods.crafting.field.IMutableMiniaturizationField; import dev.compactmods.crafting.field.MiniaturizationField; import dev.compactmods.crafting.network.FieldActivatedPacket; -import dev.compactmods.crafting.projector.FieldProjectorBlock; import dev.compactmods.crafting.recipes.MiniaturizationRecipe; import net.minecraft.client.Minecraft; import net.minecraft.client.multiplayer.ClientLevel; import net.minecraft.core.BlockPos; import net.minecraft.nbt.CompoundTag; import net.minecraft.world.item.crafting.RecipeHolder; +import org.jetbrains.annotations.Nullable; import java.util.Map; +import java.util.UUID; import java.util.concurrent.ConcurrentHashMap; -import java.util.stream.Stream; public abstract class ClientPacketHandler { - private static final Map clientProxyToFieldMap = new ConcurrentHashMap<>(); + private static final Map clientProxyDataMap = new ConcurrentHashMap<>(); + private static final long CACHE_DURATION = 1000; + + private static record ProxyData(@Nullable BlockPos fieldCenter, UUID proxyId, long timestamp) {} public static void handleFieldActivation(IMiniaturizationField field, CompoundTag fieldClientData) { Minecraft mc = Minecraft.getInstance(); @@ -99,15 +102,29 @@ public static FieldActivatedPacket createFieldActivationPacket(MiniaturizationFi return new FieldActivatedPacket(field, clientData); } - public static void handleProxyData(BlockPos proxyPos, BlockPos fieldCenter) { - clientProxyToFieldMap.put(proxyPos, fieldCenter); + public static void handleProxyData(BlockPos proxyPos, @Nullable BlockPos fieldCenter, UUID proxyId) { + clientProxyDataMap.put(proxyPos, new ProxyData(fieldCenter, proxyId, System.currentTimeMillis())); } public static BlockPos getProxyFieldCenter(BlockPos proxyPos) { - return clientProxyToFieldMap.get(proxyPos); + ProxyData data = clientProxyDataMap.get(proxyPos); + return data != null ? data.fieldCenter : null; + } + + public static boolean isProxyDataStale(BlockPos proxyPos) { + ProxyData data = clientProxyDataMap.get(proxyPos); + if (data == null) return true; + return System.currentTimeMillis() - data.timestamp > CACHE_DURATION; } public static void removeProxyData(BlockPos proxyPos) { - clientProxyToFieldMap.remove(proxyPos); + clientProxyDataMap.remove(proxyPos); + } + + public static void validateAndGetProxyData(BlockPos proxyPos, UUID currentProxyId) { + ProxyData data = clientProxyDataMap.get(proxyPos); + if (data != null && !data.proxyId.equals(currentProxyId)) { + clientProxyDataMap.remove(proxyPos); + } } } diff --git a/neoforge-main/src/main/java/dev/compactmods/crafting/client/render/ProxyProjectorHighlighter.java b/neoforge-main/src/main/java/dev/compactmods/crafting/client/render/ProxyProjectorHighlighter.java index 389cd16..15b4e03 100644 --- a/neoforge-main/src/main/java/dev/compactmods/crafting/client/render/ProxyProjectorHighlighter.java +++ b/neoforge-main/src/main/java/dev/compactmods/crafting/client/render/ProxyProjectorHighlighter.java @@ -43,9 +43,17 @@ public static boolean addBlinkingProjector(BlockPos projectorPos) { public static void renderProjectorHighlight(PoseStack poseStack, MultiBufferSource buffers, BlockPos proxyPos, Level level) { if (level == null) return; + var blockEntity = level.getBlockEntity(proxyPos); + if (blockEntity instanceof BaseFieldProxyEntity proxy) { + ClientPacketHandler.validateAndGetProxyData(proxyPos, proxy.getProxyId()); + } + + if (ClientPacketHandler.isProxyDataStale(proxyPos)) { + PacketDistributor.sendToServer(new RequestProxyDataPacket(proxyPos)); + } + BlockPos fieldCenter = ClientPacketHandler.getProxyFieldCenter(proxyPos); if (fieldCenter == null) { - PacketDistributor.sendToServer(new RequestProxyDataPacket(proxyPos)); return; } diff --git a/neoforge-main/src/main/java/dev/compactmods/crafting/network/ProxyDataResponsePacket.java b/neoforge-main/src/main/java/dev/compactmods/crafting/network/ProxyDataResponsePacket.java index 9c0feb4..e35db45 100644 --- a/neoforge-main/src/main/java/dev/compactmods/crafting/network/ProxyDataResponsePacket.java +++ b/neoforge-main/src/main/java/dev/compactmods/crafting/network/ProxyDataResponsePacket.java @@ -8,15 +8,32 @@ import net.minecraft.network.protocol.common.custom.CustomPacketPayload; import net.neoforged.neoforge.network.handling.IPayloadContext; -public record ProxyDataResponsePacket(BlockPos proxyPos, BlockPos fieldCenter) implements CustomPacketPayload { +import java.util.UUID; +import org.jetbrains.annotations.Nullable; + +public record ProxyDataResponsePacket(BlockPos proxyPos, @Nullable BlockPos fieldCenter, UUID proxyId) implements CustomPacketPayload { public static final CustomPacketPayload.Type TYPE = new CustomPacketPayload.Type<>(CompactCrafting.modRL("proxy_data_response")); - public static final StreamCodec STREAM_CODEC = StreamCodec.composite( - BlockPos.STREAM_CODEC, ProxyDataResponsePacket::proxyPos, - BlockPos.STREAM_CODEC, ProxyDataResponsePacket::fieldCenter, - ProxyDataResponsePacket::new - ); + public static final StreamCodec STREAM_CODEC = new StreamCodec() { + @Override + public ProxyDataResponsePacket decode(RegistryFriendlyByteBuf buf) { + BlockPos proxyPos = BlockPos.STREAM_CODEC.decode(buf); + BlockPos fieldCenter = buf.readBoolean() ? BlockPos.STREAM_CODEC.decode(buf) : null; + UUID proxyId = buf.readUUID(); + return new ProxyDataResponsePacket(proxyPos, fieldCenter, proxyId); + } + + @Override + public void encode(RegistryFriendlyByteBuf buf, ProxyDataResponsePacket packet) { + BlockPos.STREAM_CODEC.encode(buf, packet.proxyPos); + buf.writeBoolean(packet.fieldCenter != null); + if (packet.fieldCenter != null) { + BlockPos.STREAM_CODEC.encode(buf, packet.fieldCenter); + } + buf.writeUUID(packet.proxyId); + } + }; @Override public Type type() { @@ -24,6 +41,6 @@ public Type type() { } public static void handle(ProxyDataResponsePacket packet, IPayloadContext context) { - ClientPacketHandler.handleProxyData(packet.proxyPos, packet.fieldCenter); + ClientPacketHandler.handleProxyData(packet.proxyPos, packet.fieldCenter, packet.proxyId); } } \ No newline at end of file diff --git a/neoforge-main/src/main/java/dev/compactmods/crafting/network/RequestProxyDataPacket.java b/neoforge-main/src/main/java/dev/compactmods/crafting/network/RequestProxyDataPacket.java index cb37247..c154b27 100644 --- a/neoforge-main/src/main/java/dev/compactmods/crafting/network/RequestProxyDataPacket.java +++ b/neoforge-main/src/main/java/dev/compactmods/crafting/network/RequestProxyDataPacket.java @@ -27,8 +27,8 @@ public Type type() { public static void handle(RequestProxyDataPacket packet, IPayloadContext context) { if (context.player() instanceof ServerPlayer serverPlayer) { var blockEntity = serverPlayer.level().getBlockEntity(packet.proxyPos); - if (blockEntity instanceof BaseFieldProxyEntity proxy && proxy.fieldCenter != null) { - PacketDistributor.sendToPlayer(serverPlayer, new ProxyDataResponsePacket(packet.proxyPos, proxy.fieldCenter)); + if (blockEntity instanceof BaseFieldProxyEntity proxy) { + PacketDistributor.sendToPlayer(serverPlayer, new ProxyDataResponsePacket(packet.proxyPos, proxy.fieldCenter, proxy.getProxyId())); } } } diff --git a/neoforge-main/src/main/java/dev/compactmods/crafting/proxies/block/FieldProxyBlock.java b/neoforge-main/src/main/java/dev/compactmods/crafting/proxies/block/FieldProxyBlock.java index edd88e2..fb26dd9 100644 --- a/neoforge-main/src/main/java/dev/compactmods/crafting/proxies/block/FieldProxyBlock.java +++ b/neoforge-main/src/main/java/dev/compactmods/crafting/proxies/block/FieldProxyBlock.java @@ -54,6 +54,10 @@ protected void createBlockStateDefinition(StateDefinition.Builder field = null; + + private UUID proxyId = UUID.randomUUID(); public BaseFieldProxyEntity(BlockEntityType type, BlockPos pos, BlockState state) { super(type, pos, state); @@ -96,6 +99,7 @@ protected void saveAdditional(@NotNull CompoundTag tag, HolderLookup.Provider re if(this.fieldCenter != null) { tag.put("center", NbtUtils.writeBlockPos(this.fieldCenter)); } + tag.putUUID("proxyId", proxyId); } @Override @@ -105,5 +109,12 @@ protected void loadAdditional(CompoundTag tag, HolderLookup.Provider registries) if(tag.contains("center")) { this.fieldCenter = NbtUtils.readBlockPos(tag, "center").orElse(null); } + if(tag.hasUUID("proxyId")) { + this.proxyId = tag.getUUID("proxyId"); + } + } + + public UUID getProxyId() { + return proxyId; } } \ No newline at end of file diff --git a/neoforge-main/src/main/java/dev/compactmods/crafting/proxies/item/FieldProxyItem.java b/neoforge-main/src/main/java/dev/compactmods/crafting/proxies/item/FieldProxyItem.java index 1a49c27..10fc79f 100644 --- a/neoforge-main/src/main/java/dev/compactmods/crafting/proxies/item/FieldProxyItem.java +++ b/neoforge-main/src/main/java/dev/compactmods/crafting/proxies/item/FieldProxyItem.java @@ -48,6 +48,7 @@ public void appendHoverText(ItemStack stack, Item.@Nullable TooltipContext conte } text.add(Component.translatable("tooltip.compactcrafting.proxy_hint").withStyle(ChatFormatting.DARK_GRAY)); + text.add(Component.translatable("tooltip.compactcrafting.proxy_highlight_hint").withStyle(ChatFormatting.DARK_GRAY)); super.appendHoverText(stack, context, text, flags); } diff --git a/neoforge-main/src/main/resources/assets/compactcrafting/lang/en_us.json b/neoforge-main/src/main/resources/assets/compactcrafting/lang/en_us.json index ccfd88c..e43b0b8 100644 --- a/neoforge-main/src/main/resources/assets/compactcrafting/lang/en_us.json +++ b/neoforge-main/src/main/resources/assets/compactcrafting/lang/en_us.json @@ -26,6 +26,7 @@ "tooltip.compactcrafting.proxy_hint": "Use proxies for field automation with redstone.", "tooltip.compactcrafting.proxy_bind_hint": "Shift-use on a projector to bind to a field.", "tooltip.compactcrafting.proxy_unbind_hint": "Shift-use in the air to unbind from field.", + "tooltip.compactcrafting.proxy_highlight_hint": "Right-click on placed proxy to highlight projectors.", "messages.compactcrafting.no_field_cap": "The block at %s does not have a field reference.", "messages.compactcrafting.no_field_found": "The miniaturization field info could not be found.", From 5819e40f9c3413c769923b8ce1dab0228774549c Mon Sep 17 00:00:00 2001 From: Leclowndu93150 Date: Fri, 26 Sep 2025 09:58:11 +0200 Subject: [PATCH 19/20] improve message --- .../dev/compactmods/crafting/client/ClientEventHandler.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/neoforge-main/src/main/java/dev/compactmods/crafting/client/ClientEventHandler.java b/neoforge-main/src/main/java/dev/compactmods/crafting/client/ClientEventHandler.java index 7ccd8fe..4a910ce 100644 --- a/neoforge-main/src/main/java/dev/compactmods/crafting/client/ClientEventHandler.java +++ b/neoforge-main/src/main/java/dev/compactmods/crafting/client/ClientEventHandler.java @@ -113,7 +113,7 @@ public static void onRightClickBlock(final PlayerInteractEvent.RightClickBlock e if (block == CCBlocks.MATCH_FIELD_PROXY_BLOCK.get() || block == CCBlocks.RESCAN_FIELD_PROXY_BLOCK.get()) { BlockPos fieldCenter = ClientPacketHandler.getProxyFieldCenter(pos); if (fieldCenter == null) { - event.getEntity().sendSystemMessage(Component.literal("Proxy data not loaded yet, try again")); + event.getEntity().displayClientMessage(Component.literal("Proxy is not bound to any fields !"), true); return; } From 31176768767a28b677f3aa45e79690db3619582c Mon Sep 17 00:00:00 2001 From: Leclowndu93150 Date: Tue, 7 Oct 2025 14:14:51 +0200 Subject: [PATCH 20/20] tag datagen and periodic rescan --- .gitignore | 3 +- .../crafting/datagen/BlockTagGenerator.java | 32 +++++++++++++++++++ .../crafting/datagen/DataGeneration.java | 1 + .../crafting/field/MiniaturizationField.java | 5 +++ .../compactcrafting/recipe/compact_walls.json | 4 +-- .../compactcrafting/recipe/ender_crystal.json | 2 +- .../data/MiniaturizationRecipeCodecTests.java | 7 ++-- 7 files changed, 46 insertions(+), 8 deletions(-) create mode 100644 neoforge-datagen/src/main/java/dev/compactmods/crafting/datagen/BlockTagGenerator.java diff --git a/.gitignore b/.gitignore index 1e74fe0..a23c7d5 100644 --- a/.gitignore +++ b/.gitignore @@ -6,6 +6,7 @@ bin .classpath .project +.claude # idea out *.ipr @@ -46,4 +47,4 @@ src/generated/ neoforge-main/src/generated/ -neoforge-main/runs/ +neoforge-main/runs/ \ No newline at end of file diff --git a/neoforge-datagen/src/main/java/dev/compactmods/crafting/datagen/BlockTagGenerator.java b/neoforge-datagen/src/main/java/dev/compactmods/crafting/datagen/BlockTagGenerator.java new file mode 100644 index 0000000..274a7f0 --- /dev/null +++ b/neoforge-datagen/src/main/java/dev/compactmods/crafting/datagen/BlockTagGenerator.java @@ -0,0 +1,32 @@ +package dev.compactmods.crafting.datagen; + +import dev.compactmods.crafting.CompactCrafting; +import dev.compactmods.crafting.core.CCBlocks; +import net.minecraft.core.HolderLookup; +import net.minecraft.data.PackOutput; +import net.minecraft.tags.BlockTags; +import net.neoforged.neoforge.common.data.BlockTagsProvider; +import net.neoforged.neoforge.common.data.ExistingFileHelper; +import org.jetbrains.annotations.Nullable; + +import java.util.concurrent.CompletableFuture; + +public class BlockTagGenerator extends BlockTagsProvider { + + public BlockTagGenerator(PackOutput output, CompletableFuture lookupProvider, @Nullable ExistingFileHelper existingFileHelper) { + super(output, lookupProvider, CompactCrafting.MOD_ID, existingFileHelper); + } + + @Override + protected void addTags(HolderLookup.Provider provider) { + tag(BlockTags.MINEABLE_WITH_PICKAXE) + .add(CCBlocks.FIELD_PROJECTOR_BLOCK.get()) + .add(CCBlocks.MATCH_FIELD_PROXY_BLOCK.get()) + .add(CCBlocks.RESCAN_FIELD_PROXY_BLOCK.get()); + + tag(BlockTags.NEEDS_DIAMOND_TOOL) + .add(CCBlocks.FIELD_PROJECTOR_BLOCK.get()) + .add(CCBlocks.MATCH_FIELD_PROXY_BLOCK.get()) + .add(CCBlocks.RESCAN_FIELD_PROXY_BLOCK.get()); + } +} diff --git a/neoforge-datagen/src/main/java/dev/compactmods/crafting/datagen/DataGeneration.java b/neoforge-datagen/src/main/java/dev/compactmods/crafting/datagen/DataGeneration.java index 98a72f2..5e2dfe2 100644 --- a/neoforge-datagen/src/main/java/dev/compactmods/crafting/datagen/DataGeneration.java +++ b/neoforge-datagen/src/main/java/dev/compactmods/crafting/datagen/DataGeneration.java @@ -34,6 +34,7 @@ private static void registerServerProviders(DataGenerator generator, GatherDataE )); generator.addProvider(event.includeServer(), new RecipeGenerator(pack, lookup)); + generator.addProvider(event.includeServer(), new BlockTagGenerator(pack, lookup, event.getExistingFileHelper())); } private static void registerClientProviders(DataGenerator generator, GatherDataEvent event) { diff --git a/neoforge-main/src/main/java/dev/compactmods/crafting/field/MiniaturizationField.java b/neoforge-main/src/main/java/dev/compactmods/crafting/field/MiniaturizationField.java index 84356a0..4450d24 100644 --- a/neoforge-main/src/main/java/dev/compactmods/crafting/field/MiniaturizationField.java +++ b/neoforge-main/src/main/java/dev/compactmods/crafting/field/MiniaturizationField.java @@ -286,6 +286,11 @@ public void tick() { this.rescanTime = 0; break; } + + // Rescan every 5 seconds because tools like the Advanced Swapper don't trigger the field contents changed + if (level.getGameTime() % 100 == 0) { + doRecipeScan(); + } break; case MATCHED: diff --git a/neoforge-main/src/main/resources/data/compactcrafting/recipe/compact_walls.json b/neoforge-main/src/main/resources/data/compactcrafting/recipe/compact_walls.json index eda73d7..acb464e 100644 --- a/neoforge-main/src/main/resources/data/compactcrafting/recipe/compact_walls.json +++ b/neoforge-main/src/main/resources/data/compactcrafting/recipe/compact_walls.json @@ -26,7 +26,7 @@ } }, "outputs": [{ - "id": "minecraft:diamond", - "Count": 1 + "id": "compactmachines:wall", + "Count": 16 }] } \ No newline at end of file diff --git a/neoforge-main/src/main/resources/data/compactcrafting/recipe/ender_crystal.json b/neoforge-main/src/main/resources/data/compactcrafting/recipe/ender_crystal.json index 906fae7..fd6ebfb 100644 --- a/neoforge-main/src/main/resources/data/compactcrafting/recipe/ender_crystal.json +++ b/neoforge-main/src/main/resources/data/compactcrafting/recipe/ender_crystal.json @@ -32,7 +32,7 @@ ], "catalyst": { - "items": ["minecraft:ender_pearl"] + "id": "minecraft:ender_pearl" }, "components": { diff --git a/neoforge-main/src/test/java/dev/compactmods/crafting/test/junit/recipes/data/MiniaturizationRecipeCodecTests.java b/neoforge-main/src/test/java/dev/compactmods/crafting/test/junit/recipes/data/MiniaturizationRecipeCodecTests.java index 540a88d..776fdfb 100644 --- a/neoforge-main/src/test/java/dev/compactmods/crafting/test/junit/recipes/data/MiniaturizationRecipeCodecTests.java +++ b/neoforge-main/src/test/java/dev/compactmods/crafting/test/junit/recipes/data/MiniaturizationRecipeCodecTests.java @@ -13,7 +13,6 @@ import dev.compactmods.crafting.test.FileHelper; import net.minecraft.nbt.NbtOps; import net.minecraft.nbt.Tag; -import net.minecraft.resources.RegistryOps; import net.minecraft.server.MinecraftServer; import net.neoforged.testframework.junit.EphemeralTestServerProvider; import org.junit.jupiter.api.Assertions; @@ -37,11 +36,11 @@ public void LoadsRecipeFromJson(final MinecraftServer server) { public void DoesNotFailIfNoComponentsDefined(final MinecraftServer server) { JsonElement json = FileHelper.getJsonFromFile("recipe_tests/warn_no_components.json"); - final var ops = RegistryOps.create(JsonOps.INSTANCE, server.registryAccess()); final var result = MiniaturizationRecipe.CODEC .codec() - .parse(ops, json) - .getOrThrow(); + .parse(JsonOps.INSTANCE, json) + .resultOrPartial(Assertions::fail) + .orElseThrow(); final IRecipeComponents components = result.getComponents(); if (components == null) {