Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Metaprogramming Stuff #14

Merged
merged 14 commits into from
Jul 7, 2024
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@ protected void init() {
super.init();

partWidget = new SpellPartWidget(
handler.spell.get(), width / 2d, height / 2d, 64, handler::updateSpell,
handler.spell.get(), width / 2d, height / 2d, 64,
handler::updateSpell, handler::updateOtherHandSpell,
handler.otherHandSpell::get, handler::executeOffhand
);
handler.replacerCallback = frag -> partWidget.replaceCallback(frag);
Expand Down
85 changes: 49 additions & 36 deletions src/client/java/dev/enjarai/trickster/screen/SpellPartWidget.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
import dev.enjarai.trickster.Trickster;
import dev.enjarai.trickster.render.SpellCircleRenderer;
import dev.enjarai.trickster.spell.*;
import dev.enjarai.trickster.spell.fragment.ListFragment;
import dev.enjarai.trickster.spell.fragment.NumberFragment;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.gui.*;
import net.minecraft.client.gui.screen.narration.NarrationMessageBuilder;
Expand All @@ -12,6 +14,7 @@
import org.jetbrains.annotations.Nullable;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Optional;
import java.util.function.Consumer;
Expand All @@ -30,6 +33,8 @@ public class SpellPartWidget extends AbstractParentElement implements Drawable,
public static final Pattern COPY_OFFHAND_LITERAL = Pattern.of(4, 0, 1, 4, 2, 1);
public static final Pattern COPY_OFFHAND_LITERAL_INNER = Pattern.of(1, 2, 4, 1, 0, 4, 7);
public static final Pattern COPY_OFFHAND_EXECUTE = Pattern.of(4, 3, 0, 4, 5, 2, 4, 1);
public static final Pattern WRITE_OFFHAND_ADDRESS = Pattern.of(1, 0, 4, 8, 7, 6, 4, 2, 1, 4);


private SpellPart spellPart;
// private List<SpellPartWidget> partWidgets;
Expand All @@ -42,6 +47,7 @@ public class SpellPartWidget extends AbstractParentElement implements Drawable,
private boolean isMutable = true;

private Consumer<SpellPart> updateListener;
private Consumer<SpellPart> otherHandSpellUpdateListener;
private Supplier<SpellPart> otherHandSpellSupplier;
@Nullable
private SpellPart toBeReplaced;
Expand All @@ -53,12 +59,13 @@ public class SpellPartWidget extends AbstractParentElement implements Drawable,

private final SpellCircleRenderer renderer;

public SpellPartWidget(SpellPart spellPart, double x, double y, double size, Consumer<SpellPart> updateListener, Supplier<SpellPart> otherHandSpellSupplier, Runnable initializeReplace) {
public SpellPartWidget(SpellPart spellPart, double x, double y, double size, Consumer<SpellPart> spellUpdateListener, Consumer<SpellPart> otherHandSpellUpdateListener, Supplier<SpellPart> otherHandSpellSupplier, Runnable initializeReplace) {
this.spellPart = spellPart;
this.x = x;
this.y = y;
this.size = size;
this.updateListener = updateListener;
this.updateListener = spellUpdateListener;
this.otherHandSpellUpdateListener = otherHandSpellUpdateListener;
this.otherHandSpellSupplier = otherHandSpellSupplier;
this.initializeReplace = initializeReplace;
this.renderer = new SpellCircleRenderer(() -> this.drawingPart, () -> this.drawingPattern);
Expand Down Expand Up @@ -264,48 +271,54 @@ protected void stopDrawing() {
if (drawingPart == spellPart) {
spellPart = newPart;
} else {
setSubPartInTree(drawingPart, Optional.of(newPart), spellPart, false);
drawingPart.setSubPartInTree(Optional.of(newPart), spellPart, false);
}
} else if (compiled.equals(CREATE_PARENT_GLYPH_GLYPH)) {
var newPart = new SpellPart();
newPart.glyph = drawingPart;
if (drawingPart == spellPart) {
spellPart = newPart;
} else {
setSubPartInTree(drawingPart, Optional.of(newPart), spellPart, false);
drawingPart.setSubPartInTree(Optional.of(newPart), spellPart, false);
}
} else if (compiled.equals(EXPAND_TO_OUTER_CIRCLE_GLYPH)) {
if (drawingPart != spellPart) {
if (spellPart.glyph == drawingPart) {
spellPart = drawingPart;
} else {
setSubPartInTree(drawingPart, Optional.of(drawingPart), spellPart, true);
drawingPart.setSubPartInTree(Optional.of(drawingPart), spellPart, true);
}
}
} else if (compiled.equals(DELETE_CIRCLE_GLYPH)) {
var firstSubpart = drawingPart.getSubParts().stream().filter(Optional::isPresent).map(Optional::get).findFirst();
if (drawingPart == spellPart) {
spellPart = firstSubpart.orElse(new SpellPart());
} else {
setSubPartInTree(drawingPart, firstSubpart, spellPart, false);
drawingPart.setSubPartInTree(firstSubpart, spellPart, false);
}
} else if (compiled.equals(DELETE_BRANCH_GLYPH)) {
if (drawingPart == spellPart) {
spellPart = new SpellPart();
} else {
setSubPartInTree(drawingPart, Optional.empty(), spellPart, false);
drawingPart.setSubPartInTree(Optional.empty(), spellPart, false);
}
} else if (compiled.equals(COPY_OFFHAND_LITERAL)) {
if (drawingPart == spellPart) {
spellPart = otherHandSpellSupplier.get().deepClone();
} else {
setSubPartInTree(drawingPart, Optional.of(otherHandSpellSupplier.get().deepClone()), spellPart, false);
drawingPart.setSubPartInTree(Optional.of(otherHandSpellSupplier.get().deepClone()), spellPart, false);
}
} else if (compiled.equals(COPY_OFFHAND_LITERAL_INNER)) {
drawingPart.glyph = otherHandSpellSupplier.get().deepClone();
} else if (compiled.equals(COPY_OFFHAND_EXECUTE)) {
toBeReplaced = drawingPart;
initializeReplace.run();
} else if (compiled.equals(WRITE_OFFHAND_ADDRESS)) {
var address = getAddress(spellPart, drawingPart);
if (address.isPresent()) {
var addressFragment = new ListFragment(address.get().stream().map(num -> (Fragment) new NumberFragment(num)).toList());
otherHandSpellUpdateListener.accept(new SpellPart(addressFragment, List.of()));
}
} else {
drawingPart.glyph = new PatternGlyph(compiled, drawingPattern);
tryReset = false;
Expand Down Expand Up @@ -338,39 +351,39 @@ public boolean isDrawing() {
return drawingPart != null;
}

protected boolean setSubPartInTree(SpellPart target, Optional<SpellPart> replacement, SpellPart current, boolean targetIsInner) {
if (current.glyph instanceof SpellPart part) {
if (targetIsInner ? part.glyph == target : part == target) {
if (replacement.isPresent()) {
current.glyph = replacement.get();
} else {
current.glyph = new PatternGlyph();
}
return true;
}

if (setSubPartInTree(target, replacement, part, targetIsInner)) {
return true;
}
protected Optional<List<Integer>> getAddress(SpellPart node, SpellPart target) {
var address = new LinkedList<Integer>();
var found = getAddress(node, target, address, new LinkedList<>());
if (found) {
return Optional.of(address);
} else {
return Optional.empty();
}
}

int i = 0;
for (var part : current.subParts) {
if (part.isPresent()) {
if (targetIsInner ? part.get().glyph == target : part.get() == target) {
if (replacement.isPresent()) {
current.subParts.set(i, replacement);
} else {
current.subParts.remove(i);
}
return true;
}
protected boolean getAddress(SpellPart node, SpellPart target, List<Integer> address, List<SpellPart> glyphSpells) {
if (node == target) {
return true;
}
if (node.glyph instanceof SpellPart glyph) {
glyphSpells.add(glyph);
}

if (setSubPartInTree(target, replacement, part.get(), targetIsInner)) {
return true;
var subParts = node.subParts;
if (subParts.stream().map(Optional::isPresent).findAny().isEmpty() && !address.isEmpty()) {
address.removeLast();
} else {
for (int i = 0; i < subParts.size(); i++) {
if (subParts.get(i).isPresent()) {
address.add(i);
var found = getAddress(subParts.get(i).get(), target, address, glyphSpells);
if (found) return true;
}
}
i++;
for (var glyph : glyphSpells) {
var found = getAddress(glyph, target, address, new LinkedList<>());
if (found) return true;
}
}

return false;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@

public class ScrollAndQuillScreenHandler extends ScreenHandler {
private final ItemStack scrollStack;
private final ItemStack otherHandStack;


public final SyncedProperty<SpellPart> spell = createProperty(SpellPart.class, SpellPart.ENDEC, new SpellPart());
public final SyncedProperty<SpellPart> otherHandSpell = createProperty(SpellPart.class, SpellPart.ENDEC, new SpellPart());
Expand All @@ -41,6 +43,8 @@ public ScrollAndQuillScreenHandler(int syncId, PlayerInventory playerInventory,
super(ModScreenHandlers.SCROLL_AND_QUILL, syncId);

this.scrollStack = scrollStack;
this.otherHandStack = otherHandStack;

this.slot = slot;
this.greedyEvaluation = greedyEvaluation;

Expand All @@ -61,6 +65,8 @@ public ScrollAndQuillScreenHandler(int syncId, PlayerInventory playerInventory,
this.isMutable.set(isMutable);

addServerboundMessage(SpellMessage.class, SpellMessage.ENDEC, msg -> updateSpell(msg.spell()));
addServerboundMessage(OtherHandSpellMessage.class, OtherHandSpellMessage.ENDEC, msg -> updateOtherHandSpell(msg.spell()));

addServerboundMessage(ExecuteOffhand.class, msg -> executeOffhand());
addClientboundMessage(Replace.class, Replace.ENDEC, msg -> {
if (replacerCallback != null) {
Expand Down Expand Up @@ -102,6 +108,24 @@ public void updateSpell(SpellPart spell) {
}
}

public void updateOtherHandSpell(SpellPart spell) {
if (isMutable.get()) {
if (otherHandStack != null) {
if (!otherHandStack.isEmpty()) {
var server = player().getServer();
if (server != null) {
server.execute(() -> {
otherHandStack.set(ModComponents.SPELL, new SpellComponent(spell));
otherHandSpell.set(spell);
});
}
}
} else {
sendMessage(new OtherHandSpellMessage(spell));
}
}
}

public void executeOffhand() {
var server = player().getServer();
if (server != null) {
Expand Down Expand Up @@ -134,6 +158,10 @@ public record SpellMessage(SpellPart spell) {
public static final Endec<SpellMessage> ENDEC = SpellPart.ENDEC.xmap(SpellMessage::new, SpellMessage::spell);
}

public record OtherHandSpellMessage(SpellPart spell) {
public static final Endec<OtherHandSpellMessage> ENDEC = SpellPart.ENDEC.xmap(OtherHandSpellMessage::new, OtherHandSpellMessage::spell);
}

public record ExecuteOffhand() {
}

Expand Down
38 changes: 38 additions & 0 deletions src/main/java/dev/enjarai/trickster/spell/SpellPart.java
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,44 @@ public void buildClosure(Map<Pattern, Fragment> replacements) {
}
}

public boolean setSubPartInTree(Optional<SpellPart> replacement, SpellPart current, boolean targetIsInner) {
if (current.glyph instanceof SpellPart part) {
if (targetIsInner ? part.glyph == this : part == this) {
if (replacement.isPresent()) {
current.glyph = replacement.get();
} else {
current.glyph = new PatternGlyph();
}
return true;
}

if (setSubPartInTree(replacement, part, targetIsInner)) {
return true;
}
}

int i = 0;
for (var part : current.subParts) {
if (part.isPresent()) {
if (targetIsInner ? part.get().glyph == this : part.get() == this) {
if (replacement.isPresent()) {
current.subParts.set(i, replacement);
} else {
current.subParts.remove(i);
}
return true;
}

if (setSubPartInTree(replacement, part.get(), targetIsInner)) {
return true;
}
}
i++;
}

return false;
}

public Fragment getGlyph() {
return glyph;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,16 @@

import com.google.common.collect.ImmutableList;
import com.mojang.serialization.MapCodec;
import dev.enjarai.trickster.Trickster;
import dev.enjarai.trickster.spell.Fragment;
import dev.enjarai.trickster.spell.tricks.Trick;
import dev.enjarai.trickster.spell.tricks.Tricks;
import dev.enjarai.trickster.spell.tricks.blunder.BlunderException;
import dev.enjarai.trickster.spell.tricks.blunder.IncompatibleTypesBlunder;
import dev.enjarai.trickster.spell.tricks.blunder.IncorrectFragmentBlunder;
import net.minecraft.text.Text;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

Expand Down Expand Up @@ -43,4 +47,22 @@ public BooleanFragment asBoolean() {
public ListFragment addRange(ListFragment other) throws BlunderException {
return new ListFragment(ImmutableList.<Fragment>builder().addAll(fragments).addAll(other.fragments).build());
}

public List<Integer> sanitizeAddress(Trick source) {
var sanitizedAddress = new ArrayList<Integer>();

for (Fragment fragment : this.fragments()) {
if (fragment instanceof NumberFragment index && index.isInteger()) {
sanitizedAddress.add((int) index.number());
} else {
throw new IncorrectFragmentBlunder(
source,
1,
Text.translatable(Trickster.MOD_ID + ".fragment." + Trickster.MOD_ID + "." + "integer_list"),
this);
}
}

return sanitizedAddress;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -87,4 +87,8 @@ public boolean equals(Object obj) {
}
return false;
}

public boolean isInteger() {
return number - Math.floor(number) == 0;
}
}
12 changes: 12 additions & 0 deletions src/main/java/dev/enjarai/trickster/spell/tricks/Tricks.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
import dev.enjarai.trickster.spell.tricks.func.SupplierTrick;
import dev.enjarai.trickster.spell.tricks.list.*;
import dev.enjarai.trickster.spell.tricks.math.*;
import dev.enjarai.trickster.spell.tricks.tree.*;
import dev.enjarai.trickster.spell.tricks.vector.*;
import net.minecraft.registry.Registry;
import net.minecraft.registry.RegistryKey;
Expand Down Expand Up @@ -116,6 +117,17 @@ public RegistryEntry.Reference<Trick> add(RegistryKey<Trick> key, Trick value, R
public static final ListRemoveElementTrick LIST_REMOVE_ELEMENT = register("list_remove_element", new ListRemoveElementTrick());
public static final ListRemoveTrick LIST_REMOVE = register("list_remove", new ListRemoveTrick());

// Tree
public static final LocateGlyphTrick LOCATE_GLYPH = register("locate_glyph", new LocateGlyphTrick());
public static final LocateGlyphsTrick LOCATE_GLYPHS = register("locate_glyphs", new LocateGlyphsTrick());
public static final RetrieveGlyphTrick RETRIEVE_GLYPH = register("retrieve_glyph", new RetrieveGlyphTrick());
public static final SetGlyphTrick SET_GLYPH = register("set_glyph", new SetGlyphTrick());
public static final RetrieveSubtreeTrick RETRIEVE_SUBTREE= register("retrieve_subtree", new RetrieveSubtreeTrick());
public static final SetSubtreeTrick SET_SUBTREE = register("set_subtree", new SetSubtreeTrick());
public static final AddSubtreeTrick ADD_LEAF = register("add_subtree", new AddSubtreeTrick());
public static final RemoveSubtreeTrick REMOVE_SUBTREE = register("remove_subtree", new RemoveSubtreeTrick());


// Events
public static final CreateSpellCircleTrick CREATE_SPELL_CIRCLE = register("create_spell_circle", new CreateSpellCircleTrick());
public static final DeleteSpellCircleTrick DELETE_SPELL_CIRCLE = register("delete_spell_circle", new DeleteSpellCircleTrick());
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package dev.enjarai.trickster.spell.tricks.blunder;

import dev.enjarai.trickster.spell.tricks.Trick;
import net.minecraft.text.MutableText;

import java.util.List;

public class AddressNotInTreeBlunder extends TrickBlunderException {
public final List<Integer> address;

public AddressNotInTreeBlunder(Trick source, List<Integer> index) {
super(source);
this.address = index;
}

@Override
public MutableText createMessage() {
return super.createMessage().append("Spell does not contain a circle at this address: ").append(formatAddress(address));
}
}
Loading