Skip to content

Commit

Permalink
-re-add alchemy nodes having an item slot
Browse files Browse the repository at this point in the history
  • Loading branch information
Cassunshine committed Feb 10, 2024
1 parent bee5ec1 commit 778e0ee
Show file tree
Hide file tree
Showing 13 changed files with 235 additions and 39 deletions.
13 changes: 13 additions & 0 deletions src/client/java/cassunshine/thework/TheWorkClient.java
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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;
}
}
Original file line number Diff line number Diff line change
@@ -1,22 +1,27 @@
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;
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.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;
import net.minecraft.client.render.VertexConsumerProvider;
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;
Expand Down Expand Up @@ -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.
Expand All @@ -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);

Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ public void addRing(float radius) {

if (radiusDifference < 1) {
rings.remove(i);
blockEntity.regenerateInteractionPoints();
return;
}
}
Expand All @@ -63,6 +64,8 @@ public void addRing(float radius) {

rings.add(ring);
sortRings();

blockEntity.regenerateInteractionPoints();
}


Expand Down Expand Up @@ -97,6 +100,8 @@ public void readNbt(NbtCompound nbt) {

rings.add(newRing);
}

sortRings();
}

@Override
Expand Down Expand Up @@ -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);
}
}
Original file line number Diff line number Diff line change
@@ -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;
Expand All @@ -13,4 +14,6 @@ public interface AlchemyCircleComponent {
TheWorkNetworkEvent generateChalkEvent(ItemUsageContext context);

TheWorkNetworkEvent generateInteractEvent(ItemUsageContext context);

void regenerateInteractionPoints(AlchemyCircleBlockEntity blockEntity);
}
Original file line number Diff line number Diff line change
@@ -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;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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);
Expand All @@ -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);
}
Expand All @@ -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());
Expand Down Expand Up @@ -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<Identifier> 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];

Expand All @@ -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));
}
}

Loading

0 comments on commit 778e0ee

Please sign in to comment.