Skip to content

Commit

Permalink
Hopefully multitick tick event... untested thoue
Browse files Browse the repository at this point in the history
  • Loading branch information
enjarai committed Jul 30, 2024
1 parent 8495e9f commit 861ec89
Show file tree
Hide file tree
Showing 7 changed files with 70 additions and 19 deletions.
Original file line number Diff line number Diff line change
@@ -1,15 +1,22 @@
package dev.enjarai.trickster.block;

import dev.enjarai.trickster.Trickster;
import dev.enjarai.trickster.advancement.criterion.ModCriteria;
import dev.enjarai.trickster.spell.*;
import dev.enjarai.trickster.spell.execution.executor.DefaultSpellExecutor;
import dev.enjarai.trickster.spell.execution.executor.ErroredSpellExecutor;
import dev.enjarai.trickster.spell.execution.executor.SpellExecutor;
import dev.enjarai.trickster.spell.execution.source.BlockSpellSource;
import dev.enjarai.trickster.spell.execution.source.SpellSource;
import dev.enjarai.trickster.spell.fragment.NumberFragment;
import dev.enjarai.trickster.spell.fragment.VoidFragment;
import dev.enjarai.trickster.spell.mana.SimpleManaPool;
import dev.enjarai.trickster.spell.trick.blunder.BlunderException;
import dev.enjarai.trickster.spell.trick.blunder.NaNBlunder;
import dev.enjarai.trickster.spell.world.SpellCircleEvent;
import io.wispforest.endec.impl.KeyedEndec;
import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks;
import net.minecraft.block.entity.BlockEntity;
import net.minecraft.nbt.NbtCompound;
import net.minecraft.nbt.NbtOps;
Expand All @@ -32,7 +39,11 @@ public class SpellCircleBlockEntity extends BlockEntity {
public static final KeyedEndec<SimpleManaPool> MANA_POOL_ENDEC =
SimpleManaPool.ENDEC.keyed("mana_pool", () -> new SimpleManaPool(MAX_MANA));

public SpellPart spell = new SpellPart();
// Used with single-tick events
public SpellPart spell;
// Used with multitick events
public SpellExecutor executor;

public SpellCircleEvent event = SpellCircleEvent.NONE;
public Text lastError;
public int age;
Expand All @@ -51,6 +62,8 @@ public void stdIncrease() {
}
};

public transient SpellSource spellSource;

public SpellCircleBlockEntity(BlockPos pos, BlockState state) {
super(ModBlocks.SPELL_CIRCLE_ENTITY, pos, state);
}
Expand All @@ -65,35 +78,63 @@ protected void readNbt(NbtCompound nbt, RegistryWrapper.WrapperLookup registryLo
.ifPresent(pair -> spell = pair.getFirst());
}

if (nbt.contains("executor")) {
SpellExecutor.CODEC.get().decode(NbtOps.INSTANCE, nbt.get("executor"))
.resultOrPartial(err -> Trickster.LOGGER.warn("Failed to load executor in spell circle: {}", err))
.ifPresent(pair -> executor = pair.getFirst());
}

if (nbt.contains("event")) {
event = SpellCircleEvent.REGISTRY.getEntry(Identifier.of(nbt.getString("event")))
.map(RegistryEntry.Reference::value).orElse(SpellCircleEvent.NONE);
}

manaPool = nbt.get(MANA_POOL_ENDEC);

lastPower = nbt.getInt("last_power");
}

@Override
protected void writeNbt(NbtCompound nbt, RegistryWrapper.WrapperLookup registryLookup) {
super.writeNbt(nbt, registryLookup);

SpellPart.CODEC.encodeStart(NbtOps.INSTANCE, spell)
.resultOrPartial(err -> Trickster.LOGGER.warn("Failed to save spell in spell circle: {}", err))
.ifPresent(element -> nbt.put("spell", element));
if (spell != null) {
SpellPart.CODEC.encodeStart(NbtOps.INSTANCE, spell)
.resultOrPartial(err -> Trickster.LOGGER.warn("Failed to save spell in spell circle: {}", err))
.ifPresent(element -> nbt.put("spell", element));
}

if (executor != null) {
SpellExecutor.CODEC.get().encodeStart(NbtOps.INSTANCE, executor)
.resultOrPartial(err -> Trickster.LOGGER.warn("Failed to save executor in spell circle: {}", err))
.ifPresent(element -> nbt.put("executor", element));
}

nbt.putString("event", event.id().toString());

nbt.put(MANA_POOL_ENDEC, manaPool);

nbt.putInt("last_power", lastPower);
}

public void tick() {
manaPool.stdIncrease();

if (event == SpellCircleEvent.TICK && !getWorld().isClient()) {
if (age % 10 == 0) {
var iterations = age / 10;
callEvent(List.of(new NumberFragment(iterations)));
markDirty();
if (event.isMultiTick() && !getWorld().isClient()) {
if (spellSource == null) {
spellSource = new BlockSpellSource((ServerWorld) getWorld(), getPos(), this);
}

try {
if (executor.run(spellSource).isPresent()) {
getWorld().setBlockState(getPos(), Blocks.AIR.getDefaultState());
}
} catch (BlunderException blunder) {
lastError = blunder.createMessage()
.append(" (").append(executor.getCurrentState().formatStackTrace()).append(")");
} catch (Exception e) {
lastError = Text.literal("Uncaught exception in spell: " + e.getMessage())
.append(" (").append(executor.getCurrentState().formatStackTrace()).append(")");
}
}
age++;
Expand All @@ -119,6 +160,10 @@ public NbtCompound toInitialChunkDataNbt(RegistryWrapper.WrapperLookup registryL
}

public boolean callEvent(List<Fragment> arguments) {
if (event.isMultiTick()) {
throw new UnsupportedOperationException("Cannot call multi-tick event directly.");
}

try {
return new DefaultSpellExecutor(spell, arguments).singleTickRun(new BlockSpellSource((ServerWorld) getWorld(), getPos(), this)).asBoolean().bool();
} catch (Exception e) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
public class SpellExecutionManager {
public static final Codec<SpellExecutionManager> CODEC = RecordCodecBuilder.create(instance -> instance.group(
Codec.INT.optionalFieldOf("capacity", 5).forGetter(e -> e.capacity),
Codec.unboundedMap(Codec.STRING.xmap(Integer::parseInt, Object::toString), SpellExecutor.CODEC.get().codec())
Codec.unboundedMap(Codec.STRING.xmap(Integer::parseInt, Object::toString), SpellExecutor.CODEC.get())
.fieldOf("spells").forGetter((e) -> e.spells)
).apply(instance, SpellExecutionManager::new));

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ public class DefaultSpellExecutor implements SpellExecutor {
Codec.list(Fragment.CODEC.get().codec()).fieldOf("inputs").forGetter(executor -> executor.inputs),
Codec.list(Codec.INT).fieldOf("scope").forGetter(executor -> executor.scope),
ExecutionState.CODEC.fieldOf("state").forGetter(executor -> executor.state),
SpellExecutor.CODEC.get().codec().optionalFieldOf("child").forGetter(executor -> executor.child),
SpellExecutor.CODEC.get().optionalFieldOf("child").forGetter(executor -> executor.child),
Fragment.CODEC.get().codec().optionalFieldOf("override_return_value").forGetter(executor -> executor.overrideReturnValue)
).apply(instance, (instructions, inputs, scope, state, child, overrideReturnValue) -> {
List<SpellInstruction> serializedInstructions = instructions.stream().map(SerializedSpellInstruction::toDeserialized).collect(Collectors.toList());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ public class IteratorSpellExecutor extends DefaultSpellExecutor {
ListFragment.CODEC.codec().fieldOf("list").forGetter(executor -> executor.list),
Codec.list(Fragment.CODEC.get().codec()).fieldOf("inputs").forGetter(executor -> executor.inputs),
ExecutionState.CODEC.fieldOf("state").forGetter(executor -> executor.state),
SpellExecutor.CODEC.get().codec().optionalFieldOf("child").forGetter(executor -> executor.child)
SpellExecutor.CODEC.get().optionalFieldOf("child").forGetter(executor -> executor.child)
).apply(instance, IteratorSpellExecutor::new)));

protected final SpellPart executable;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import com.google.common.base.Supplier;
import com.google.common.base.Suppliers;
import com.mojang.serialization.Codec;
import com.mojang.serialization.MapCodec;
import dev.enjarai.trickster.spell.Fragment;
import dev.enjarai.trickster.spell.SpellContext;
Expand All @@ -13,7 +14,8 @@
import java.util.Optional;

public interface SpellExecutor {
Supplier<MapCodec<SpellExecutor>> CODEC = Suppliers.memoize(() -> SpellExecutorType.REGISTRY.getCodec().dispatchMap(SpellExecutor::type, SpellExecutorType::codec));
Supplier<MapCodec<SpellExecutor>> MAP_CODEC = Suppliers.memoize(() -> SpellExecutorType.REGISTRY.getCodec().dispatchMap(SpellExecutor::type, SpellExecutorType::codec));
Supplier<Codec<SpellExecutor>> CODEC = Suppliers.memoize(() -> MAP_CODEC.get().codec());

SpellExecutorType<?> type();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@
public class TryCatchSpellExecutor extends DefaultSpellExecutor {
public static final MapCodec<TryCatchSpellExecutor> CODEC = RecordCodecBuilder.mapCodec((instance) -> instance.group(
DefaultSpellExecutor.CODEC.codec().fieldOf("self").forGetter(executor -> executor),
SpellExecutor.CODEC.get().fieldOf("try").forGetter(executor -> executor.trySpell),
SpellExecutor.CODEC.get().fieldOf("catch").forGetter(executor -> executor.catchSpell),
SpellExecutor.MAP_CODEC.get().fieldOf("try").forGetter(executor -> executor.trySpell),
SpellExecutor.MAP_CODEC.get().fieldOf("catch").forGetter(executor -> executor.catchSpell),
Codec.BOOL.fieldOf("catching").forGetter(executor -> executor.catching)
).apply(instance, (self, trySpell, catchSpell, catching) -> new TryCatchSpellExecutor(self.instructions, self.inputs, self.scope, self.state, self.child, self.overrideReturnValue, trySpell, catchSpell, catching)));

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@

import static dev.enjarai.trickster.block.SpellCircleBlockEntity.LISTENER_RADIUS;

public record SpellCircleEvent(Identifier id, Pattern pattern) {
public record SpellCircleEvent(Identifier id, Pattern pattern, boolean isMultiTick) {
private static final Map<Pattern, SpellCircleEvent> LOOKUP = new HashMap<>();

public static final RegistryKey<Registry<SpellCircleEvent>> REGISTRY_KEY = RegistryKey.ofRegistry(Trickster.id("circle_event"));
Expand All @@ -44,12 +44,16 @@ public RegistryEntry.Reference<SpellCircleEvent> add(RegistryKey<SpellCircleEven
public static final SpellCircleEvent ENTITY_MOVE = register("entity_move", Pattern.of(3, 4, 5, 8, 4));
public static final SpellCircleEvent USE_ITEM = register("use_item", Pattern.of(0, 4, 8, 5, 1, 0, 3, 7, 8));

public static final SpellCircleEvent TICK = register("tick", Pattern.of(0, 3, 6, 7, 8, 5, 2, 1, 0, 4, 5));
public static final SpellCircleEvent TICK = register("tick", Pattern.of(0, 3, 6, 7, 8, 5, 2, 1, 0, 4, 5), true);
public static final SpellCircleEvent REDSTONE_UPDATE = register("redstone_update", Pattern.of(1, 5, 8, 7, 6, 3, 1));

private static SpellCircleEvent register(String path, Pattern pattern) {
private static SpellCircleEvent register(String path, Pattern pattern, boolean isMultiTick) {
var id = Trickster.id(path);
return Registry.register(REGISTRY, id, new SpellCircleEvent(id, pattern));
return Registry.register(REGISTRY, id, new SpellCircleEvent(id, pattern, isMultiTick));
}

private static SpellCircleEvent register(String path, Pattern pattern) {
return register(path, pattern, false);
}

public static void register() {
Expand Down

0 comments on commit 861ec89

Please sign in to comment.