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

Blocky Chroniclers #796

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 23 additions & 1 deletion Common/src/main/java/at/petrak/hexcasting/api/HexAPI.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package at.petrak.hexcasting.api;

import at.petrak.hexcasting.api.addldata.ADIotaHolder;
import at.petrak.hexcasting.api.addldata.ADMediaHolder;
import at.petrak.hexcasting.api.casting.ActionRegistryEntry;
import at.petrak.hexcasting.api.casting.castables.SpecialHandler;
Expand All @@ -8,15 +9,16 @@
import at.petrak.hexcasting.xplat.IXplatAbstractions;
import com.google.common.base.Suppliers;
import net.minecraft.ChatFormatting;
import net.minecraft.core.BlockPos;
import net.minecraft.network.chat.Component;
import net.minecraft.resources.ResourceKey;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.sounds.SoundEvent;
import net.minecraft.sounds.SoundEvents;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.EntityType;
import net.minecraft.world.entity.EquipmentSlot;
import net.minecraft.world.entity.Mob;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.ArmorItem;
Expand Down Expand Up @@ -213,6 +215,26 @@ default ArmorMaterial robesMaterial() {
return DUMMY_ARMOR_MATERIAL;
}

@FunctionalInterface
interface IBlockyIotaProvider{
ADIotaHolder getIotaHolder(ServerLevel level, BlockPos pos);
}

/**
* Register's an iota holder provider for a block to be used with Chronicler's.
* <p>
* NOTE: should implement IBlockyIotaProvider on the block or ADIotaHolder on the block entity if possible.
* This method should only be used in cases where that's not feasible, such as an optional hex
* dependency or adding a provider to another mod's block.
* </p>
* @param blockID the resloc/id for the block
* @return if the holder was successfully registered
* @see IXplatAbstractions#findDataHolder(BlockPos, ServerLevel)
*/
default boolean registerBlockyIotaHolder(ResourceLocation blockID, IBlockyIotaProvider holder){
return false;
}

/**
* Location in the userdata of the ravenmind
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,4 +34,24 @@ default Iota emptyIota() {
* @return whether it is possible to write to this IotaHolder
*/
boolean writeable();

// a helper for read-only holders
interface ADIotaHolderReadOnly extends ADIotaHolder{
default boolean writeIota(@Nullable Iota iota, boolean simulate){
return false;
}

default boolean writeable(){ return false; }
}

// wraps an iota in an iota holder
static ADIotaHolder ofStatic(Iota iota){
return new ADIotaHolderReadOnly(){
@Nullable
public CompoundTag readIotaTag(){ return IotaType.serialize(iota); }

@Nullable
public Iota readIota(ServerLevel world) { return iota; }
};
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,20 @@ fun List<Iota>.getLongOrList(idx: Int, argc: Int = 0): Either<Long, SpellList> {
)
}


fun List<Iota>.getEntityOrBlockPos(idx: Int, argc: Int = 0): Either<Entity, BlockPos> {
val datum = this.getOrElse(idx) { throw MishapNotEnoughArgs(idx + 1, this.size) }
return when (datum) {
is EntityIota -> Either.left(datum.entity)
is Vec3Iota -> Either.right(BlockPos.containing(datum.vec3))
else -> throw MishapInvalidIota.of(
datum,
if (argc == 0) idx else argc - (idx + 1),
"entity_or_vector"
)
}
}

fun evaluatable(datum: Iota, reverseIdx: Int): Either<Iota, SpellList> =
when (datum) {
is ListIota -> Either.right(datum.list)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package at.petrak.hexcasting.api.casting.mishaps

import com.mojang.datafixers.util.Either
import net.minecraft.core.BlockPos
import net.minecraft.world.entity.Entity
import net.minecraft.world.item.ItemStack
import net.minecraft.world.phys.Vec3

// a silly stupid wrapper for throwing arbitrary badness mishaps (the ones that have a .of(thing, stub) constructor.
class MishapBad {
companion object {
@JvmStatic
fun of(thing: Any, stub: String): Mishap {
return when(thing){
is Either<*, *> -> thing.map({l -> of(l, stub)}, {r -> of(r, stub)})
is Entity -> MishapBadEntity.of(thing, stub)
is BlockPos -> MishapBadBlock.of(thing, stub)
is Vec3 -> MishapBadLocation(thing, stub)
is ItemStack -> MishapBadOffhandItem.of(thing, stub)
else -> throw IllegalArgumentException()
}
}
}
}
Original file line number Diff line number Diff line change
@@ -1,15 +1,22 @@
package at.petrak.hexcasting.common.blocks.akashic;

import at.petrak.hexcasting.api.HexAPI.IBlockyIotaProvider;
import at.petrak.hexcasting.api.addldata.ADIotaHolder;
import at.petrak.hexcasting.api.casting.iota.Iota;
import at.petrak.hexcasting.api.casting.iota.IotaType;
import at.petrak.hexcasting.api.casting.iota.ListIota;
import at.petrak.hexcasting.api.casting.iota.PatternIota;
import at.petrak.hexcasting.api.casting.math.HexPattern;
import net.minecraft.core.BlockPos;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.Block;
import org.jetbrains.annotations.Nullable;

public class BlockAkashicRecord extends Block {
import java.util.ArrayList;
import java.util.List;

public class BlockAkashicRecord extends Block implements IBlockyIotaProvider {
public BlockAkashicRecord(Properties p_49795_) {
super(p_49795_);
}
Expand Down Expand Up @@ -61,4 +68,19 @@ Iota lookupPattern(BlockPos herePos, HexPattern key, ServerLevel slevel) {
}

// TODO get comparators working again and also cache the number of iotas somehow?

@Override
public ADIotaHolder getIotaHolder(ServerLevel level, BlockPos recPos) {
List<Iota> labels = new ArrayList<>();
AkashicFloodfiller.floodFillFor(recPos, level,
(pos, bs, world) -> {
if(world.getBlockEntity(pos) instanceof BlockEntityAkashicBookshelf tile
&& tile.getPattern() != null
){
labels.add(new PatternIota(tile.getPattern()));
}
return false;
});
return ADIotaHolder.ofStatic(new ListIota(labels));
}
}
Original file line number Diff line number Diff line change
@@ -1,17 +1,20 @@
package at.petrak.hexcasting.common.blocks.akashic;

import at.petrak.hexcasting.api.addldata.ADIotaHolder.ADIotaHolderReadOnly;
import at.petrak.hexcasting.api.block.HexBlockEntity;
import at.petrak.hexcasting.api.casting.iota.Iota;
import at.petrak.hexcasting.api.casting.iota.IotaType;
import at.petrak.hexcasting.api.casting.iota.PatternIota;
import at.petrak.hexcasting.api.casting.math.HexPattern;
import at.petrak.hexcasting.client.render.HexPatternPoints;
import at.petrak.hexcasting.common.lib.HexBlockEntities;
import net.minecraft.core.BlockPos;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.level.block.state.BlockState;
import org.jetbrains.annotations.Nullable;

public class BlockEntityAkashicBookshelf extends HexBlockEntity {
public class BlockEntityAkashicBookshelf extends HexBlockEntity implements ADIotaHolderReadOnly {
public static final String TAG_PATTERN = "pattern";
public static final String TAG_IOTA = "iota";
public static final String TAG_DUMMY = "dummy";
Expand Down Expand Up @@ -89,4 +92,20 @@ protected void loadModData(CompoundTag tag) {
this.iotaTag = null;
}
}

@Override
public CompoundTag readIotaTag(){
if(pattern == null){
return IotaType.serialize(emptyIota());
}
return IotaType.serialize(new PatternIota(pattern));
}

@Override
public Iota readIota(ServerLevel world) {
if(pattern == null){
return emptyIota();
}
return new PatternIota(pattern);
}
}
Original file line number Diff line number Diff line change
@@ -1,15 +1,21 @@
package at.petrak.hexcasting.common.blocks.circles;

import at.petrak.hexcasting.api.addldata.ADIotaHolder;
import at.petrak.hexcasting.api.block.HexBlockEntity;
import at.petrak.hexcasting.api.casting.iota.Iota;
import at.petrak.hexcasting.api.casting.iota.IotaType;
import at.petrak.hexcasting.api.casting.iota.NullIota;
import at.petrak.hexcasting.api.casting.iota.PatternIota;
import at.petrak.hexcasting.api.casting.math.HexPattern;
import at.petrak.hexcasting.common.lib.HexBlockEntities;
import net.minecraft.core.BlockPos;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.Tag;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.level.block.state.BlockState;
import org.jetbrains.annotations.Nullable;

public class BlockEntitySlate extends HexBlockEntity {
public class BlockEntitySlate extends HexBlockEntity implements ADIotaHolder {
public static final String TAG_PATTERN = "pattern";

@Nullable
Expand Down Expand Up @@ -42,4 +48,39 @@ protected void loadModData(CompoundTag tag) {
}
}

@Override
public CompoundTag readIotaTag(){
if(pattern == null){
return IotaType.serialize(emptyIota());
}
return IotaType.serialize(new PatternIota(pattern));
}

@Override
public Iota readIota(ServerLevel world) {
if(pattern == null){
return emptyIota();
}
return new PatternIota(pattern);
}

@Override
public boolean writeIota(@Nullable Iota iota, boolean simulate){
if(!simulate){
if(iota instanceof PatternIota pIota){
this.pattern = pIota.getPattern();
sync();
}
if(iota instanceof NullIota || iota == null){
this.pattern = null;
sync();
}
}
return iota instanceof PatternIota || iota instanceof NullIota || iota == null;
}

@Override
public boolean writeable(){
return true;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ package at.petrak.hexcasting.common.casting.actions.rw

import at.petrak.hexcasting.api.casting.castables.ConstMediaAction
import at.petrak.hexcasting.api.casting.eval.CastingEnvironment
import at.petrak.hexcasting.api.casting.getEntity
import at.petrak.hexcasting.api.casting.getEntityOrBlockPos
import at.petrak.hexcasting.api.casting.iota.Iota
import at.petrak.hexcasting.api.casting.mishaps.MishapBadEntity
import at.petrak.hexcasting.api.casting.mishaps.MishapBad
import at.petrak.hexcasting.xplat.IXplatAbstractions

object OpTheCoolerRead : ConstMediaAction {
Expand All @@ -14,16 +14,18 @@ object OpTheCoolerRead : ConstMediaAction {
args: List<Iota>,
env: CastingEnvironment
): List<Iota> {
val target = args.getEntity(0, argc)
val target = args.getEntityOrBlockPos(0, argc)

env.assertEntityInRange(target)
target.map(env::assertEntityInRange, env::assertPosInRange)

val datumHolder = IXplatAbstractions.INSTANCE.findDataHolder(target)
?: throw MishapBadEntity.of(target, "iota.read")
val datumHolder = target.map(
IXplatAbstractions.INSTANCE::findDataHolder,
{pos -> IXplatAbstractions.INSTANCE.findDataHolder(pos, env.world)})
?: throw MishapBad.of(target, "iota.read")

val datum = datumHolder.readIota(env.world)
?: datumHolder.emptyIota()
?: throw MishapBadEntity.of(target, "iota.read")
?: throw MishapBad.of(target, "iota.read")
return listOf(datum)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ package at.petrak.hexcasting.common.casting.actions.rw
import at.petrak.hexcasting.api.casting.asActionResult
import at.petrak.hexcasting.api.casting.castables.ConstMediaAction
import at.petrak.hexcasting.api.casting.eval.CastingEnvironment
import at.petrak.hexcasting.api.casting.getEntity
import at.petrak.hexcasting.api.casting.getEntityOrBlockPos
import at.petrak.hexcasting.api.casting.iota.Iota
import at.petrak.hexcasting.xplat.IXplatAbstractions

Expand All @@ -14,10 +14,13 @@ object OpTheCoolerReadable : ConstMediaAction {
args: List<Iota>,
env: CastingEnvironment
): List<Iota> {
val target = args.getEntity(0, argc)
env.assertEntityInRange(target)
val target = args.getEntityOrBlockPos(0, argc)

val datumHolder = IXplatAbstractions.INSTANCE.findDataHolder(target)
target.map(env::assertEntityInRange, env::assertPosInRange)

val datumHolder = target.map(
IXplatAbstractions.INSTANCE::findDataHolder,
{pos -> IXplatAbstractions.INSTANCE.findDataHolder(pos, env.world)})
?: return false.asActionResult

datumHolder.readIota(env.world)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ package at.petrak.hexcasting.common.casting.actions.rw
import at.petrak.hexcasting.api.casting.asActionResult
import at.petrak.hexcasting.api.casting.castables.ConstMediaAction
import at.petrak.hexcasting.api.casting.eval.CastingEnvironment
import at.petrak.hexcasting.api.casting.getEntity
import at.petrak.hexcasting.api.casting.getEntityOrBlockPos
import at.petrak.hexcasting.api.casting.iota.Iota
import at.petrak.hexcasting.api.casting.iota.NullIota
import at.petrak.hexcasting.xplat.IXplatAbstractions
Expand All @@ -15,10 +15,13 @@ object OpTheCoolerWritable : ConstMediaAction {
args: List<Iota>,
env: CastingEnvironment
): List<Iota> {
val target = args.getEntity(0, argc)
env.assertEntityInRange(target)
val target = args.getEntityOrBlockPos(0, argc)

val datumHolder = IXplatAbstractions.INSTANCE.findDataHolder(target)
target.map(env::assertEntityInRange, env::assertPosInRangeForEditing)

val datumHolder = target.map(
IXplatAbstractions.INSTANCE::findDataHolder,
{pos -> IXplatAbstractions.INSTANCE.findDataHolder(pos, env.world)})
?: return false.asActionResult

val success = datumHolder.writeIota(NullIota(), true)
Expand Down
Loading
Loading