kotlin now compiles! ... now onto java
This commit is contained in:
parent
8b7369fe8b
commit
434c480b0b
25 changed files with 260 additions and 458 deletions
|
@ -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;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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?
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
}
|
||||
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
)
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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)));
|
||||
|
|
|
@ -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(),
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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 -> {
|
||||
|
|
Loading…
Reference in a new issue