package com.minelittlepony.unicopia.container; import java.util.*; import java.util.function.Consumer; import com.minelittlepony.unicopia.network.datasync.Synchronizable; import com.minelittlepony.unicopia.util.NbtSerialisable; import net.minecraft.nbt.NbtCompound; import net.minecraft.nbt.NbtElement; import net.minecraft.network.PacketByteBuf; import net.minecraft.util.Identifier; import net.minecraft.util.math.MathHelper; public class SpellbookState extends Synchronizable implements NbtSerialisable { private Optional currentPageId = Optional.empty(); private boolean dirty; private final Map states = new HashMap<>(); public boolean isDirty() { boolean isDirty = dirty; dirty = false; return isDirty; } public Optional getCurrentPageId() { return currentPageId; } public void setCurrentPageId(Identifier pageId) { currentPageId = Optional.ofNullable(pageId); synchronize(); } public PageState getState(Identifier pageId) { return states.computeIfAbsent(pageId, i -> new PageState(page -> synchronize())); } @Override public void copyFrom(SpellbookState state) { currentPageId = state.currentPageId; state.states.forEach((id, page) -> getState(id).copyFrom(page)); dirty = true; } public void toPacket(PacketByteBuf buf) { buf.writeOptional(currentPageId, PacketByteBuf::writeIdentifier); buf.writeMap(states, PacketByteBuf::writeIdentifier, (b, v) -> v.toPacket(b)); } public SpellbookState fromPacket(PacketByteBuf buf) { currentPageId = buf.readOptional(PacketByteBuf::readIdentifier); buf.readMap(PacketByteBuf::readIdentifier, b -> new PageState(page -> synchronize()).fromPacket(b)).forEach((id, state) -> { getState(id).copyFrom(state); }); return this; } @Override public void toNBT(NbtCompound compound) { currentPageId.ifPresent(id -> compound.putString("current_page", id.toString())); NbtCompound states = new NbtCompound(); compound.put("states", states); this.states.forEach((id, page) -> { states.put(id.toString(), page.toNBT()); }); } @Override public void fromNBT(NbtCompound compound) { currentPageId = compound.contains("current_page", NbtElement.STRING_TYPE) ? Optional.ofNullable(Identifier.tryParse(compound.getString("current_page"))) : Optional.empty(); NbtCompound states = compound.getCompound("states"); states.getKeys().stream().forEach(key -> { Identifier id = Identifier.tryParse(key); if (id != null) { getState(id).fromNBT(states.getCompound(key)); } }); } public static class PageState extends Synchronizable implements NbtSerialisable { private int offset; public PageState() {} PageState(Consumer synchronizer) { setSynchronizer(synchronizer); } @Override public void copyFrom(PageState other) { offset = other.offset; } public void setOffset(int offset) { this.offset = offset; synchronize(); } public int getOffset() { return offset; } public void swap(int incr, int max) { setOffset(MathHelper.clamp(getOffset() + incr, 0, max - 1)); } public void toPacket(PacketByteBuf buf) { buf.writeInt(offset); } public PageState fromPacket(PacketByteBuf buf) { offset = buf.readInt(); return this; } @Override public void toNBT(NbtCompound compound) { compound.putInt("offset", offset); } @Override public void fromNBT(NbtCompound compound) { offset = compound.getInt("offset"); } } }