Skip to content

Commit

Permalink
Rotational connector arrows
Browse files Browse the repository at this point in the history
  • Loading branch information
gdavid04 committed Mar 7, 2024
1 parent 1f9e77f commit 5a04a56
Show file tree
Hide file tree
Showing 3 changed files with 94 additions and 20 deletions.
2 changes: 2 additions & 0 deletions src/main/java/gdavid/phi/spell/connector/BridgeConnector.java
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ public void drawParams(PoseStack ms, MultiBufferSource buffers, int light) {
@OnlyIn(Dist.CLIENT)
public void drawLine(PoseStack ms, MultiBufferSource buffers, int light, Side side) {
if (!side.isEnabled()) return;
/* TODO fix before 1.19 release
GlStateManager._enableBlend();
GlStateManager.glBlendFuncSeparate(SourceFactor.SRC_ALPHA.value, DestFactor.ONE_MINUS_SRC_ALPHA.value,
SourceFactor.ZERO.value, SourceFactor.ONE.value);
Expand Down Expand Up @@ -136,6 +137,7 @@ public void drawLine(PoseStack ms, MultiBufferSource buffers, int light, Side si
buffer.vertex(mat, -8, -8, 0).color(r, g, b, a);
buffer.uv(minU, minV).uv2(light).endVertex();
GlStateManager._disableBlend();
*/
}

@Override
Expand Down
58 changes: 38 additions & 20 deletions src/main/java/gdavid/phi/spell/connector/ClockwiseConnector.java
Original file line number Diff line number Diff line change
@@ -1,20 +1,19 @@
package gdavid.phi.spell.connector;

import com.mojang.blaze3d.vertex.PoseStack;
import com.mojang.blaze3d.vertex.VertexConsumer;
import gdavid.phi.util.EvalHelper;
import gdavid.phi.util.SpellCachedView;
import net.minecraft.client.renderer.MultiBufferSource;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import vazkii.psi.api.spell.EnumPieceType;
import vazkii.psi.api.spell.EnumSpellStat;
import vazkii.psi.api.spell.IGenericRedirector;
import vazkii.psi.api.spell.Spell;
import vazkii.psi.api.spell.SpellCompilationException;
import vazkii.psi.api.spell.SpellContext;
import vazkii.psi.api.spell.SpellMetadata;
import vazkii.psi.api.PsiAPI;
import vazkii.psi.api.spell.*;
import vazkii.psi.api.spell.SpellParam.Any;
import vazkii.psi.api.spell.SpellParam.ArrowType;
import vazkii.psi.api.spell.SpellParam.Side;
import vazkii.psi.api.spell.SpellPiece;
import vazkii.psi.api.spell.SpellRuntimeException;

import java.util.*;

public class ClockwiseConnector extends SpellPiece implements IGenericRedirector {

Expand Down Expand Up @@ -42,15 +41,24 @@ public Side reverseSide(Side side) {
@Override
@OnlyIn(Dist.CLIENT)
public void drawParams(PoseStack ms, MultiBufferSource buffers, int light) {
// TODO fix this when there's an API that doesn't require a registered
// SpellParam
/*
* for (SpellParam.Side side : SpellParam.Side.values()) { if (!side.isEnabled()
* || !spell.grid.getPieceAtSideSafely(x, y,
* side).isInputSide(side.getOpposite())) { continue; } RenderHelper.param(ms,
* buffers, light, SpellParam.GRAY, ArrowType.IN, remapSide(side.getOpposite()),
* this); }
*/
VertexConsumer buffer = buffers.getBuffer(PsiAPI.internalHandler.getProgrammerLayer());
for (Side side : SpellParam.Side.values()) {
if (!isInputSide(side)) continue;
int index = 0, count = 1;
SpellPiece neighbour = spell.grid.getPieceAtSideSafely(x, y, side);
if (neighbour != null) {
int nbcount = neighbour.getParamArrowCount(side.getOpposite());
if (side.asInt() > side.getOpposite().asInt()) index += nbcount;
count += nbcount;
}
float percent = count > 1 ? (float) index / (count - 1) : 0.5f;
drawParam(ms, buffer, light, side, SpellParam.GRAY, ArrowType.IN, percent);
}
}

@Override
public int getParamArrowCount(Side side) {
return isInputSide(side) ? 1 : 0;
}

@Override
Expand Down Expand Up @@ -78,10 +86,20 @@ public Object execute(SpellContext context) throws SpellRuntimeException {
return null;
}

// Cache input sides to avoid recalculating them multiple times every frame
private final SpellCachedView<Set<Side>> isInputSideView = new SpellCachedView<>(this, () -> {
var res = new HashSet<Side>();
for (Side side : Side.values()) {
if (!side.isEnabled()) continue;
SpellPiece piece = spell.grid.getPieceAtSideSafely(x, y, reverseSide(side).getOpposite());
if (piece != null && piece.isInputSide(reverseSide(side))) res.add(side);
}
return res;
}, Collections::emptySet);

@Override
public boolean isInputSide(Side side) {
// No recursive check to avoid dealing with infinite loops
return spell.grid.getPieceAtSideSafely(x, y, reverseSide(side)) != null;
return isInputSideView.get().contains(side);
}

}
54 changes: 54 additions & 0 deletions src/main/java/gdavid/phi/util/SpellCachedView.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package gdavid.phi.util;

import org.jetbrains.annotations.NotNull;
import vazkii.psi.api.spell.SpellPiece;

import java.util.UUID;
import java.util.function.Supplier;

/**
* Caches a value so it's only computed once for a spell.
* This is useful for things that are expensive to compute but only change when the spell changes, such as loop checks.
*/
public class SpellCachedView<T> {

private final SpellPiece owner;
private UUID lastSpellUUID = null;
private final Supplier<? extends T> supplier, fallbackSupplier;
private boolean updating = false;
private T value;

public SpellCachedView(@NotNull SpellPiece owner, @NotNull Supplier<? extends T> supplier) {
this(owner, supplier, () -> { throw new SelfReferentialException(owner); });
}

public SpellCachedView(@NotNull SpellPiece owner, @NotNull Supplier<? extends T> supplier, @NotNull Supplier<? extends T> fallbackSupplier) {
this.owner = owner;
this.supplier = supplier;
this.fallbackSupplier = fallbackSupplier;
}

public T get() throws SelfReferentialException {
if (lastSpellUUID == null || !lastSpellUUID.equals(owner.spell.uuid)) {
// Return a fallback value in case of self-reference
if (updating) return fallbackSupplier.get();
updating = true;
value = supplier.get();
lastSpellUUID = owner.spell.uuid;
updating = false;
}
return value;
}

public static class SelfReferentialException extends IllegalStateException {

public final SpellPiece piece;

public SelfReferentialException(SpellPiece owner) {
super("Self-referential SpellCachedView evaluation in " + owner);
piece = owner;
}

}

}

0 comments on commit 5a04a56

Please sign in to comment.