From 778e0ee2cb27d4205505808b4993704e4700aec0 Mon Sep 17 00:00:00 2001 From: Cassunshine Date: Sat, 10 Feb 2024 13:55:28 -0500 Subject: [PATCH] -re-add alchemy nodes having an item slot --- .../cassunshine/thework/TheWorkClient.java | 13 +++ .../AlchemyCircleBlockEntityRenderer.java | 28 +++++- .../nodes/RuneAlchemyNodeTypeRenderer.java | 2 +- .../thework/alchemy/circle/AlchemyCircle.java | 11 +++ .../circle/AlchemyCircleComponent.java | 3 + .../events/node/AlchemyNodeSetItem.java | 45 ++++++++++ .../alchemy/circle/node/AlchemyNode.java | 85 +++++++++++++------ .../circle/node/type/AlchemyNodeType.java | 7 ++ .../circle/node/type/AlchemyNodeTypes.java | 2 +- .../alchemy/circle/path/AlchemyPath.java | 6 ++ .../alchemy/circle/ring/AlchemyRing.java | 19 +++-- .../AlchemyCircleBlockEntity.java | 50 +++++++++++ .../network/events/TheWorkNetworkEvents.java | 3 +- 13 files changed, 235 insertions(+), 39 deletions(-) create mode 100644 src/main/java/cassunshine/thework/alchemy/circle/events/node/AlchemyNodeSetItem.java diff --git a/src/client/java/cassunshine/thework/TheWorkClient.java b/src/client/java/cassunshine/thework/TheWorkClient.java index 834a0b4..b9e2a1f 100644 --- a/src/client/java/cassunshine/thework/TheWorkClient.java +++ b/src/client/java/cassunshine/thework/TheWorkClient.java @@ -9,11 +9,16 @@ import cassunshine.thework.rendering.particles.TheWorkParticleRenderers; import net.fabricmc.api.ClientModInitializer; import net.fabricmc.fabric.api.blockrenderlayer.v1.BlockRenderLayerMap; +import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientLifecycleEvents; +import net.fabricmc.fabric.api.client.rendering.v1.WorldRenderEvents; +import net.minecraft.client.MinecraftClient; import net.minecraft.client.render.RenderLayer; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class TheWorkClient implements ClientModInitializer { + private static final double RENDER_TIME_MULT = 1.0d / 1_000_000_000d; + public static final Logger CLIENT_LOGGER = LoggerFactory.getLogger(TheWorkClient.class); @Override @@ -28,4 +33,12 @@ public void onInitializeClient() { TheWorkClientNetworking.initialize(); BlockRenderLayerMap.INSTANCE.putBlock(TheWorkBlocks.ALCHEMY_JAR_BLOCK, RenderLayer.getTranslucent()); } + + public static double getTime() { + var world = MinecraftClient.getInstance().world; + + if (world == null) + return 0; + return (world.getTime() + MinecraftClient.getInstance().getTickDelta()) / 20.0f; + } } \ No newline at end of file diff --git a/src/client/java/cassunshine/thework/rendering/blockentities/alchemy_block/AlchemyCircleBlockEntityRenderer.java b/src/client/java/cassunshine/thework/rendering/blockentities/alchemy_block/AlchemyCircleBlockEntityRenderer.java index 6fb25d1..47afc48 100644 --- a/src/client/java/cassunshine/thework/rendering/blockentities/alchemy_block/AlchemyCircleBlockEntityRenderer.java +++ b/src/client/java/cassunshine/thework/rendering/blockentities/alchemy_block/AlchemyCircleBlockEntityRenderer.java @@ -1,5 +1,6 @@ package cassunshine.thework.rendering.blockentities.alchemy_block; +import cassunshine.thework.TheWorkClient; import cassunshine.thework.TheWorkMod; import cassunshine.thework.alchemy.circle.AlchemyCircle; import cassunshine.thework.alchemy.circle.node.AlchemyNode; @@ -7,9 +8,12 @@ import cassunshine.thework.alchemy.circle.node.type.AlchemyNodeTypes; import cassunshine.thework.alchemy.circle.ring.AlchemyRing; import cassunshine.thework.blockentities.alchemycircle.AlchemyCircleBlockEntity; +import cassunshine.thework.blocks.TheWorkBlocks; import cassunshine.thework.rendering.blockentities.alchemy_block.nodes.AlchemyNodeTypeRenderers; import cassunshine.thework.rendering.util.RenderingUtilities; import cassunshine.thework.utils.TheWorkUtils; +import com.google.common.hash.HashCode; +import net.minecraft.client.MinecraftClient; import net.minecraft.client.render.LightmapTextureManager; import net.minecraft.client.render.OverlayTexture; import net.minecraft.client.render.RenderLayer; @@ -17,6 +21,7 @@ import net.minecraft.client.render.block.entity.BlockEntityRenderer; import net.minecraft.client.render.block.entity.BlockEntityRendererFactory; import net.minecraft.client.util.math.MatrixStack; +import net.minecraft.item.BlockItem; import net.minecraft.util.Identifier; import net.minecraft.util.math.MathHelper; import net.minecraft.world.LightType; @@ -68,7 +73,6 @@ public void render(AlchemyCircleBlockEntity entity, float tickDelta, MatrixStack RenderingUtilities.setupNormal(0, 1, 0); RenderingUtilities.setupColor(255, 255, 255, 255); - renderRandom.setSeed(entity.getPos().asLong()); try { //Offset to middle of block, and move up a little to prevent z-fighting. @@ -77,6 +81,8 @@ public void render(AlchemyCircleBlockEntity entity, float tickDelta, MatrixStack drawFullCircle(0.5f, 8); drawFullCircle(0.5f, 4); + renderRandom.setSeed(entity.getPos().asLong()); + drawCirclePips(0.5f + LINE_THICKNESS, 0, MathHelper.PI, 4, 1 / 8.0f, false); drawCirclePips(0.5f + LINE_THICKNESS, MathHelper.PI, MathHelper.TAU, 4, 1 / 8.0f, false); @@ -104,10 +110,13 @@ public void render(AlchemyCircleBlockEntity entity, float tickDelta, MatrixStack private void drawRing(AlchemyRing ring, AlchemyRing next) { + renderRandom.setSeed(Float.hashCode(ring.radius)); + var clockwise = ring.isClockwise; var nodeWidthAngle = MathHelper.lerp(0.5f / ring.circumference, 0, MathHelper.TAU); var spinMult = clockwise ? 1 : -1; + for (int i = 0; i < ring.nodes.length; i++) { var indexNext = ring.getNextNodeIndex(i); @@ -151,8 +160,21 @@ private void drawNode(AlchemyNode node) { drawFullCircle(0.5f, 8); //Render item - if (!node.heldStack.isEmpty()) - RenderingUtilities.renderItem(node.heldStack, node.ring.circle.blockEntity.getWorld(), LightmapTextureManager.MAX_LIGHT_COORDINATE, OverlayTexture.DEFAULT_UV); + if (!node.heldStack.isEmpty()) { + if (node.heldStack.getItem() instanceof BlockItem blockItem && blockItem.getBlock() == TheWorkBlocks.ALCHEMY_JAR_BLOCK) { + RenderingUtilities.translateMatrix(-0.5f, 0, -0.5f); + RenderingUtilities.renderBlock(TheWorkBlocks.ALCHEMY_JAR_BLOCK.getDefaultState(), LightmapTextureManager.MAX_LIGHT_COORDINATE, OverlayTexture.DEFAULT_UV); + } else { + renderRandom.setSeed(node.getPosition().hashCode()); + float time = (float) TheWorkClient.getTime(); + time += renderRandom.nextFloat(MathHelper.TAU); + + RenderingUtilities.translateMatrix(0, MathHelper.sin((time * 2) % MathHelper.TAU) * 0.1f, 0); + RenderingUtilities.rotateMatrix(0, time * 2.0f, 0); + + RenderingUtilities.renderItem(node.heldStack, node.ring.circle.blockEntity.getWorld(), LightmapTextureManager.MAX_LIGHT_COORDINATE, OverlayTexture.DEFAULT_UV); + } + } //Run custom renderer var customRenderer = AlchemyNodeTypeRenderers.get(node.nodeType); diff --git a/src/client/java/cassunshine/thework/rendering/blockentities/alchemy_block/nodes/RuneAlchemyNodeTypeRenderer.java b/src/client/java/cassunshine/thework/rendering/blockentities/alchemy_block/nodes/RuneAlchemyNodeTypeRenderer.java index 49f6f1c..c45e418 100644 --- a/src/client/java/cassunshine/thework/rendering/blockentities/alchemy_block/nodes/RuneAlchemyNodeTypeRenderer.java +++ b/src/client/java/cassunshine/thework/rendering/blockentities/alchemy_block/nodes/RuneAlchemyNodeTypeRenderer.java @@ -12,7 +12,7 @@ public class RuneAlchemyNodeTypeRenderer extends AlchemyNodeTypeRenderer { @Override public void render(AlchemyNode node) { var sprite = node.rune; - if (sprite == null || sprite == AlchemyNode.NULL_RUNE) + if (sprite == null || node.rune.equals(AlchemyNode.NULL_RUNE)) return; //Modify rune to point to rune texture. diff --git a/src/main/java/cassunshine/thework/alchemy/circle/AlchemyCircle.java b/src/main/java/cassunshine/thework/alchemy/circle/AlchemyCircle.java index 6cdc7cd..a669a7b 100644 --- a/src/main/java/cassunshine/thework/alchemy/circle/AlchemyCircle.java +++ b/src/main/java/cassunshine/thework/alchemy/circle/AlchemyCircle.java @@ -53,6 +53,7 @@ public void addRing(float radius) { if (radiusDifference < 1) { rings.remove(i); + blockEntity.regenerateInteractionPoints(); return; } } @@ -63,6 +64,8 @@ public void addRing(float radius) { rings.add(ring); sortRings(); + + blockEntity.regenerateInteractionPoints(); } @@ -97,6 +100,8 @@ public void readNbt(NbtCompound nbt) { rings.add(newRing); } + + sortRings(); } @Override @@ -143,4 +148,10 @@ public TheWorkNetworkEvent generateInteractEvent(ItemUsageContext context) { return TheWorkNetworkEvents.NONE; } + + @Override + public void regenerateInteractionPoints(AlchemyCircleBlockEntity blockEntity) { + for (AlchemyRing ring : rings) + ring.regenerateInteractionPoints(blockEntity); + } } diff --git a/src/main/java/cassunshine/thework/alchemy/circle/AlchemyCircleComponent.java b/src/main/java/cassunshine/thework/alchemy/circle/AlchemyCircleComponent.java index 310ad53..d0f5b01 100644 --- a/src/main/java/cassunshine/thework/alchemy/circle/AlchemyCircleComponent.java +++ b/src/main/java/cassunshine/thework/alchemy/circle/AlchemyCircleComponent.java @@ -1,5 +1,6 @@ package cassunshine.thework.alchemy.circle; +import cassunshine.thework.blockentities.alchemycircle.AlchemyCircleBlockEntity; import cassunshine.thework.network.events.TheWorkNetworkEvent; import net.minecraft.item.ItemUsageContext; import net.minecraft.nbt.NbtCompound; @@ -13,4 +14,6 @@ public interface AlchemyCircleComponent { TheWorkNetworkEvent generateChalkEvent(ItemUsageContext context); TheWorkNetworkEvent generateInteractEvent(ItemUsageContext context); + + void regenerateInteractionPoints(AlchemyCircleBlockEntity blockEntity); } diff --git a/src/main/java/cassunshine/thework/alchemy/circle/events/node/AlchemyNodeSetItem.java b/src/main/java/cassunshine/thework/alchemy/circle/events/node/AlchemyNodeSetItem.java new file mode 100644 index 0000000..b83cef6 --- /dev/null +++ b/src/main/java/cassunshine/thework/alchemy/circle/events/node/AlchemyNodeSetItem.java @@ -0,0 +1,45 @@ +package cassunshine.thework.alchemy.circle.events.node; + +import cassunshine.thework.TheWorkMod; +import cassunshine.thework.alchemy.circle.node.AlchemyNode; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NbtCompound; +import net.minecraft.network.PacketByteBuf; +import net.minecraft.util.Identifier; + +public class AlchemyNodeSetItem extends AlchemyNodeEvent { + public static final Identifier IDENTIFIER = new Identifier(TheWorkMod.ModID, "node_set_item"); + + public ItemStack stack; + + public AlchemyNodeSetItem() { + super(IDENTIFIER); + } + + public AlchemyNodeSetItem(ItemStack stack, AlchemyNode node) { + super(node, IDENTIFIER); + + this.stack = stack.copy(); + } + + @Override + public void writePacket(PacketByteBuf buf) { + super.writePacket(buf); + + buf.writeNbt(stack.writeNbt(new NbtCompound())); + } + + @Override + public void readPacket(PacketByteBuf buf) { + super.readPacket(buf); + + stack = ItemStack.fromNbt(buf.readNbt()); + } + + @Override + public void applyToNode(AlchemyNode node) { + super.applyToNode(node); + + node.heldStack = stack; + } +} diff --git a/src/main/java/cassunshine/thework/alchemy/circle/node/AlchemyNode.java b/src/main/java/cassunshine/thework/alchemy/circle/node/AlchemyNode.java index ec750a4..c636fed 100644 --- a/src/main/java/cassunshine/thework/alchemy/circle/node/AlchemyNode.java +++ b/src/main/java/cassunshine/thework/alchemy/circle/node/AlchemyNode.java @@ -2,11 +2,14 @@ import cassunshine.thework.TheWorkMod; import cassunshine.thework.alchemy.circle.AlchemyCircleComponent; +import cassunshine.thework.alchemy.circle.events.node.AlchemyNodeSetItem; import cassunshine.thework.alchemy.circle.events.node.AlchemyNodeSetTypeAndRune; import cassunshine.thework.alchemy.circle.node.type.AlchemyNodeType; import cassunshine.thework.alchemy.circle.node.type.AlchemyNodeTypes; import cassunshine.thework.alchemy.circle.ring.AlchemyRing; +import cassunshine.thework.blockentities.alchemycircle.AlchemyCircleBlockEntity; import cassunshine.thework.elements.inventory.ElementInventory; +import cassunshine.thework.entities.InteractionPointEntity; import cassunshine.thework.network.events.TheWorkNetworkEvent; import cassunshine.thework.network.events.TheWorkNetworkEvents; import cassunshine.thework.utils.TheWorkUtils; @@ -49,6 +52,10 @@ public class AlchemyNode implements AlchemyCircleComponent { */ public AlchemyNodeType.Data typeData = AlchemyNodeType.Data.NONE; + /** + * Interaction point entity for nodes that hold items + */ + public InteractionPointEntity interactionPoint; /** * Determines if the node should output to the next path in the sequence. @@ -77,19 +84,14 @@ public float getAngle() { } public Vec3d getPosition() { - return ring.circle.blockEntity.fullPosition.add( - MathHelper.sin(getAngle()) * ring.radius, - 0, - MathHelper.cos(getAngle()) * ring.radius - ); + return ring.circle.blockEntity.fullPosition.add(MathHelper.sin(getAngle()) * ring.radius, 0, MathHelper.cos(getAngle()) * ring.radius); } private String[] getBookPages(ItemUsageContext context) { var offHand = context.getHand() == Hand.MAIN_HAND ? Hand.OFF_HAND : Hand.MAIN_HAND; var stack = context.getPlayer().getStackInHand(offHand); - if (stack.isEmpty() || stack.getItem() != Items.WRITABLE_BOOK || !stack.hasNbt()) - return null; + if (stack.isEmpty() || stack.getItem() != Items.WRITABLE_BOOK || !stack.hasNbt()) return null; var bookNbt = stack.getNbt(); var list = bookNbt.getList("pages", NbtElement.STRING_TYPE); @@ -107,10 +109,17 @@ private String[] getBookPages(ItemUsageContext context) { public void setTypeAndRune(Identifier type, Identifier rune) { var newType = AlchemyNodeTypes.get(type); - if (newType == nodeType && this.rune == rune) - return; + if (newType == nodeType && this.rune == rune) return; + + //Only spawn an interaction entity if the type requires, and there is no rune set. + if (newType.holdsItems && rune.equals(NULL_RUNE)) { + if (interactionPoint == null) interactionPoint = ring.circle.blockEntity.addInteractionPoint(getPosition().add(0, ring.circle.blockEntity.getPos().getY() + 1 / 64.0f, 0)); + } else { + if (interactionPoint != null) interactionPoint = ring.circle.blockEntity.removeInteractionPoint(interactionPoint); + } - if (!heldStack.isEmpty()) { + //Pop off any existing items. + if (!heldStack.isEmpty() && interactionPoint == null) { var pos = getPosition(); TheWorkUtils.dropItem(ring.circle.blockEntity.getWorld(), heldStack, (float) pos.x, (float) ring.circle.blockEntity.getPos().getY() + 0.5f, (float) pos.z); } @@ -119,6 +128,26 @@ public void setTypeAndRune(Identifier type, Identifier rune) { this.rune = rune; } + public boolean isInteractionInRange(ItemUsageContext context) { + var interactPos = context.getHitPos().withAxis(Direction.Axis.Y, 0); + var pos = getPosition(); + + return interactPos.distanceTo(pos) < 0.7f; + } + + private TheWorkNetworkEvent swapItemWithPlayer(ItemUsageContext context) { + var hand = context.getHand(); + var stack = context.getPlayer().getStackInHand(hand); + + //If both items are empty, do nothing. + if ((stack.isEmpty() && heldStack.isEmpty())) + return TheWorkNetworkEvents.NONE; + + context.getPlayer().setStackInHand(hand, heldStack); + + return new AlchemyNodeSetItem(stack, this); + } + @Override public NbtCompound writeNbt(NbtCompound nbt) { nbt.putString("type", nodeType.id.toString()); @@ -148,34 +177,26 @@ public void readNbt(NbtCompound nbt) { @Override public TheWorkNetworkEvent generateChalkEvent(ItemUsageContext context) { - var interactPos = context.getHitPos().withAxis(Direction.Axis.Y, 0); - var pos = getPosition(); - - var length = interactPos.distanceTo(pos); - - if (interactPos.distanceTo(pos) > 0.7f) - return TheWorkNetworkEvents.NONE; + if (!isInteractionInRange(context)) return TheWorkNetworkEvents.NONE; //Get all pages in held book. var pages = getBookPages(context); - if (pages == null || pages.length == 0) - return TheWorkNetworkEvents.NONE; + if (pages == null || pages.length == 0) return TheWorkNetworkEvents.NONE; //Try to parse identifiers from pages. ArrayList identifiers = new ArrayList<>(); for (var page : pages) { var id = Identifier.tryParse(page); - if (id != null) - identifiers.add(id); + if (id.getPath().isEmpty()) continue; - if (identifiers.size() == 2) - break; + if (id != null) identifiers.add(id); + + if (identifiers.size() == 2) break; } - if (identifiers.isEmpty()) - return TheWorkNetworkEvents.NONE; + if (identifiers.isEmpty()) return TheWorkNetworkEvents.NONE; Identifier[] ids = new Identifier[2]; @@ -188,15 +209,25 @@ public TheWorkNetworkEvent generateChalkEvent(ItemUsageContext context) { ids[1] = identifiers.get(1); } - if (ids[0].equals(nodeType.id) && ids[1].equals(rune)) - return new AlchemyNodeSetTypeAndRune(AlchemyNodeTypes.NONE.id, NULL_RUNE, this); + if (ids[0].equals(nodeType.id) && ids[1].equals(rune)) return new AlchemyNodeSetTypeAndRune(AlchemyNodeTypes.NONE.id, NULL_RUNE, this); return new AlchemyNodeSetTypeAndRune(ids[0], ids[1], this); } @Override public TheWorkNetworkEvent generateInteractEvent(ItemUsageContext context) { + if (!isInteractionInRange(context)) return TheWorkNetworkEvents.NONE; + + //If the type holds items, swap item with player item. + if (nodeType.holdsItems) + return swapItemWithPlayer(context); + return TheWorkNetworkEvents.NONE; } + + @Override + public void regenerateInteractionPoints(AlchemyCircleBlockEntity blockEntity) { + if (nodeType.holdsItems) interactionPoint = blockEntity.addInteractionPoint(getPosition().add(0, blockEntity.getPos().getY() + 1 / 64.0f, 0)); + } } diff --git a/src/main/java/cassunshine/thework/alchemy/circle/node/type/AlchemyNodeType.java b/src/main/java/cassunshine/thework/alchemy/circle/node/type/AlchemyNodeType.java index 036904a..b72ac5b 100644 --- a/src/main/java/cassunshine/thework/alchemy/circle/node/type/AlchemyNodeType.java +++ b/src/main/java/cassunshine/thework/alchemy/circle/node/type/AlchemyNodeType.java @@ -7,6 +7,8 @@ public class AlchemyNodeType { public Identifier id; + public boolean holdsItems = false; + public void activate(AlchemyNode node) { } @@ -23,6 +25,11 @@ public AlchemyNodeType.Data getData() { return Data.NONE; } + public AlchemyNodeType withItemHolding() { + this.holdsItems = true; + return this; + } + public abstract static class Data { diff --git a/src/main/java/cassunshine/thework/alchemy/circle/node/type/AlchemyNodeTypes.java b/src/main/java/cassunshine/thework/alchemy/circle/node/type/AlchemyNodeTypes.java index d562071..1986703 100644 --- a/src/main/java/cassunshine/thework/alchemy/circle/node/type/AlchemyNodeTypes.java +++ b/src/main/java/cassunshine/thework/alchemy/circle/node/type/AlchemyNodeTypes.java @@ -11,7 +11,7 @@ public class AlchemyNodeTypes { public static final AlchemyNodeType NONE = register(new Identifier(TheWorkMod.ModID, "none"), new AlchemyNodeType()); - public static final AlchemyNodeType DECONSTRUCT = register(new Identifier(TheWorkMod.ModID, "deconstruct"), new DeconstructNodeType()); + public static final AlchemyNodeType DECONSTRUCT = register(new Identifier(TheWorkMod.ModID, "deconstruct"), new DeconstructNodeType().withItemHolding()); public static void initialize() { diff --git a/src/main/java/cassunshine/thework/alchemy/circle/path/AlchemyPath.java b/src/main/java/cassunshine/thework/alchemy/circle/path/AlchemyPath.java index ba9761e..89caa3d 100644 --- a/src/main/java/cassunshine/thework/alchemy/circle/path/AlchemyPath.java +++ b/src/main/java/cassunshine/thework/alchemy/circle/path/AlchemyPath.java @@ -2,6 +2,7 @@ import cassunshine.thework.alchemy.circle.AlchemyCircleComponent; import cassunshine.thework.alchemy.circle.ring.AlchemyRing; +import cassunshine.thework.blockentities.alchemycircle.AlchemyCircleBlockEntity; import cassunshine.thework.elements.Element; import cassunshine.thework.elements.Elements; import cassunshine.thework.network.events.TheWorkNetworkEvent; @@ -136,4 +137,9 @@ public TheWorkNetworkEvent generateChalkEvent(ItemUsageContext context) { public TheWorkNetworkEvent generateInteractEvent(ItemUsageContext context) { return TheWorkNetworkEvents.NONE; } + + @Override + public void regenerateInteractionPoints(AlchemyCircleBlockEntity blockEntity) { + + } } diff --git a/src/main/java/cassunshine/thework/alchemy/circle/ring/AlchemyRing.java b/src/main/java/cassunshine/thework/alchemy/circle/ring/AlchemyRing.java index 1d5387c..b37da8a 100644 --- a/src/main/java/cassunshine/thework/alchemy/circle/ring/AlchemyRing.java +++ b/src/main/java/cassunshine/thework/alchemy/circle/ring/AlchemyRing.java @@ -6,6 +6,7 @@ import cassunshine.thework.alchemy.circle.events.ring.AlchemyRingClockwiseSet; import cassunshine.thework.alchemy.circle.node.AlchemyNode; import cassunshine.thework.alchemy.circle.path.AlchemyPath; +import cassunshine.thework.blockentities.alchemycircle.AlchemyCircleBlockEntity; import cassunshine.thework.network.events.TheWorkNetworkEvent; import cassunshine.thework.network.events.TheWorkNetworkEvents; import net.minecraft.item.ItemUsageContext; @@ -105,8 +106,7 @@ public int getNextNodeIndex(int i) { } public AlchemyNode getNode(int i) { - if (i < 0) - i += nodes.length; + if (i < 0) i += nodes.length; return nodes[i % nodes.length]; } @@ -150,8 +150,7 @@ public TheWorkNetworkEvent generateChalkEvent(ItemUsageContext context) { //Pass to nodes first. for (AlchemyNode node : nodes) { var nodeEvent = node.generateChalkEvent(context); - if (nodeEvent != TheWorkNetworkEvents.NONE) - return nodeEvent; + if (nodeEvent != TheWorkNetworkEvents.NONE) return nodeEvent; } var flatHitPos = context.getHitPos().withAxis(Direction.Axis.Y, 0); @@ -160,15 +159,23 @@ public TheWorkNetworkEvent generateChalkEvent(ItemUsageContext context) { var relativeRadius = hitRadius - radius; //If chalk hit point is too far, do nothing. - if (Math.abs(relativeRadius) > 1.0f) - return TheWorkNetworkEvents.NONE; + if (Math.abs(relativeRadius) > 1.0f) return TheWorkNetworkEvents.NONE; return new AlchemyRingClockwiseSet(relativeRadius >= 0, this); } @Override public TheWorkNetworkEvent generateInteractEvent(ItemUsageContext context) { + for (AlchemyNode node : nodes) { + var event = node.generateInteractEvent(context); + if (event != TheWorkNetworkEvents.NONE) return event; + } return TheWorkNetworkEvents.NONE; } + @Override + public void regenerateInteractionPoints(AlchemyCircleBlockEntity blockEntity) { + for (AlchemyNode node : nodes) + node.regenerateInteractionPoints(blockEntity); + } } diff --git a/src/main/java/cassunshine/thework/blockentities/alchemycircle/AlchemyCircleBlockEntity.java b/src/main/java/cassunshine/thework/blockentities/alchemycircle/AlchemyCircleBlockEntity.java index bc79ee9..a29c0ae 100644 --- a/src/main/java/cassunshine/thework/blockentities/alchemycircle/AlchemyCircleBlockEntity.java +++ b/src/main/java/cassunshine/thework/blockentities/alchemycircle/AlchemyCircleBlockEntity.java @@ -4,12 +4,14 @@ import cassunshine.thework.alchemy.circle.ring.AlchemyRing; import cassunshine.thework.blockentities.TheWorkBlockEntities; import cassunshine.thework.blocks.AlchemyCircleBlock; +import cassunshine.thework.entities.InteractionPointEntity; import cassunshine.thework.items.TheWorkItems; import cassunshine.thework.network.events.TheWorkNetworkEvent; import cassunshine.thework.network.events.TheWorkNetworkEvents; import net.minecraft.block.BlockState; import net.minecraft.block.FenceBlock; import net.minecraft.block.entity.BlockEntity; +import net.minecraft.entity.Entity; import net.minecraft.item.ItemUsage; import net.minecraft.item.ItemUsageContext; import net.minecraft.nbt.NbtCompound; @@ -30,6 +32,10 @@ public class AlchemyCircleBlockEntity extends BlockEntity { */ private static final HashMap> LOADED = new HashMap<>(); + private final ArrayList interactionPoints = new ArrayList<>(); + private final ArrayList newPoints = new ArrayList<>(); + + public final Vec3d fullPosition; public final AlchemyCircle circle; @@ -44,12 +50,50 @@ public AlchemyCircleBlockEntity(BlockPos pos, BlockState state) { public static void tick(World world, BlockPos pos, BlockState blockState, AlchemyCircleBlockEntity blockEntity) { + + //Update new block entities. + for (InteractionPointEntity newPoint : blockEntity.newPoints) + newPoint.setCircle(blockEntity); + blockEntity.newPoints.clear(); + if (!blockEntity.circle.isActive) return; var circle = blockEntity.circle; } + public void regenerateInteractionPoints() { + //Clear all previous interaction points. + for (InteractionPointEntity point : interactionPoints) + point.remove(Entity.RemovalReason.DISCARDED); + interactionPoints.clear(); + + //Generate entirely new ones. + circle.regenerateInteractionPoints(this); + } + + public InteractionPointEntity addInteractionPoint(Vec3d position) { + if (getWorld() == null) + return null; + + var point = new InteractionPointEntity(null, getWorld()); + point.setPosition(position); + + interactionPoints.add(point); + getWorld().spawnEntity(point); + + newPoints.add(point); + + return point; + } + + public InteractionPointEntity removeInteractionPoint(InteractionPointEntity toRemove) { + if (interactionPoints.remove(toRemove)) + toRemove.remove(Entity.RemovalReason.DISCARDED); + + return null; + } + @Override protected void writeNbt(NbtCompound nbt) { super.writeNbt(nbt); @@ -78,6 +122,8 @@ public void setWorld(World world) { synchronized (LOADED) { LOADED.computeIfAbsent(world, id -> new ArrayList<>()).add(this); } + + regenerateInteractionPoints(); } @Override @@ -90,6 +136,10 @@ public void markRemoved() { list.remove(this); if (list.isEmpty()) LOADED.remove(world); } + + for (InteractionPointEntity point : interactionPoints) + point.remove(Entity.RemovalReason.DISCARDED); + interactionPoints.clear(); } //Handles interaction with the alchemy circle given a context. diff --git a/src/main/java/cassunshine/thework/network/events/TheWorkNetworkEvents.java b/src/main/java/cassunshine/thework/network/events/TheWorkNetworkEvents.java index e0de7c4..996903c 100644 --- a/src/main/java/cassunshine/thework/network/events/TheWorkNetworkEvents.java +++ b/src/main/java/cassunshine/thework/network/events/TheWorkNetworkEvents.java @@ -2,6 +2,7 @@ import cassunshine.thework.TheWorkMod; import cassunshine.thework.alchemy.circle.events.circle.AddRingEvent; +import cassunshine.thework.alchemy.circle.events.node.AlchemyNodeSetItem; import cassunshine.thework.alchemy.circle.events.node.AlchemyNodeSetTypeAndRune; import cassunshine.thework.alchemy.circle.events.ring.AlchemyRingClockwiseSet; import net.fabricmc.fabric.api.networking.v1.PacketByteBufs; @@ -29,7 +30,7 @@ public static void initialize() { register(AddRingEvent.IDENTIFIER, AddRingEvent::new); register(AlchemyRingClockwiseSet.IDENTIFIER, AlchemyRingClockwiseSet::new); register(AlchemyNodeSetTypeAndRune.IDENTIFIER, AlchemyNodeSetTypeAndRune::new); - + register(AlchemyNodeSetItem.IDENTIFIER, AlchemyNodeSetItem::new); }