kotlin now compiles! ... now onto java

This commit is contained in:
gamma-delta 2022-06-14 14:35:06 -05:00
parent 8b7369fe8b
commit 434c480b0b
25 changed files with 260 additions and 458 deletions

View file

@ -6,6 +6,8 @@ import at.petrak.hexcasting.common.lib.HexIotaTypes;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.Tag;
import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.Style;
import net.minecraft.network.chat.TextComponent;
import net.minecraft.server.level.ServerLevel;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@ -31,23 +33,43 @@ public class PatternIota extends Iota {
return this.getPattern().serializeToNBT();
}
public static IotaType<PatternIota> TYPE = new IotaType<>() {
@Nullable
@Override
public PatternIota deserialize(Tag tag, ServerLevel world) throws IllegalArgumentException {
return PatternIota.deserialize(tag);
}
@Override
public Component display(Tag tag) {
return PatternIota.display(PatternIota.deserialize(tag).getPattern());
}
@Override
public int color() {
return 0xff_ffaa00;
}
};
public static PatternIota deserialize(Tag tag) throws IllegalArgumentException {
var patTag = HexUtils.downcast(tag, CompoundTag.TYPE);
HexPattern pat = HexPattern.fromNBT(patTag);
return new PatternIota(pat);
}
@Override
public Component display(Tag tag) {
return null;
}
public static Component display(HexPattern pat) {
var out = new TextComponent("HexPattern")
.withStyle(Style.EMPTY.withColor(HexIotaTypes.PATTERN.color()));
out.append("(");
out.append(pat.getStartDir().toString());
@Override
public int color() {
return 0;
var sig = pat.anglesSignature();
if (!sig.isEmpty()) {
out.append(" ");
out.append(sig);
}
out.append(")");
return out;
}
};
}

View file

@ -112,6 +112,8 @@ data class HexPattern(public val startDir: HexDir, public val angles: MutableLis
fun toLines(hexSize: Float, origin: Vec2): List<Vec2> =
this.positions().map { coordToPx(it, hexSize, origin) }
fun sigsEqual(that: HexPattern) = this.anglesSignature() == that.anglesSignature()
override fun toString(): String = buildString {
append("HexPattern[")
append(this@HexPattern.startDir)

View file

@ -0,0 +1,66 @@
package at.petrak.hexcasting.common.blocks.akashic;
import at.petrak.hexcasting.api.misc.TriPredicate;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.state.BlockState;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayDeque;
import java.util.HashSet;
public interface AkashicFloodfiller {
default boolean canBeFloodedThrough(BlockPos pos, BlockState state, Level world) {
return true;
}
@Nullable
static BlockPos floodFillFor(BlockPos start, Level world, TriPredicate<BlockPos, BlockState, Level> isTarget) {
return floodFillFor(start, world, 0f, isTarget);
}
@Nullable
static BlockPos floodFillFor(BlockPos start, Level world, float skipChance,
TriPredicate<BlockPos, BlockState, Level> isTarget) {
var seenBlocks = new HashSet<BlockPos>();
var todo = new ArrayDeque<BlockPos>();
todo.add(start);
var skippedBlocks = new HashSet<BlockPos>();
while (!todo.isEmpty()) {
var here = todo.remove();
for (var dir : Direction.values()) {
var neighbor = here.relative(dir);
if (seenBlocks.add(neighbor)) {
var bs = world.getBlockState(neighbor);
if (isTarget.test(neighbor, bs, world)) {
if (world.random.nextFloat() < skipChance) {
return neighbor;
} else {
skippedBlocks.add(neighbor);
}
} else if (canItBeFloodedThrough(neighbor, bs, world)) {
todo.add(neighbor);
}
}
}
}
if (!skippedBlocks.isEmpty()) {
// We found something valid, we just skipped past it
return skippedBlocks.iterator().next();
}
return null;
}
static boolean canItBeFloodedThrough(BlockPos pos, BlockState state, Level world) {
if (!(state.getBlock() instanceof AkashicFloodfiller flooder)) {
return false;
}
return flooder.canBeFloodedThrough(pos, state, world);
}
}

View file

@ -1,10 +1,8 @@
package at.petrak.hexcasting.common.blocks.akashic;
import at.petrak.hexcasting.annotations.SoftImplement;
import at.petrak.hexcasting.api.spell.DatumType;
import at.petrak.hexcasting.api.spell.iota.Iota;
import at.petrak.hexcasting.api.spell.iota.PatternIota;
import at.petrak.hexcasting.common.items.ItemScroll;
import at.petrak.hexcasting.common.lib.HexBlocks;
import at.petrak.hexcasting.common.lib.HexSounds;
import at.petrak.hexcasting.xplat.IForgeLikeBlock;
import net.minecraft.core.BlockPos;
@ -24,32 +22,20 @@ import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.state.StateDefinition;
import net.minecraft.world.level.block.state.properties.BlockStateProperties;
import net.minecraft.world.level.block.state.properties.BooleanProperty;
import net.minecraft.world.level.block.state.properties.DirectionProperty;
import net.minecraft.world.level.block.state.properties.EnumProperty;
import net.minecraft.world.phys.BlockHitResult;
import org.jetbrains.annotations.Nullable;
public class BlockAkashicBookshelf extends BlockAkashicFloodfiller implements EntityBlock, IForgeLikeBlock {
public class BlockAkashicBookshelf extends Block implements AkashicFloodfiller, EntityBlock, IForgeLikeBlock {
public static final DirectionProperty FACING = BlockStateProperties.HORIZONTAL_FACING;
public static final EnumProperty<DatumType> DATUM_TYPE = EnumProperty.create("datum_type", DatumType.class);
public static final BooleanProperty HAS_BOOKS = BooleanProperty.create("has_books");
public BlockAkashicBookshelf(Properties p_49795_) {
super(p_49795_);
this.registerDefaultState(this.getStateDefinition().any()
.setValue(FACING, Direction.NORTH)
.setValue(DATUM_TYPE, DatumType.EMPTY));
}
@Override
public @Nullable
BlockPos getRecordPosition(BlockPos herePos, BlockState state, Level world) {
// time saving measure?
if (world.getBlockEntity(herePos) instanceof BlockEntityAkashicBookshelf tile &&
tile.getRecordPos() != null && world.getBlockEntity(
tile.getRecordPos()) instanceof BlockEntityAkashicRecord) {
return tile.getRecordPos();
}
return super.getRecordPosition(herePos, state, world);
.setValue(HAS_BOOKS, false));
}
@Override
@ -59,19 +45,13 @@ public class BlockAkashicBookshelf extends BlockAkashicFloodfiller implements En
var stack = pPlayer.getItemInHand(pHand);
if (stack.getItem() instanceof ItemScroll scroll) {
if (!pLevel.isClientSide()) {
scroll.writeDatum(stack, LegacySpellDatum.make(shelf.getPattern()));
scroll.writeDatum(stack, new PatternIota(shelf.getPattern()));
}
pLevel.playSound(pPlayer, pPos, HexSounds.SCROLL_SCRIBBLE, SoundSource.BLOCKS, 1f, 1f);
return InteractionResult.sidedSuccess(pLevel.isClientSide);
} else if (pPlayer.isDiscrete() && pHand == InteractionHand.MAIN_HAND && stack.isEmpty()) {
if (!pLevel.isClientSide()) {
shelf.setNewData(null, null, DatumType.EMPTY);
var recordPos = HexBlocks.AKASHIC_BOOKSHELF.getRecordPosition(pPos, pState, pLevel);
if (recordPos != null &&
pLevel.getBlockEntity(recordPos) instanceof BlockEntityAkashicRecord record) {
record.revalidateAllBookshelves();
}
shelf.clearIota();
}
pLevel.playSound(pPlayer, pPos, HexSounds.SCROLL_SCRIBBLE, SoundSource.BLOCKS,
@ -83,32 +63,9 @@ public class BlockAkashicBookshelf extends BlockAkashicFloodfiller implements En
return InteractionResult.PASS;
}
@Override
public void onPlace(BlockState pState, Level world, BlockPos pos, BlockState pOldState, boolean pIsMoving) {
if (world.getBlockEntity(pos) instanceof BlockEntityAkashicBookshelf tile) {
var recordPos = BlockAkashicFloodfiller.floodFillFor(pos, world,
(here, bs, level) -> bs.is(HexBlocks.AKASHIC_RECORD));
if (pOldState.getBlock() != pState.getBlock()) {
tile.setNewData(recordPos, recordPos == null ? null : tile.getPattern(),
recordPos == null ? DatumType.EMPTY : pState.getValue(DATUM_TYPE));
}
}
}
@Override
public void neighborChanged(BlockState pState, Level world, BlockPos pos, Block pBlock, BlockPos pFromPos,
boolean pIsMoving) {
if (world.getBlockEntity(pos) instanceof BlockEntityAkashicBookshelf tile) {
var recordPos = BlockAkashicFloodfiller.floodFillFor(pos, world,
(here, bs, level) -> bs.is(HexBlocks.AKASHIC_RECORD));
tile.setNewData(recordPos, recordPos == null ? null : tile.getPattern(),
recordPos == null ? DatumType.EMPTY : pState.getValue(DATUM_TYPE));
}
}
@Override
protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> builder) {
builder.add(FACING, DATUM_TYPE);
builder.add(FACING, HAS_BOOKS);
}
@Override
@ -128,12 +85,12 @@ public class BlockAkashicBookshelf extends BlockAkashicFloodfiller implements En
@Override
public boolean hasAnalogOutputSignal(BlockState pState) {
return true;
return pState.getValue(HAS_BOOKS);
}
@Override
public int getAnalogOutputSignal(BlockState pState, Level pLevel, BlockPos pPos) {
return pState.getValue(DATUM_TYPE).ordinal();
return pState.getValue(HAS_BOOKS) ? 15 : 0;
}
@Nullable

View file

@ -1,80 +0,0 @@
package at.petrak.hexcasting.common.blocks.akashic;
import at.petrak.hexcasting.api.misc.TriPredicate;
import at.petrak.hexcasting.common.lib.HexBlocks;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.state.BlockState;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayDeque;
import java.util.HashSet;
public class BlockAkashicFloodfiller extends Block {
public BlockAkashicFloodfiller(Properties p_49795_) {
super(p_49795_);
}
public @Nullable
BlockPos getRecordPosition(BlockPos here, BlockState state, Level world) {
return floodFillFor(here, world,
(pos, bs, level) -> bs.is(HexBlocks.AKASHIC_RECORD));
}
@Override
public void onRemove(BlockState pState, Level pLevel, BlockPos pPos, BlockState pNewState, boolean pIsMoving) {
var recordPos = this.getRecordPosition(pPos, pState, pLevel);
if (recordPos != null && pLevel.getBlockEntity(recordPos) instanceof BlockEntityAkashicRecord akashic) {
akashic.removeFloodfillerAt(pPos);
}
super.onRemove(pState, pLevel, pPos, pNewState, pIsMoving);
}
public boolean canBeFloodedThrough(BlockPos pos, BlockState state, Level world) {
return true;
}
public static @Nullable
BlockPos floodFillFor(BlockPos start, Level world,
TriPredicate<BlockPos, BlockState, Level> isValid, TriPredicate<BlockPos, BlockState, Level> isTarget) {
var seenBlocks = new HashSet<BlockPos>();
var todo = new ArrayDeque<BlockPos>();
todo.add(start);
while (!todo.isEmpty()) {
var here = todo.remove();
for (var dir : Direction.values()) {
var neighbor = here.relative(dir);
if (seenBlocks.add(neighbor)) {
var bs = world.getBlockState(neighbor);
if (isTarget.test(neighbor, bs, world)) {
return neighbor;
} else if (isValid.test(neighbor, bs, world)) {
todo.add(neighbor);
}
}
}
}
return null;
}
public static @Nullable
BlockPos floodFillFor(BlockPos start, Level world,
TriPredicate<BlockPos, BlockState, Level> isTarget) {
return floodFillFor(start, world, BlockAkashicFloodfiller::canItBeFloodedThrough, isTarget);
}
public static boolean canItBeFloodedThrough(BlockPos pos, BlockState state, Level world) {
if (!(state.getBlock() instanceof BlockAkashicFloodfiller flooder)) {
return false;
}
return flooder.canBeFloodedThrough(pos, state, world);
}
}

View file

@ -0,0 +1,9 @@
package at.petrak.hexcasting.common.blocks.akashic;
import net.minecraft.world.level.block.Block;
public class BlockAkashicLigature extends Block implements AkashicFloodfiller {
public BlockAkashicLigature(Properties properties) {
super(properties);
}
}

View file

@ -1,66 +1,64 @@
package at.petrak.hexcasting.common.blocks.akashic;
import at.petrak.hexcasting.api.spell.DatumType;
import at.petrak.hexcasting.api.spell.iota.Iota;
import at.petrak.hexcasting.api.spell.math.HexPattern;
import at.petrak.hexcasting.common.lib.HexIotaTypes;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.EntityBlock;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.state.BlockState;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayDeque;
import java.util.HashSet;
public class BlockAkashicRecord extends Block implements EntityBlock {
public class BlockAkashicRecord extends Block {
public BlockAkashicRecord(Properties p_49795_) {
super(p_49795_);
}
@Nullable
@Override
public BlockEntity newBlockEntity(BlockPos pPos, BlockState pState) {
return new BlockEntityAkashicRecord(pPos, pState);
/**
* @return the block position of the place it gets stored, or null if there was no room.
* <p>
* Will never clobber anything.
*/
public @Nullable
BlockPos addNewDatum(BlockPos herePos, Level level, HexPattern key, Iota datum) {
var clobbereePos = AkashicFloodfiller.floodFillFor(herePos, level,
(pos, bs, world) ->
world.getBlockEntity(pos) instanceof BlockEntityAkashicBookshelf tile
&& tile.getPattern() != null && tile.getPattern().sigsEqual(key));
if (clobbereePos != null) {
return null;
}
@Override
public boolean hasAnalogOutputSignal(BlockState pState) {
return true;
var openPos = AkashicFloodfiller.floodFillFor(herePos, level, 0.5f,
(pos, bs, world) ->
world.getBlockEntity(pos) instanceof BlockEntityAkashicBookshelf tile
&& tile.getPattern() == null);
if (openPos != null) {
var tile = (BlockEntityAkashicBookshelf) level.getBlockEntity(openPos);
tile.setNewMapping(key, datum);
return openPos;
} else {
return null;
}
}
@Override
public int getAnalogOutputSignal(BlockState pState, Level pLevel, BlockPos pPos) {
BlockEntity be = pLevel.getBlockEntity(pPos);
if (be instanceof BlockEntityAkashicRecord record) {
return Math.min(15, record.getCount());
}
return 0;
public @Nullable
Iota lookupPattern(BlockPos herePos, HexPattern key, ServerLevel slevel) {
var foundPos = AkashicFloodfiller.floodFillFor(herePos, slevel,
(pos, bs, world) ->
world.getBlockEntity(pos) instanceof BlockEntityAkashicBookshelf tile
&& tile.getPattern() != null && tile.getPattern().sigsEqual(key));
if (foundPos == null) {
return null;
}
@Override
public void onRemove(BlockState pState, Level pLevel, BlockPos pPos, BlockState pNewState, boolean pIsMoving) {
var seen = new HashSet<BlockPos>();
var todo = new ArrayDeque<BlockPos>();
todo.add(pPos);
// we do NOT add this position to the valid positions, because the record
// isn't flood-fillable through.
while (!todo.isEmpty()) {
var here = todo.remove();
var tile = (BlockEntityAkashicBookshelf) slevel.getBlockEntity(foundPos);
var tag = tile.getIotaTag();
return tag == null ? null : HexIotaTypes.deserialize(tag, slevel);
}
for (var dir : Direction.values()) {
var neighbor = here.relative(dir);
if (seen.add(neighbor)) {
var bs = pLevel.getBlockState(neighbor);
if (BlockAkashicFloodfiller.canItBeFloodedThrough(neighbor, bs, pLevel)) {
todo.add(neighbor);
}
if (pLevel.getBlockEntity(neighbor) instanceof BlockEntityAkashicBookshelf shelf) {
shelf.setNewData(null, null, DatumType.EMPTY);
}
}
}
}
super.onRemove(pState, pLevel, pPos, pNewState, pIsMoving);
}
// TODO get comparators working again and also cache the number of iotas somehow?
}

View file

@ -1,80 +1,85 @@
package at.petrak.hexcasting.common.blocks.akashic;
import at.petrak.hexcasting.api.block.HexBlockEntity;
import at.petrak.hexcasting.api.spell.DatumType;
import at.petrak.hexcasting.api.spell.iota.Iota;
import at.petrak.hexcasting.api.spell.math.HexPattern;
import at.petrak.hexcasting.common.lib.HexBlockEntities;
import at.petrak.hexcasting.common.lib.HexIotaTypes;
import net.minecraft.core.BlockPos;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.NbtUtils;
import net.minecraft.nbt.Tag;
import net.minecraft.world.level.block.state.BlockState;
import org.jetbrains.annotations.Nullable;
public class BlockEntityAkashicBookshelf extends HexBlockEntity {
public static final String TAG_RECORD_POS = "record_pos";
public static final String TAG_PATTERN = "pattern";
public static final String TAG_IOTA = "iota";
// This might actually be inaccurate! It's a best-guess
private BlockPos recordPos = null;
// This is only not null if this stores any data.
private HexPattern pattern = null;
// When the world is first loading we can sometimes try to deser this from nbt without the world existing yet.
// We also need a way to display the iota to the client.
// For both these cases we save just the tag of the iota.
private CompoundTag iotaTag = null;
public BlockEntityAkashicBookshelf(BlockPos pWorldPosition, BlockState pBlockState) {
super(HexBlockEntities.AKASHIC_BOOKSHELF_TILE, pWorldPosition, pBlockState);
}
@Nullable
public BlockPos getRecordPos() {
return recordPos;
}
@Nullable
public HexPattern getPattern() {
return pattern;
}
@Nullable
public CompoundTag getIotaTag() {
return iotaTag;
}
public void setNewData(BlockPos recordPos, HexPattern pattern, DatumType type) {
this.recordPos = recordPos;
public void setNewMapping(HexPattern pattern, Iota iota) {
var previouslyEmpty = this.pattern == null;
this.pattern = pattern;
this.iotaTag = HexIotaTypes.serialize(iota);
if (previouslyEmpty) {
var oldBs = this.getBlockState();
var newBs = oldBs.setValue(BlockAkashicBookshelf.HAS_BOOKS, true);
this.level.setBlock(this.getBlockPos(), newBs, 3);
this.level.sendBlockUpdated(this.getBlockPos(), oldBs, newBs, 3);
} else {
this.setChanged();
}
}
public void clearIota() {
var previouslyEmpty = this.pattern == null;
this.pattern = null;
this.iotaTag = null;
this.setChanged();
BlockState worldBs = this.level.getBlockState(this.getBlockPos());
if (!previouslyEmpty) {
var oldBs = this.getBlockState();
if (worldBs.getBlock() == oldBs.getBlock()) {
var newBs = oldBs.setValue(BlockAkashicBookshelf.DATUM_TYPE, type);
var newBs = oldBs.setValue(BlockAkashicBookshelf.HAS_BOOKS, false);
this.level.setBlock(this.getBlockPos(), newBs, 3);
this.level.sendBlockUpdated(this.getBlockPos(), oldBs, newBs, 3);
} else {
this.setChanged();
}
}
@Override
protected void saveModData(CompoundTag compoundTag) {
compoundTag.put(TAG_RECORD_POS,
this.recordPos == null ? new CompoundTag() : NbtUtils.writeBlockPos(this.recordPos));
compoundTag.put(TAG_PATTERN, this.pattern == null ? new CompoundTag() : this.pattern.serializeToNBT());
if (this.pattern != null && this.iotaTag != null) {
compoundTag.put(TAG_PATTERN, this.pattern.serializeToNBT());
compoundTag.put(TAG_IOTA, this.iotaTag);
}
}
@Override
protected void loadModData(CompoundTag compoundTag) {
CompoundTag recordPos = compoundTag.getCompound(TAG_RECORD_POS);
CompoundTag pattern = compoundTag.getCompound(TAG_PATTERN);
if (recordPos.contains("X", Tag.TAG_ANY_NUMERIC) &&
recordPos.contains("Y", Tag.TAG_ANY_NUMERIC) &&
recordPos.contains("Z", Tag.TAG_ANY_NUMERIC)) {
this.recordPos = NbtUtils.readBlockPos(recordPos);
} else {
this.recordPos = null;
}
if (HexPattern.isPattern(pattern)) {
this.pattern = HexPattern.fromNBT(pattern);
} else {
this.pattern = null;
protected void loadModData(CompoundTag tag) {
if (tag.contains(TAG_PATTERN) && tag.contains(TAG_IOTA)) {
this.pattern = HexPattern.fromNBT(tag.getCompound(TAG_PATTERN));
this.iotaTag = tag.getCompound(TAG_IOTA);
}
}
}

View file

@ -1,178 +0,0 @@
package at.petrak.hexcasting.common.blocks.akashic;
import at.petrak.hexcasting.api.block.HexBlockEntity;
import at.petrak.hexcasting.api.spell.DatumType;
import at.petrak.hexcasting.api.spell.iota.Iota;
import at.petrak.hexcasting.api.spell.math.HexDir;
import at.petrak.hexcasting.api.spell.math.HexPattern;
import at.petrak.hexcasting.common.lib.HexBlockEntities;
import net.minecraft.ChatFormatting;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.NbtUtils;
import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.TranslatableComponent;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.level.block.state.BlockState;
import org.jetbrains.annotations.Nullable;
import java.util.*;
public class BlockEntityAkashicRecord extends HexBlockEntity {
public static final String TAG_LOOKUP = "lookup",
TAG_POS = "pos",
TAG_DATUM = "datum",
TAG_DIR = "dir";
// Hex pattern signatures to pos and iota.
// Note this is NOT a record of the entire floodfill! Just bookshelves.
private final Map<String, Entry> entries = new HashMap<>();
public BlockEntityAkashicRecord(BlockPos pWorldPosition, BlockState pBlockState) {
super(HexBlockEntities.AKASHIC_RECORD_TILE, pWorldPosition, pBlockState);
}
public void removeFloodfillerAt(BlockPos pos) {
// lmao just recalc everything
this.revalidateAllBookshelves();
}
/**
* @return the block position of the place it gets stored, or null if there was no room.
* <p>
* Will never clobber anything.
*/
public @Nullable
BlockPos addNewDatum(HexPattern key, Iota datum) {
String entryKey = getKey(key);
if (this.entries.containsKey(entryKey)) {
return null; // would clobber
}
var openPos = BlockAkashicFloodfiller.floodFillFor(this.worldPosition, this.level,
(pos, bs, world) -> world.getBlockEntity(pos) instanceof BlockEntityAkashicBookshelf tile
&& tile.getPattern() == null);
if (openPos != null) {
var tile = (BlockEntityAkashicBookshelf) this.level.getBlockEntity(openPos);
tile.setNewData(this.getBlockPos(), key, datum.getType());
this.entries.put(entryKey, new Entry(openPos, key.getStartDir(), datum.serializeToNBT()));
this.sync();
return openPos;
} else {
return null;
}
}
private String getKey(HexPattern key) {
String angles = key.anglesSignature();
if (angles.isEmpty()) {
return "empty"; // contains non-angle characters, so can't occur any way other than this
}
return angles;
}
public @Nullable
Iota lookupPattern(HexPattern key, ServerLevel slevel) {
var entry = this.entries.get(getKey(key));
if (entry == null) {
return null;
} else {
return LegacySpellDatum.fromNBT(entry.datum, slevel);
}
}
public Component getDisplayAt(HexPattern key) {
var entry = this.entries.get(getKey(key));
if (entry != null) {
return LegacySpellDatum.displayFromNBT(entry.datum);
} else {
return new TranslatableComponent("hexcasting.spelldata.akashic.nopos").withStyle(ChatFormatting.RED);
}
}
public int getCount() {
return this.entries.size();
}
public void revalidateAllBookshelves() {
// floodfill for all known positions
var validPoses = new HashSet<BlockPos>();
{
var seen = new HashSet<BlockPos>();
var todo = new ArrayDeque<BlockPos>();
todo.add(this.worldPosition);
// we do NOT add this position to the valid positions, because the record
// isn't flood-fillable through.
while (!todo.isEmpty()) {
var here = todo.remove();
for (var dir : Direction.values()) {
var neighbor = here.relative(dir);
if (seen.add(neighbor)) {
var bs = this.level.getBlockState(neighbor);
if (BlockAkashicFloodfiller.canItBeFloodedThrough(neighbor, bs, this.level)) {
todo.add(neighbor);
if (this.level.getBlockEntity(neighbor) instanceof BlockEntityAkashicBookshelf &&
bs.hasProperty(BlockAkashicBookshelf.DATUM_TYPE) &&
bs.getValue(BlockAkashicBookshelf.DATUM_TYPE) != DatumType.EMPTY) {
validPoses.add(neighbor);
}
}
}
}
}
}
var sigs = new ArrayList<>(this.entries.keySet());
for (var sig : sigs) {
var entry = this.entries.get(sig);
if (!validPoses.contains(entry.pos)) {
// oh no!
this.entries.remove(sig);
if (this.level.getBlockEntity(entry.pos) instanceof BlockEntityAkashicBookshelf shelf) {
shelf.setNewData(null, null, DatumType.EMPTY);
}
}
}
this.sync();
}
@Override
protected void saveModData(CompoundTag compoundTag) {
var lookupTag = new CompoundTag();
this.entries.forEach((sig, entry) -> {
var t = new CompoundTag();
t.put(TAG_POS, NbtUtils.writeBlockPos(entry.pos));
t.put(TAG_DATUM, entry.datum);
t.putByte(TAG_DIR, (byte) entry.startDir.ordinal());
lookupTag.put(sig, t);
});
compoundTag.put(TAG_LOOKUP, lookupTag);
}
@Override
protected void loadModData(CompoundTag compoundTag) {
var lookupTag = compoundTag.getCompound(TAG_LOOKUP);
this.entries.clear();
var sigs = lookupTag.getAllKeys();
for (var sig : sigs) {
var entryTag = lookupTag.getCompound(sig);
var pos = NbtUtils.readBlockPos(entryTag.getCompound(TAG_POS));
var dir = HexDir.values()[entryTag.getByte(TAG_DIR)];
var datum = entryTag.getCompound(TAG_DATUM);
this.entries.put(sig, new Entry(pos, dir, datum));
}
}
private record Entry(BlockPos pos, HexDir startDir, CompoundTag datum) {
}
}

View file

@ -2,7 +2,7 @@ package at.petrak.hexcasting.common.blocks.circles;
import at.petrak.hexcasting.annotations.SoftImplement;
import at.petrak.hexcasting.api.block.circle.BlockCircleComponent;
import at.petrak.hexcasting.api.spell.iota.Iota;
import at.petrak.hexcasting.api.spell.iota.PatternIota;
import at.petrak.hexcasting.api.spell.math.HexPattern;
import at.petrak.hexcasting.common.lib.HexItems;
import net.minecraft.core.BlockPos;
@ -102,7 +102,7 @@ public class BlockSlate extends BlockCircleComponent implements EntityBlock, Sim
if (be instanceof BlockEntitySlate slate) {
ItemStack stack = new ItemStack(HexItems.SLATE);
if (slate.pattern != null) {
HexItems.SLATE.writeDatum(stack, LegacySpellDatum.make(slate.pattern));
HexItems.SLATE.writeDatum(stack, new PatternIota(slate.pattern));
}
return stack;
}

View file

@ -8,7 +8,7 @@ import at.petrak.hexcasting.api.spell.getPattern
import at.petrak.hexcasting.api.spell.iota.Iota
import at.petrak.hexcasting.api.spell.iota.NullIota
import at.petrak.hexcasting.api.spell.mishaps.MishapNoAkashicRecord
import at.petrak.hexcasting.common.blocks.akashic.BlockEntityAkashicRecord
import at.petrak.hexcasting.common.blocks.akashic.BlockAkashicRecord
object OpAkashicRead : ConstManaAction {
override val argc = 2
@ -18,12 +18,12 @@ object OpAkashicRead : ConstManaAction {
val pos = args.getBlockPos(0, argc)
val key = args.getPattern(1, argc)
val tile = ctx.world.getBlockEntity(pos)
if (tile !is BlockEntityAkashicRecord) {
val record = ctx.world.getBlockState(pos).block
if (record !is BlockAkashicRecord) {
throw MishapNoAkashicRecord(pos)
}
val datum = tile.lookupPattern(key, ctx.world)
val datum = record.lookupPattern(pos, key, ctx.world)
return listOf(datum ?: NullIota.INSTANCE)
}
}

View file

@ -7,8 +7,9 @@ import at.petrak.hexcasting.api.spell.iota.Iota
import at.petrak.hexcasting.api.spell.math.HexPattern
import at.petrak.hexcasting.api.spell.mishaps.MishapNoAkashicRecord
import at.petrak.hexcasting.api.spell.mishaps.MishapOthersName
import at.petrak.hexcasting.common.blocks.akashic.BlockEntityAkashicRecord
import at.petrak.hexcasting.common.blocks.akashic.BlockAkashicRecord
import at.petrak.hexcasting.common.lib.HexSounds
import net.minecraft.core.BlockPos
import net.minecraft.sounds.SoundSource
object OpAkashicWrite : SpellAction {
@ -28,8 +29,8 @@ object OpAkashicWrite : SpellAction {
ctx.assertVecInRange(pos)
val tile = ctx.world.getBlockEntity(pos)
if (tile !is BlockEntityAkashicRecord) {
val record = ctx.world.getBlockState(pos).block
if (record !is BlockAkashicRecord) {
throw MishapNoAkashicRecord(pos)
}
@ -38,19 +39,24 @@ object OpAkashicWrite : SpellAction {
throw MishapOthersName(trueName)
return Triple(
Spell(tile, key, datum),
Spell(record, pos, key, datum),
ManaConstants.DUST_UNIT,
listOf()
)
}
private data class Spell(val record: BlockEntityAkashicRecord, val key: HexPattern, val datum: Iota) :
private data class Spell(
val record: BlockAkashicRecord,
val recordPos: BlockPos,
val key: HexPattern,
val datum: Iota
) :
RenderedSpell {
override fun cast(ctx: CastingContext) {
record.addNewDatum(key, datum)
record.addNewDatum(recordPos, ctx.world, key, datum)
ctx.world.playSound(
null, record.blockPos, HexSounds.SCROLL_SCRIBBLE, SoundSource.BLOCKS,
null, recordPos, HexSounds.SCROLL_SCRIBBLE, SoundSource.BLOCKS,
1f, 0.8f
)

View file

@ -1,7 +1,7 @@
package at.petrak.hexcasting.common.command;
import at.petrak.hexcasting.api.PatternRegistry;
import at.petrak.hexcasting.api.spell.iota.Iota;
import at.petrak.hexcasting.api.spell.iota.PatternIota;
import at.petrak.hexcasting.api.spell.math.HexPattern;
import at.petrak.hexcasting.common.items.ItemScroll;
import at.petrak.hexcasting.common.lib.HexItems;
@ -30,10 +30,10 @@ public class ListPatternsCommand {
ctx.getSource().sendSuccess(new TranslatableComponent("command.hexcasting.pats.listing"), false);
for (var pair : listing) {
HexPattern hexPattern = HexPattern.fromAngles(pair.getKey(), pair.getValue().getSecond());
ctx.getSource().sendSuccess(new TextComponent(pair.getValue().getFirst().toString())
.append(": ")
.append(LegacySpellDatum.make(HexPattern.fromAngles(pair.getKey(), pair.getValue().getSecond()))
.display()), false);
.append(PatternIota.display(hexPattern)), false);
}

View file

@ -1,8 +1,10 @@
package at.petrak.hexcasting.common.items;
import at.petrak.hexcasting.api.item.IotaHolderItem;
import at.petrak.hexcasting.api.spell.iota.DoubleIota;
import at.petrak.hexcasting.api.spell.iota.Iota;
import at.petrak.hexcasting.api.utils.NBTHelper;
import at.petrak.hexcasting.common.lib.HexIotaTypes;
import at.petrak.hexcasting.common.lib.HexSounds;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.network.chat.Component;
@ -27,8 +29,8 @@ public class ItemAbacus extends Item implements IotaHolderItem {
@Override
public @Nullable CompoundTag readIotaTag(ItemStack stack) {
var datum = LegacySpellDatum.make(NBTHelper.getDouble(stack, TAG_VALUE));
return datum.serializeToNBT();
var datum = new DoubleIota(NBTHelper.getDouble(stack, TAG_VALUE));
return HexIotaTypes.serialize(datum);
}
@Override

View file

@ -69,8 +69,8 @@ public class ItemScroll extends Item implements IotaHolderItem {
@Override
public void writeDatum(ItemStack stack, Iota datum) {
if (this.canWrite(stack, datum) && datum.getPayload() instanceof HexPattern pat) {
NBTHelper.putCompound(stack, TAG_PATTERN, pat.serializeToNBT());
if (this.canWrite(stack, datum) && datum instanceof PatternIota pat) {
NBTHelper.putCompound(stack, TAG_PATTERN, pat.getPattern().serializeToNBT());
}
}

View file

@ -3,12 +3,13 @@ package at.petrak.hexcasting.common.items;
import at.petrak.hexcasting.annotations.SoftImplement;
import at.petrak.hexcasting.api.HexAPI;
import at.petrak.hexcasting.api.item.IotaHolderItem;
import at.petrak.hexcasting.api.spell.DatumType;
import at.petrak.hexcasting.api.spell.iota.Iota;
import at.petrak.hexcasting.api.spell.iota.PatternIota;
import at.petrak.hexcasting.api.spell.math.HexPattern;
import at.petrak.hexcasting.api.utils.NBTHelper;
import at.petrak.hexcasting.client.gui.PatternTooltipGreeble;
import at.petrak.hexcasting.common.blocks.circles.BlockEntitySlate;
import at.petrak.hexcasting.common.lib.HexIotaTypes;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.Tag;
import net.minecraft.network.chat.Component;
@ -77,13 +78,14 @@ public class ItemSlate extends BlockItem implements IotaHolderItem {
return null;
}
var out = new CompoundTag();
out.put(LegacySpellDatum.TAG_PATTERN, patTag);
out.putString(HexIotaTypes.KEY_TYPE, "hexcasting:pattern");
out.put(HexIotaTypes.KEY_DATA, patTag);
return out;
}
@Override
public boolean canWrite(ItemStack stack, Iota datum) {
return datum == null || datum.getType() == DatumType.PATTERN;
return datum instanceof PatternIota && !NBTHelper.hasCompound(stack, BlockEntitySlate.TAG_PATTERN);
}
@Override
@ -95,9 +97,9 @@ public class ItemSlate extends BlockItem implements IotaHolderItem {
if (beTag.isEmpty()) {
NBTHelper.remove(stack, "BlockEntityTag");
}
} else if (datum.getPayload() instanceof HexPattern pat) {
} else if (datum instanceof PatternIota pat) {
var beTag = NBTHelper.getOrCreateCompound(stack, "BlockEntityTag");
beTag.put(BlockEntitySlate.TAG_PATTERN, pat.serializeToNBT());
beTag.put(BlockEntitySlate.TAG_PATTERN, pat.getPattern().serializeToNBT());
}
}
}

View file

@ -1,11 +1,11 @@
package at.petrak.hexcasting.common.items.magic;
import at.petrak.hexcasting.api.item.HexHolderItem;
import at.petrak.hexcasting.api.spell.iota.Iota;
import at.petrak.hexcasting.api.spell.casting.CastingContext;
import at.petrak.hexcasting.api.spell.casting.CastingHarness;
import at.petrak.hexcasting.api.spell.math.HexPattern;
import at.petrak.hexcasting.api.spell.iota.Iota;
import at.petrak.hexcasting.api.utils.NBTHelper;
import at.petrak.hexcasting.common.lib.HexIotaTypes;
import at.petrak.hexcasting.common.lib.HexSounds;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.ListTag;
@ -33,7 +33,7 @@ import static at.petrak.hexcasting.api.HexAPI.modLoc;
* Item that holds a list of patterns in it ready to be cast
*/
public abstract class ItemPackagedHex extends ItemMediaHolder implements HexHolderItem {
public static final String TAG_PATTERNS = "patterns";
public static final String TAG_PROGRAM = "patterns";
public static final ResourceLocation HAS_PATTERNS_PRED = modLoc("has_patterns");
public ItemPackagedHex(Properties pProperties) {
@ -54,12 +54,12 @@ public abstract class ItemPackagedHex extends ItemMediaHolder implements HexHold
@Override
public boolean hasHex(ItemStack stack) {
return NBTHelper.hasList(stack, TAG_PATTERNS, Tag.TAG_COMPOUND);
return NBTHelper.hasList(stack, TAG_PROGRAM, Tag.TAG_COMPOUND);
}
@Override
public @Nullable List<Iota> getHex(ItemStack stack, ServerLevel level) {
var patsTag = NBTHelper.getList(stack, TAG_PATTERNS, Tag.TAG_COMPOUND);
var patsTag = NBTHelper.getList(stack, TAG_PROGRAM, Tag.TAG_COMPOUND);
if (patsTag == null) {
return null;
@ -68,30 +68,26 @@ public abstract class ItemPackagedHex extends ItemMediaHolder implements HexHold
var out = new ArrayList<Iota>();
for (var patTag : patsTag) {
CompoundTag tag = NBTHelper.getAsCompound(patTag);
if (tag.size() != 1) {
out.add(LegacySpellDatum.make(HexPattern.fromNBT(tag)));
} else {
out.add(LegacySpellDatum.fromNBT(tag, level));
}
out.add(HexIotaTypes.deserialize(tag, level));
}
return out;
}
@Override
public void writeHex(ItemStack stack, List<Iota> patterns, int mana) {
public void writeHex(ItemStack stack, List<Iota> program, int mana) {
ListTag patsTag = new ListTag();
for (Iota pat : patterns) {
patsTag.add(pat.serializeToNBT());
for (Iota pat : program) {
patsTag.add(HexIotaTypes.serialize(pat));
}
NBTHelper.putList(stack, TAG_PATTERNS, patsTag);
NBTHelper.putList(stack, TAG_PROGRAM, patsTag);
withMana(stack, mana, mana);
}
@Override
public void clearHex(ItemStack stack) {
NBTHelper.remove(stack, ItemPackagedHex.TAG_PATTERNS);
NBTHelper.remove(stack, ItemPackagedHex.TAG_PROGRAM);
NBTHelper.remove(stack, TAG_MANA);
NBTHelper.remove(stack, TAG_MAX_MANA);
}

View file

@ -2,7 +2,6 @@ package at.petrak.hexcasting.common.lib;
import at.petrak.hexcasting.api.HexAPI;
import at.petrak.hexcasting.common.blocks.akashic.BlockEntityAkashicBookshelf;
import at.petrak.hexcasting.common.blocks.akashic.BlockEntityAkashicRecord;
import at.petrak.hexcasting.common.blocks.circles.BlockEntitySlate;
import at.petrak.hexcasting.common.blocks.entity.BlockEntityConjured;
import at.petrak.hexcasting.common.blocks.entity.BlockEntityLookingImpetus;
@ -37,9 +36,6 @@ public class HexBlockEntities {
public static final BlockEntityType<BlockEntityAkashicBookshelf> AKASHIC_BOOKSHELF_TILE = register(
"akashic_bookshelf_tile",
BlockEntityAkashicBookshelf::new, HexBlocks.AKASHIC_BOOKSHELF);
public static final BlockEntityType<BlockEntityAkashicRecord> AKASHIC_RECORD_TILE = register(
"akashic_record_tile",
BlockEntityAkashicRecord::new, HexBlocks.AKASHIC_RECORD);
public static final BlockEntityType<BlockEntityStoredPlayerImpetus> IMPETUS_STOREDPLAYER_TILE = register(
"impetus_storedplayer_tile",

View file

@ -1,12 +1,11 @@
package at.petrak.hexcasting.common.lib;
import at.petrak.hexcasting.api.block.circle.BlockAbstractImpetus;
import at.petrak.hexcasting.api.spell.DatumType;
import at.petrak.hexcasting.common.blocks.BlockConjured;
import at.petrak.hexcasting.common.blocks.BlockConjuredLight;
import at.petrak.hexcasting.common.blocks.BlockFlammable;
import at.petrak.hexcasting.common.blocks.akashic.BlockAkashicBookshelf;
import at.petrak.hexcasting.common.blocks.akashic.BlockAkashicFloodfiller;
import at.petrak.hexcasting.common.blocks.akashic.BlockAkashicLigature;
import at.petrak.hexcasting.common.blocks.akashic.BlockAkashicRecord;
import at.petrak.hexcasting.common.blocks.circles.BlockEmptyImpetus;
import at.petrak.hexcasting.common.blocks.circles.BlockSlate;
@ -143,9 +142,9 @@ public class HexBlocks {
new BlockAkashicRecord(akashicWoodyHard().lightLevel(bs -> 15)));
public static final BlockAkashicBookshelf AKASHIC_BOOKSHELF = blockItem("akashic_bookshelf",
new BlockAkashicBookshelf(akashicWoodyHard()
.lightLevel(bs -> (bs.getValue(BlockAkashicBookshelf.DATUM_TYPE) == DatumType.EMPTY) ? 0 : 4)));
public static final BlockAkashicFloodfiller AKASHIC_CONNECTOR = blockItem("akashic_connector",
new BlockAkashicFloodfiller(akashicWoodyHard().lightLevel(bs -> 10)));
.lightLevel(bs -> (bs.getValue(BlockAkashicBookshelf.HAS_BOOKS)) ? 4 : 0)));
public static final BlockAkashicLigature AKASHIC_LIGATURE = blockItem("akashic_connector",
new BlockAkashicLigature(akashicWoodyHard().lightLevel(bs -> 4)));
// Decoration?!
public static final Block SLATE_BLOCK = blockItem("slate_block", new Block(slateish().strength(2f, 4f)));

View file

@ -2,10 +2,10 @@ package at.petrak.hexcasting.common.network;
import at.petrak.hexcasting.api.mod.HexItemTags;
import at.petrak.hexcasting.api.mod.HexStatistics;
import at.petrak.hexcasting.api.spell.iota.Iota;
import at.petrak.hexcasting.api.spell.casting.ControllerInfo;
import at.petrak.hexcasting.api.spell.casting.ResolvedPattern;
import at.petrak.hexcasting.api.spell.casting.ResolvedPatternType;
import at.petrak.hexcasting.api.spell.iota.PatternIota;
import at.petrak.hexcasting.api.spell.math.HexCoord;
import at.petrak.hexcasting.api.spell.math.HexPattern;
import at.petrak.hexcasting.common.lib.HexSounds;
@ -89,7 +89,7 @@ public record MsgNewSpellPatternSyn(InteractionHand handUsed, HexPattern pattern
clientInfo = new ControllerInfo(false, harness.getStack().isEmpty(), ResolvedPatternType.INVALID,
harness.generateDescs());
} else {
clientInfo = harness.executeIota(LegacySpellDatum.make(this.pattern), sender.getLevel());
clientInfo = harness.executeIota(new PatternIota(this.pattern), sender.getLevel());
if (clientInfo.getMakesCastSound()) {
sender.level.playSound(null, sender.getX(), sender.getY(), sender.getZ(),

View file

@ -1,9 +1,9 @@
package at.petrak.hexcasting.common.network;
import at.petrak.hexcasting.api.spell.iota.Iota;
import at.petrak.hexcasting.api.utils.NBTHelper;
import at.petrak.hexcasting.common.items.ItemAbacus;
import at.petrak.hexcasting.common.items.ItemSpellbook;
import at.petrak.hexcasting.common.lib.HexIotaTypes;
import at.petrak.hexcasting.common.lib.HexItems;
import at.petrak.hexcasting.common.lib.HexSounds;
import io.netty.buffer.ByteBuf;
@ -123,7 +123,7 @@ public record MsgShiftScrollSyn(InteractionHand hand, double scrollDelta, boolea
var datumTag = HexItems.ABACUS.readIotaTag(stack);
if (datumTag != null) {
var popup = LegacySpellDatum.displayFromNBT(datumTag);
var popup = HexIotaTypes.getDisplay(datumTag);
sender.displayClientMessage(
new TranslatableComponent("hexcasting.tooltip.abacus", popup).withStyle(ChatFormatting.GREEN), true);
}

View file

@ -28,7 +28,7 @@ public class HexBlockTagProvider extends PaucalBlockTagProvider {
.add(HexBlocks.AMETHYST_DUST_BLOCK);
tag(BlockTags.MINEABLE_WITH_AXE)
.add(HexBlocks.AKASHIC_RECORD, HexBlocks.AKASHIC_BOOKSHELF, HexBlocks.AKASHIC_CONNECTOR,
.add(HexBlocks.AKASHIC_RECORD, HexBlocks.AKASHIC_BOOKSHELF, HexBlocks.AKASHIC_LIGATURE,
HexBlocks.AKASHIC_LOG, HexBlocks.AKASHIC_LOG_STRIPPED,
HexBlocks.AKASHIC_WOOD, HexBlocks.AKASHIC_WOOD_STRIPPED,
HexBlocks.AKASHIC_PLANKS, HexBlocks.AKASHIC_PANEL, HexBlocks.AKASHIC_TILE,

View file

@ -47,7 +47,7 @@ public class HexLootTables extends PaucalLootTableProvider {
dropSelf(blockTables, HexBlocks.EMPTY_IMPETUS,
HexBlocks.IMPETUS_RIGHTCLICK, HexBlocks.IMPETUS_LOOK, HexBlocks.IMPETUS_STOREDPLAYER,
HexBlocks.DIRECTRIX_REDSTONE, HexBlocks.EMPTY_DIRECTRIX,
HexBlocks.AKASHIC_RECORD, HexBlocks.AKASHIC_BOOKSHELF, HexBlocks.AKASHIC_CONNECTOR,
HexBlocks.AKASHIC_RECORD, HexBlocks.AKASHIC_BOOKSHELF, HexBlocks.AKASHIC_LIGATURE,
HexBlocks.SLATE_BLOCK, HexBlocks.AMETHYST_DUST_BLOCK, HexBlocks.AMETHYST_TILES, HexBlocks.SCROLL_PAPER,
HexBlocks.ANCIENT_SCROLL_PAPER, HexBlocks.SCROLL_PAPER_LANTERN, HexBlocks.ANCIENT_SCROLL_PAPER_LANTERN,
HexBlocks.SCONCE,

View file

@ -315,7 +315,7 @@ public class HexplatRecipes extends PaucalRecipeProvider {
.pattern("CCC")
.pattern("LPL")
.unlockedBy("enlightenment", enlightenment).save(recipes);
ShapedRecipeBuilder.shaped(HexBlocks.AKASHIC_CONNECTOR)
ShapedRecipeBuilder.shaped(HexBlocks.AKASHIC_LIGATURE)
.define('L', HexItemTags.AKASHIC_LOGS)
.define('P', HexItemTags.AKASHIC_PLANKS)
.define('C', HexItems.CHARGED_AMETHYST)
@ -352,7 +352,7 @@ public class HexplatRecipes extends PaucalRecipeProvider {
.unlockedBy("enlightenment", enlightenment)
.save(recipes, modLoc("brainsweep/directrix_redstone"));
new BrainsweepRecipeBuilder(StateIngredientHelper.of(HexBlocks.AKASHIC_CONNECTOR),
new BrainsweepRecipeBuilder(StateIngredientHelper.of(HexBlocks.AKASHIC_LIGATURE),
new VillagerIngredient(new ResourceLocation("librarian"), null, 5),
HexBlocks.AKASHIC_RECORD.defaultBlockState())
.unlockedBy("enlightenment", enlightenment)

View file

@ -126,7 +126,7 @@ public class HexBlockStatesAndModels extends PaucalBlockStateAndModelProvider {
var akashicRecordModel = models().getExistingFile(modLoc("block/akashic_record"));
simpleBlock(HexBlocks.AKASHIC_RECORD, akashicRecordModel);
simpleBlockItem(HexBlocks.AKASHIC_RECORD, akashicRecordModel);
blockAndItem(HexBlocks.AKASHIC_CONNECTOR,
blockAndItem(HexBlocks.AKASHIC_LIGATURE,
models().cubeAll("akashic_connector", modLoc("block/akashic/connector")));
getVariantBuilder(HexBlocks.AKASHIC_BOOKSHELF).forAllStates(bs -> {