diff --git a/src/main/java/appeng/server/testplots/AutoCraftingTestPlots.java b/src/main/java/appeng/server/testplots/AutoCraftingTestPlots.java index 4109e710573..9707334ebe5 100644 --- a/src/main/java/appeng/server/testplots/AutoCraftingTestPlots.java +++ b/src/main/java/appeng/server/testplots/AutoCraftingTestPlots.java @@ -12,6 +12,7 @@ import net.minecraft.world.item.crafting.RecipeType; import net.minecraft.world.level.ItemLike; import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.block.state.properties.BlockStateProperties; import net.minecraft.world.level.material.Fluids; import appeng.api.config.Actionable; @@ -24,6 +25,7 @@ import appeng.blockentity.crafting.PatternProviderBlockEntity; import appeng.blockentity.misc.InscriberBlockEntity; import appeng.blockentity.storage.SkyChestBlockEntity; +import appeng.core.AppEng; import appeng.core.definitions.AEBlocks; import appeng.core.definitions.AEItems; import appeng.core.definitions.AEParts; @@ -31,6 +33,7 @@ import appeng.me.helpers.BaseActionSource; import appeng.menu.AutoCraftingMenu; import appeng.server.testworld.PlotBuilder; +import appeng.server.testworld.SpawnExtraGridTestToolsChest; import appeng.server.testworld.TestCraftingJob; import appeng.util.inv.AppEngInternalInventory; @@ -66,6 +69,7 @@ public static void create(PlotBuilder plot) { drive.getInternalInventory().addItems(CreativeCellItem.ofItems(Items.REDSTONE)); drive.getInternalInventory().addItems(CreativeCellItem.ofFluids(Fluids.LAVA)); }); + plot.block("7 -1 0", AEBlocks.CELL_WORKBENCH); plot.part("6 0 1", Direction.NORTH, AEParts.PATTERN_ENCODING_TERMINAL, term -> { var inv = term.getLogic().getBlankPatternInv(); inv.addItems(AEItems.BLANK_PATTERN.stack(64)); @@ -74,6 +78,15 @@ public static void create(PlotBuilder plot) { plot.part("4 0 1", Direction.NORTH, AEParts.TERMINAL); plot.part("3 0 1", Direction.NORTH, AEParts.CRAFTING_TERMINAL); + // Wireless access + plot.blockState("6 1 1", AEBlocks.WIRELESS_ACCESS_POINT.block() + .defaultBlockState() + .setValue(BlockStateProperties.FACING, Direction.UP)); + plot.addBuildAction(new SpawnExtraGridTestToolsChest( + new BlockPos(8, 0, 1), + new BlockPos(7, 0, 1), + AppEng.makeId("autocrafting_testplot"))); + // Subsystem to craft obsidian buildObsidianCrafting(plot.offset(3, 0, 5)); diff --git a/src/main/java/appeng/server/testplots/SpawnExtraGridTestTools.java b/src/main/java/appeng/server/testplots/SpawnExtraGridTestTools.java new file mode 100644 index 00000000000..1b576d8c830 --- /dev/null +++ b/src/main/java/appeng/server/testplots/SpawnExtraGridTestTools.java @@ -0,0 +1,34 @@ +package appeng.server.testplots; + +import net.minecraft.resources.ResourceLocation; +import net.neoforged.bus.api.Event; + +import appeng.api.inventories.InternalInventory; +import appeng.api.networking.IGrid; + +/** + * Triggered to spawn additional testing tools into a container placed next to a spawned AE2 grid. + */ +public class SpawnExtraGridTestTools extends Event { + private final ResourceLocation plotId; + private final InternalInventory inventory; + private final IGrid grid; + + public SpawnExtraGridTestTools(ResourceLocation plotId, InternalInventory inventory, IGrid grid) { + this.plotId = plotId; + this.inventory = inventory; + this.grid = grid; + } + + public ResourceLocation getPlotId() { + return plotId; + } + + public InternalInventory getInventory() { + return inventory; + } + + public IGrid getGrid() { + return grid; + } +} diff --git a/src/main/java/appeng/server/testplots/SpawnTestTools.java b/src/main/java/appeng/server/testplots/SpawnTestTools.java new file mode 100644 index 00000000000..e17c0e3e0e6 --- /dev/null +++ b/src/main/java/appeng/server/testplots/SpawnTestTools.java @@ -0,0 +1,38 @@ +package appeng.server.testplots; + +import java.util.List; + +import net.minecraft.core.GlobalPos; +import net.neoforged.bus.api.SubscribeEvent; +import net.neoforged.fml.common.Mod; + +import appeng.api.config.Actionable; +import appeng.api.features.GridLinkables; +import appeng.blockentity.networking.WirelessAccessPointBlockEntity; +import appeng.core.definitions.AEItems; + +@Mod.EventBusSubscriber +public final class SpawnTestTools { + + @SubscribeEvent + public static void spawnWirelessTerminals(SpawnExtraGridTestTools e) { + // Find a suitable WAP to link to + var waps = e.getGrid().getMachines(WirelessAccessPointBlockEntity.class); + if (waps.isEmpty()) { + return; + } + + var wap = waps.iterator().next(); + var inventory = e.getInventory(); + + for (var item : List.of(AEItems.WIRELESS_CRAFTING_TERMINAL, AEItems.WIRELESS_TERMINAL)) { + var terminal = item.stack(); + // Fully charge it + item.asItem().injectAEPower(terminal, Double.MAX_VALUE, Actionable.MODULATE); + // Link it to the WAP we just placed + GridLinkables.get(item).link(terminal, GlobalPos.of(wap.getLevel().dimension(), wap.getBlockPos())); + inventory.addItems(terminal); + } + } + +} diff --git a/src/main/java/appeng/server/testworld/BuildAction.java b/src/main/java/appeng/server/testworld/BuildAction.java index 931c5a0f870..6c31ca9efaa 100644 --- a/src/main/java/appeng/server/testworld/BuildAction.java +++ b/src/main/java/appeng/server/testworld/BuildAction.java @@ -8,7 +8,7 @@ import net.minecraft.world.entity.player.Player; import net.minecraft.world.level.levelgen.structure.BoundingBox; -interface BuildAction { +public interface BuildAction { BoundingBox getBoundingBox(); default void build(ServerLevel level, Player player, BlockPos origin) { diff --git a/src/main/java/appeng/server/testworld/GridInitHelper.java b/src/main/java/appeng/server/testworld/GridInitHelper.java new file mode 100644 index 00000000000..5135b9ee352 --- /dev/null +++ b/src/main/java/appeng/server/testworld/GridInitHelper.java @@ -0,0 +1,53 @@ +package appeng.server.testworld; + +import java.util.function.BiConsumer; + +import net.minecraft.core.BlockPos; +import net.minecraft.server.level.ServerLevel; + +import appeng.api.networking.IGrid; +import appeng.api.networking.IGridNode; +import appeng.blockentity.networking.CableBusBlockEntity; +import appeng.hooks.ticking.TickHandler; +import appeng.me.helpers.IGridConnectedBlockEntity; + +final class GridInitHelper { + + static void doAfterGridInit(ServerLevel level, BlockPos pos, boolean waitForActive, + BiConsumer consumer) { + Runnable delayedAction = new Runnable() { + private int attempts = 120; + + @Override + public void run() { + // Check if there's a grid node there + var be = level.getBlockEntity(pos); + IGridNode gridNode = null; + if (be instanceof IGridConnectedBlockEntity host) { + gridNode = host.getMainNode().getNode(); + } else if (be instanceof CableBusBlockEntity cableBus) { + var centerPart = cableBus.getCableBus().getPart(null); + if (centerPart != null) { + gridNode = centerPart.getGridNode(); + } else { + return; // Stop -> not eligible + } + } else { + return; // Stop -> not eligible + } + + if (gridNode == null || waitForActive && !gridNode.isActive()) { + if (--attempts > 0) { + TickHandler.instance().addCallable(level, this); + } else { + throw new IllegalStateException("Couldn't access grid node @ " + pos); + } + } else { + consumer.accept(gridNode.getGrid(), gridNode); + } + } + }; + TickHandler.instance().addCallable(level, delayedAction); + } + +} diff --git a/src/main/java/appeng/server/testworld/PlaceItemFrameAction.java b/src/main/java/appeng/server/testworld/PlaceItemFrameAction.java new file mode 100644 index 00000000000..075be7f1d8b --- /dev/null +++ b/src/main/java/appeng/server/testworld/PlaceItemFrameAction.java @@ -0,0 +1,32 @@ +package appeng.server.testworld; + +import java.util.List; +import java.util.function.Consumer; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.decoration.ItemFrame; +import net.minecraft.world.level.levelgen.structure.BoundingBox; + +public record PlaceItemFrameAction(BlockPos pos, Direction facing, + Consumer customizer) implements BuildAction { + @Override + public BoundingBox getBoundingBox() { + return new BoundingBox(pos); + } + + @Override + public void spawnEntities(ServerLevel level, BlockPos origin, List entities) { + var actualPos = pos.offset(origin); + + var itemFrame = new ItemFrame(EntityType.ITEM_FRAME, level, actualPos, facing); + if (!level.addFreshEntity(itemFrame)) { + return; + } + customizer.accept(itemFrame); + entities.add(itemFrame); + } +} diff --git a/src/main/java/appeng/server/testworld/PlotBuilder.java b/src/main/java/appeng/server/testworld/PlotBuilder.java index 1c41613aff7..cc49ab50f93 100644 --- a/src/main/java/appeng/server/testworld/PlotBuilder.java +++ b/src/main/java/appeng/server/testworld/PlotBuilder.java @@ -348,6 +348,15 @@ default void fencedEntity(BlockPos pos, EntityType entity) { }); } + default void entity(BlockPos pos, EntityType entity) { + entity(pos, entity, e -> { + }); + } + + default void entity(BlockPos pos, EntityType entity, Consumer postProcessor) { + addBuildAction(new SpawnEntityAction(bb(posToBb(pos)), entity, postProcessor)); + } + default void fencedEntity(BlockPos pos, EntityType entity, Consumer postProcessor) { var subPlot = offset(pos.getX(), pos.getY(), pos.getZ()); subPlot.block("[-1,1] -1 [-1,1]", Blocks.STONE); diff --git a/src/main/java/appeng/server/testworld/PostGridInitAction.java b/src/main/java/appeng/server/testworld/PostGridInitAction.java index bb589177642..dfa404fe920 100644 --- a/src/main/java/appeng/server/testworld/PostGridInitAction.java +++ b/src/main/java/appeng/server/testworld/PostGridInitAction.java @@ -9,9 +9,6 @@ import appeng.api.networking.IGrid; import appeng.api.networking.IGridNode; -import appeng.blockentity.networking.CableBusBlockEntity; -import appeng.hooks.ticking.TickHandler; -import appeng.me.helpers.IGridConnectedBlockEntity; public record PostGridInitAction(BoundingBox bb, BiConsumer consumer, @@ -19,39 +16,7 @@ public record PostGridInitAction(BoundingBox bb, @Override public void placeBlock(ServerLevel level, Player player, BlockPos pos, BlockPos minPos, BlockPos maxPos) { - Runnable delayedAction = new Runnable() { - private int attempts = 120; - - @Override - public void run() { - // Check if there's a grid node there - var be = level.getBlockEntity(pos); - IGridNode gridNode = null; - if (be instanceof IGridConnectedBlockEntity host) { - gridNode = host.getMainNode().getNode(); - } else if (be instanceof CableBusBlockEntity cableBus) { - var centerPart = cableBus.getCableBus().getPart(null); - if (centerPart != null) { - gridNode = centerPart.getGridNode(); - } else { - return; // Stop -> not eligible - } - } else { - return; // Stop -> not eligible - } - - if (gridNode == null || waitForActive && !gridNode.isActive()) { - if (--attempts > 0) { - TickHandler.instance().addCallable(level, this); - } else { - throw new IllegalStateException("Couldn't access grid node @ " + pos); - } - } else { - consumer.accept(gridNode.getGrid(), gridNode); - } - } - }; - TickHandler.instance().addCallable(level, delayedAction); + GridInitHelper.doAfterGridInit(level, pos, waitForActive, consumer); } @Override diff --git a/src/main/java/appeng/server/testworld/SpawnExtraGridTestToolsChest.java b/src/main/java/appeng/server/testworld/SpawnExtraGridTestToolsChest.java new file mode 100644 index 00000000000..d7be8ae70a6 --- /dev/null +++ b/src/main/java/appeng/server/testworld/SpawnExtraGridTestToolsChest.java @@ -0,0 +1,40 @@ +package appeng.server.testworld; + +import net.minecraft.core.BlockPos; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.levelgen.structure.BoundingBox; +import net.neoforged.neoforge.common.NeoForge; + +import appeng.core.definitions.AEBlockEntities; +import appeng.core.definitions.AEBlocks; +import appeng.server.testplots.SpawnExtraGridTestTools; + +/** + * Spawns a sky stone chest at the given position and once the grid at another position is initialized, posts + * {@link SpawnExtraGridTestTools} to allow the chest to be populated. + */ +public record SpawnExtraGridTestToolsChest(BlockPos chestPos, BlockPos gridPos, + ResourceLocation plotId) implements BuildAction { + @Override + public BoundingBox getBoundingBox() { + return new BoundingBox(chestPos); + } + + @Override + public void build(ServerLevel level, Player player, BlockPos origin) { + var absChestPod = chestPos.offset(origin); + var absGridPos = gridPos.offset(origin); + level.setBlock(absChestPod, AEBlocks.SMOOTH_SKY_STONE_CHEST.block().defaultBlockState(), Block.UPDATE_ALL); + + GridInitHelper.doAfterGridInit(level, absGridPos, false, (grid, gridNode) -> { + var chestOpt = level.getBlockEntity(absChestPod, AEBlockEntities.SKY_CHEST); + chestOpt.ifPresent(chest -> { + var inventory = chest.getInternalInventory(); + NeoForge.EVENT_BUS.post(new SpawnExtraGridTestTools(plotId, inventory, grid)); + }); + }); + } +}