mirror of
https://github.com/Sollace/Unicopia.git
synced 2024-11-27 15:17:59 +01:00
Refactor chapters and fix packet serializing error
This commit is contained in:
parent
0e2b0bcc34
commit
e3a8d0cd13
19 changed files with 448 additions and 391 deletions
|
@ -7,7 +7,7 @@ import java.util.UUID;
|
|||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import com.minelittlepony.unicopia.container.SpellbookChapter;
|
||||
import com.minelittlepony.unicopia.container.spellbook.SpellbookChapter;
|
||||
import com.minelittlepony.unicopia.entity.player.Pony;
|
||||
import com.minelittlepony.unicopia.entity.player.dummy.DummyPlayerEntity;
|
||||
import com.minelittlepony.unicopia.particle.ParticleSpawner;
|
||||
|
|
|
@ -18,8 +18,8 @@ import com.minelittlepony.unicopia.block.UBlocks;
|
|||
import com.minelittlepony.unicopia.block.state.StateMapLoader;
|
||||
import com.minelittlepony.unicopia.command.Commands;
|
||||
import com.minelittlepony.unicopia.compat.trinkets.TrinketsDelegate;
|
||||
import com.minelittlepony.unicopia.container.SpellbookChapterLoader;
|
||||
import com.minelittlepony.unicopia.container.UScreenHandlers;
|
||||
import com.minelittlepony.unicopia.container.spellbook.SpellbookChapterLoader;
|
||||
import com.minelittlepony.unicopia.diet.DietsLoader;
|
||||
import com.minelittlepony.unicopia.diet.affliction.AfflictionType;
|
||||
import com.minelittlepony.unicopia.entity.damage.UDamageTypes;
|
||||
|
|
|
@ -19,7 +19,7 @@ import com.minelittlepony.unicopia.client.gui.DismissSpellScreen;
|
|||
import com.minelittlepony.unicopia.client.gui.spellbook.ClientChapters;
|
||||
import com.minelittlepony.unicopia.client.particle.ClientBoundParticleSpawner;
|
||||
import com.minelittlepony.unicopia.client.sound.*;
|
||||
import com.minelittlepony.unicopia.container.SpellbookChapter;
|
||||
import com.minelittlepony.unicopia.container.spellbook.SpellbookChapter;
|
||||
import com.minelittlepony.unicopia.entity.Living;
|
||||
import com.minelittlepony.unicopia.entity.player.PlayerPhysics;
|
||||
import com.minelittlepony.unicopia.entity.player.Pony;
|
||||
|
|
|
@ -3,7 +3,8 @@ package com.minelittlepony.unicopia.client.gui.spellbook;
|
|||
import java.util.*;
|
||||
import com.minelittlepony.unicopia.client.gui.spellbook.SpellbookChapterList.*;
|
||||
import com.minelittlepony.unicopia.client.gui.spellbook.element.DynamicContent;
|
||||
import com.minelittlepony.unicopia.container.SpellbookChapter;
|
||||
import com.minelittlepony.unicopia.container.spellbook.SpellbookChapter;
|
||||
import com.minelittlepony.unicopia.container.spellbook.TabSide;
|
||||
|
||||
import net.minecraft.network.PacketByteBuf;
|
||||
import net.minecraft.util.*;
|
||||
|
@ -26,7 +27,7 @@ public class ClientChapters {
|
|||
buffer.readEnumConstant(TabSide.class),
|
||||
buffer.readInt(),
|
||||
buffer.readInt(),
|
||||
buffer.readOptional(DynamicContent::new)
|
||||
Optional.of(new DynamicContent(buffer))
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,7 +6,8 @@ import java.util.stream.Stream;
|
|||
|
||||
import com.minelittlepony.common.client.gui.IViewRoot;
|
||||
import com.minelittlepony.unicopia.Debug;
|
||||
import com.minelittlepony.unicopia.container.SpellbookChapter;
|
||||
import com.minelittlepony.unicopia.container.spellbook.SpellbookChapter;
|
||||
import com.minelittlepony.unicopia.container.spellbook.TabSide;
|
||||
|
||||
import net.minecraft.client.gui.DrawContext;
|
||||
import net.minecraft.util.Identifier;
|
||||
|
@ -59,11 +60,6 @@ public class SpellbookChapterList {
|
|||
}
|
||||
}
|
||||
|
||||
public enum TabSide {
|
||||
LEFT,
|
||||
RIGHT
|
||||
}
|
||||
|
||||
public interface Content extends Drawable {
|
||||
void init(SpellbookScreen screen, Identifier pageId);
|
||||
|
||||
|
|
|
@ -19,6 +19,7 @@ import com.minelittlepony.unicopia.client.gui.spellbook.SpellbookChapterList.*;
|
|||
import com.minelittlepony.unicopia.compat.trinkets.TrinketSlotBackSprites;
|
||||
import com.minelittlepony.unicopia.container.*;
|
||||
import com.minelittlepony.unicopia.container.inventory.*;
|
||||
import com.minelittlepony.unicopia.container.spellbook.TabSide;
|
||||
import com.minelittlepony.unicopia.network.Channel;
|
||||
import com.minelittlepony.unicopia.network.MsgSpellbookStateChanged;
|
||||
import com.mojang.blaze3d.platform.GlStateManager;
|
||||
|
|
|
@ -6,7 +6,7 @@ import java.util.stream.Stream;
|
|||
|
||||
import com.minelittlepony.common.client.gui.dimension.Bounds;
|
||||
import com.minelittlepony.unicopia.client.gui.spellbook.SpellbookChapterList.Chapter;
|
||||
import com.minelittlepony.unicopia.client.gui.spellbook.SpellbookChapterList.TabSide;
|
||||
import com.minelittlepony.unicopia.container.spellbook.TabSide;
|
||||
|
||||
import net.minecraft.util.Identifier;
|
||||
|
||||
|
|
|
@ -9,8 +9,8 @@ import com.minelittlepony.unicopia.client.gui.MagicText;
|
|||
import com.minelittlepony.unicopia.client.gui.spellbook.SpellbookScreen;
|
||||
import com.minelittlepony.unicopia.client.gui.spellbook.SpellbookChapterList.Content;
|
||||
import com.minelittlepony.unicopia.client.gui.spellbook.SpellbookChapterList.Drawable;
|
||||
import com.minelittlepony.unicopia.container.SpellbookChapterLoader.Flow;
|
||||
import com.minelittlepony.unicopia.container.SpellbookState;
|
||||
import com.minelittlepony.unicopia.container.spellbook.Flow;
|
||||
import com.minelittlepony.unicopia.entity.player.Pony;
|
||||
import net.minecraft.client.MinecraftClient;
|
||||
import net.minecraft.client.gui.DrawContext;
|
||||
|
|
|
@ -2,7 +2,7 @@ package com.minelittlepony.unicopia.client.gui.spellbook.element;
|
|||
|
||||
import com.minelittlepony.common.client.gui.IViewRoot;
|
||||
import com.minelittlepony.common.client.gui.dimension.Bounds;
|
||||
import com.minelittlepony.unicopia.container.SpellbookChapterLoader.Flow;
|
||||
import com.minelittlepony.unicopia.container.spellbook.Flow;
|
||||
|
||||
import net.minecraft.client.gui.DrawContext;
|
||||
import net.minecraft.util.Identifier;
|
||||
|
|
|
@ -12,7 +12,9 @@ import com.minelittlepony.unicopia.ability.magic.spell.effect.SpellType;
|
|||
import com.minelittlepony.unicopia.ability.magic.spell.trait.Trait;
|
||||
import com.minelittlepony.unicopia.block.state.Schematic;
|
||||
import com.minelittlepony.unicopia.client.gui.spellbook.SpellbookChapterList.Drawable;
|
||||
import com.minelittlepony.unicopia.container.SpellbookChapterLoader.Flow;
|
||||
import com.minelittlepony.unicopia.container.spellbook.ChapterPageElement;
|
||||
import com.minelittlepony.unicopia.container.spellbook.Flow;
|
||||
|
||||
import net.minecraft.client.gui.DrawContext;
|
||||
import net.minecraft.network.PacketByteBuf;
|
||||
import net.minecraft.network.RegistryByteBuf;
|
||||
|
@ -45,24 +47,22 @@ public interface PageElement extends Drawable {
|
|||
static PageElement read(DynamicContent.Page page, PacketByteBuf buffer) {
|
||||
byte type = buffer.readByte();
|
||||
return switch (type) {
|
||||
case 0 -> new Image(buffer.readIdentifier(), boundsFromBuffer(buffer), buffer.readEnumConstant(Flow.class));
|
||||
case 1 -> new Recipe(page, buffer.readIdentifier(), Bounds.empty());
|
||||
case 2 -> new Stack(page, IngredientWithSpell.PACKET_CODEC.decode((RegistryByteBuf)buffer), boundsFromBuffer(buffer));
|
||||
case 3 -> new TextBlock(page, List.of(Suppliers.ofInstance(TextCodecs.PACKET_CODEC.decode(buffer))));
|
||||
case 4 -> new TextBlock(page, buffer.readList(b -> {
|
||||
case ChapterPageElement.IMAGE -> new Image(buffer.readIdentifier(), boundsFromBuffer(buffer), buffer.readEnumConstant(Flow.class));
|
||||
case ChapterPageElement.RECIPE -> new Recipe(page, buffer.readIdentifier(), Bounds.empty());
|
||||
case ChapterPageElement.STACK -> new Stack(page, IngredientWithSpell.PACKET_CODEC.decode((RegistryByteBuf)buffer), boundsFromBuffer(buffer));
|
||||
case ChapterPageElement.TEXT_BLOCK -> new TextBlock(page, List.of(Suppliers.ofInstance(TextCodecs.PACKET_CODEC.decode(buffer))));
|
||||
case ChapterPageElement.INGREDIENTS -> new TextBlock(page, buffer.readList(b -> {
|
||||
int count = b.readVarInt();
|
||||
byte t = b.readByte();
|
||||
return switch (t) {
|
||||
case 1 -> formatLine(capture(b.readIdentifier(), id -> {
|
||||
return Registries.ITEM.get(id).getDefaultStack().getName();
|
||||
}), "item", count);
|
||||
case 1 -> formatLine(capture(b.readIdentifier(), id -> Registries.ITEM.get(id).getDefaultStack().getName()), "item", count);
|
||||
case 2 -> formatLine(Trait.PACKET_CODEC.decode(b)::getShortName, "trait", count);
|
||||
case 3 -> Suppliers.ofInstance(TextCodecs.PACKET_CODEC.decode(b));
|
||||
case 4 -> formatLine(SpellType.getKey(b.readIdentifier())::getName, "spell", count);
|
||||
default -> throw new IllegalArgumentException("Unexpected value: " + t);
|
||||
};
|
||||
}));
|
||||
case 5 -> new Structure(Bounds.empty(), Schematic.fromPacket(buffer));
|
||||
case ChapterPageElement.STRUCTURE -> new Structure(Bounds.empty(), Schematic.fromPacket(buffer));
|
||||
default -> throw new IllegalArgumentException("Unexpected value: " + type);
|
||||
};
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@ import java.util.function.Supplier;
|
|||
import com.minelittlepony.common.client.gui.IViewRoot;
|
||||
import com.minelittlepony.common.client.gui.dimension.Bounds;
|
||||
import com.minelittlepony.unicopia.client.gui.ParagraphWrappingVisitor;
|
||||
import com.minelittlepony.unicopia.container.SpellbookChapterLoader.Flow;
|
||||
import com.minelittlepony.unicopia.container.spellbook.Flow;
|
||||
import com.minelittlepony.unicopia.entity.player.Pony;
|
||||
|
||||
import net.minecraft.client.MinecraftClient;
|
||||
|
|
|
@ -1,362 +0,0 @@
|
|||
package com.minelittlepony.unicopia.container;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.concurrent.*;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.StreamSupport;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
|
||||
import com.google.gson.*;
|
||||
import com.minelittlepony.common.client.gui.dimension.Bounds;
|
||||
import com.minelittlepony.unicopia.Debug;
|
||||
import com.minelittlepony.unicopia.Unicopia;
|
||||
import com.minelittlepony.unicopia.ability.magic.spell.crafting.IngredientWithSpell;
|
||||
import com.minelittlepony.unicopia.ability.magic.spell.trait.Trait;
|
||||
import com.minelittlepony.unicopia.block.state.StateUtil;
|
||||
import com.minelittlepony.unicopia.client.gui.spellbook.SpellbookChapterList.*;
|
||||
import com.minelittlepony.unicopia.network.Channel;
|
||||
import com.minelittlepony.unicopia.network.MsgServerResources;
|
||||
import com.minelittlepony.unicopia.util.Resources;
|
||||
import com.mojang.logging.LogUtils;
|
||||
import com.mojang.serialization.JsonOps;
|
||||
|
||||
import net.fabricmc.fabric.api.resource.IdentifiableResourceReloadListener;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.network.PacketByteBuf;
|
||||
import net.minecraft.network.RegistryByteBuf;
|
||||
import net.minecraft.registry.DynamicRegistryManager;
|
||||
import net.minecraft.resource.JsonDataLoader;
|
||||
import net.minecraft.resource.ResourceManager;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.text.Text;
|
||||
import net.minecraft.text.TextCodecs;
|
||||
import net.minecraft.text.TextColor;
|
||||
import net.minecraft.util.*;
|
||||
import net.minecraft.util.profiler.Profiler;
|
||||
|
||||
public class SpellbookChapterLoader extends JsonDataLoader implements IdentifiableResourceReloadListener {
|
||||
private static final Logger LOGGER = LogUtils.getLogger();
|
||||
private static final Identifier ID = Unicopia.id("spellbook/chapters");
|
||||
private static final Executor EXECUTOR = CompletableFuture.delayedExecutor(5, TimeUnit.SECONDS);
|
||||
|
||||
public static final SpellbookChapterLoader INSTANCE = new SpellbookChapterLoader();
|
||||
|
||||
private boolean dirty;
|
||||
private Map<Identifier, SpellbookChapter> chapters = new HashMap<>();
|
||||
|
||||
public SpellbookChapterLoader() {
|
||||
super(Resources.GSON, ID.getPath());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Identifier getFabricId() {
|
||||
return ID;
|
||||
}
|
||||
|
||||
public Map<Identifier, SpellbookChapter> getChapters() {
|
||||
return chapters;
|
||||
}
|
||||
|
||||
public void sendUpdate(MinecraftServer server) {
|
||||
if (dirty) {
|
||||
dirty = false;
|
||||
Channel.SERVER_RESOURCES.sendToAllPlayers(new MsgServerResources(), server);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void apply(Map<Identifier, JsonElement> data, ResourceManager manager, Profiler profiler) {
|
||||
try {
|
||||
chapters = data.entrySet().stream().collect(Collectors.toMap(
|
||||
Map.Entry::getKey,
|
||||
entry -> new Chapter(entry.getKey(), JsonHelper.asObject(entry.getValue(), "root"))
|
||||
));
|
||||
} catch (IllegalStateException | JsonParseException e) {
|
||||
LOGGER.error("Could not load spellbook chapters due to exception", e);
|
||||
}
|
||||
|
||||
if (Debug.SPELLBOOK_CHAPTERS) {
|
||||
CompletableFuture.runAsync(() -> {
|
||||
try {
|
||||
Util.waitAndApply(executor -> reload(CompletableFuture::completedFuture, manager, profiler, profiler, Util.getMainWorkerExecutor(), executor)).get();
|
||||
} catch (InterruptedException | ExecutionException e) {
|
||||
}
|
||||
dirty = true;
|
||||
}, EXECUTOR);
|
||||
}
|
||||
}
|
||||
|
||||
private static Text readText(JsonElement json) {
|
||||
return json.isJsonPrimitive() ? Text.translatable(json.getAsString()) : Text.Serialization.fromJsonTree(json, DynamicRegistryManager.EMPTY);
|
||||
}
|
||||
|
||||
public enum Flow {
|
||||
NONE, LEFT, RIGHT
|
||||
}
|
||||
|
||||
public record Chapter (
|
||||
Identifier id,
|
||||
TabSide side,
|
||||
int tabY,
|
||||
int color,
|
||||
List<Page> pages) implements SpellbookChapter {
|
||||
@Deprecated
|
||||
public Chapter(Identifier id, JsonObject json) {
|
||||
this(id,
|
||||
TabSide.valueOf(JsonHelper.getString(json, "side")),
|
||||
JsonHelper.getInt(json, "y_position"),
|
||||
JsonHelper.getInt(json, "color", 0),
|
||||
loadContent(JsonHelper.getObject(json, "content", new JsonObject()))
|
||||
);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
private static List<Page> loadContent(JsonObject json) {
|
||||
return Optional.of(JsonHelper.getArray(json, "pages", new JsonArray()))
|
||||
.filter(pages -> pages.size() > 0)
|
||||
.stream()
|
||||
.flatMap(pages -> StreamSupport.stream(pages.spliterator(), false))
|
||||
.map(Page::of)
|
||||
.toList();
|
||||
}
|
||||
|
||||
public void write(RegistryByteBuf buffer) {
|
||||
buffer.writeIdentifier(id);
|
||||
buffer.writeEnumConstant(side);
|
||||
buffer.writeInt(tabY);
|
||||
buffer.writeInt(color);
|
||||
buffer.writeBoolean(true);
|
||||
buffer.writeCollection(pages, Page::write);
|
||||
}
|
||||
}
|
||||
|
||||
private record Page (
|
||||
Text title,
|
||||
int level,
|
||||
int color,
|
||||
List<Element> elements
|
||||
) {
|
||||
private static final Page EMPTY = new Page(Text.empty(), 0, 0, List.of());
|
||||
|
||||
public static Page of(JsonElement json) {
|
||||
return json.isJsonObject() && json.getAsJsonObject().keySet().isEmpty() ? EMPTY : new Page(json);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
Page(JsonElement json) {
|
||||
this(json.getAsJsonObject());
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
Page(JsonObject json) {
|
||||
this(
|
||||
readText(json.get("title")),
|
||||
JsonHelper.getInt(json, "level", 0),
|
||||
TextColor.parse(JsonHelper.getString(json, "color", "")).result().map(TextColor::getRgb).orElse(0),
|
||||
new ArrayList<>()
|
||||
);
|
||||
JsonHelper.getArray(json, "elements", new JsonArray()).forEach(element -> {
|
||||
elements.add(Element.read(element));
|
||||
});
|
||||
}
|
||||
|
||||
public void toBuffer(RegistryByteBuf buffer) {
|
||||
TextCodecs.PACKET_CODEC.encode(buffer, title);
|
||||
buffer.writeInt(level);
|
||||
buffer.writeInt(color);
|
||||
buffer.writeCollection(elements, Element::write);
|
||||
}
|
||||
|
||||
public static void write(PacketByteBuf buffer, Page page) {
|
||||
page.toBuffer((RegistryByteBuf)buffer);
|
||||
}
|
||||
}
|
||||
|
||||
private interface Element {
|
||||
void toBuffer(RegistryByteBuf buffer);
|
||||
|
||||
record Image (Identifier texture, Bounds bounds, Flow flow) implements Element {
|
||||
@Override
|
||||
public void toBuffer(RegistryByteBuf buffer) {
|
||||
buffer.writeByte(0);
|
||||
buffer.writeIdentifier(texture);
|
||||
boundsToBuffer(bounds, buffer);
|
||||
buffer.writeEnumConstant(flow);
|
||||
}
|
||||
}
|
||||
|
||||
record Multi(int count, Element element) implements Element {
|
||||
@Override
|
||||
public void toBuffer(RegistryByteBuf buffer) {
|
||||
buffer.writeVarInt(count);
|
||||
element.toBuffer(buffer);
|
||||
}
|
||||
}
|
||||
|
||||
record Id(byte id, Identifier value) implements Element {
|
||||
@Override
|
||||
public void toBuffer(RegistryByteBuf buffer) {
|
||||
buffer.writeByte(id);
|
||||
buffer.writeIdentifier(value);
|
||||
}
|
||||
}
|
||||
|
||||
record Stack (IngredientWithSpell ingredient, Bounds bounds) implements Element {
|
||||
@Override
|
||||
public void toBuffer(RegistryByteBuf buffer) {
|
||||
buffer.writeByte(2);
|
||||
IngredientWithSpell.PACKET_CODEC.encode(buffer, ingredient);
|
||||
boundsToBuffer(bounds, buffer);
|
||||
}
|
||||
}
|
||||
|
||||
record TextBlock (Text text) implements Element {
|
||||
@Override
|
||||
public void toBuffer(RegistryByteBuf buffer) {
|
||||
buffer.writeByte(3);
|
||||
TextCodecs.PACKET_CODEC.encode(buffer, text);
|
||||
}
|
||||
}
|
||||
|
||||
record Structure(List<Element> commands) implements Element {
|
||||
static Element loadCommand(JsonObject json) {
|
||||
|
||||
if (json.has("pos")) {
|
||||
var pos = JsonHelper.getArray(json, "pos");
|
||||
return new Set(
|
||||
pos.get(0).getAsInt(), pos.get(1).getAsInt(), pos.get(2).getAsInt(),
|
||||
StateUtil.stateFromString(json.get("state").getAsString())
|
||||
);
|
||||
}
|
||||
|
||||
var min = JsonHelper.getArray(json, "min");
|
||||
var max = JsonHelper.getArray(json, "max");
|
||||
return new Fill(
|
||||
min.get(0).getAsInt(), min.get(1).getAsInt(), min.get(2).getAsInt(),
|
||||
max.get(0).getAsInt(), max.get(1).getAsInt(), max.get(2).getAsInt(),
|
||||
StateUtil.stateFromString(json.get("state").getAsString())
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void toBuffer(RegistryByteBuf buffer) {
|
||||
buffer.writeByte(5);
|
||||
buffer.writeCollection(commands, (b, c) -> c.toBuffer(buffer));
|
||||
}
|
||||
|
||||
record Set(int x, int y, int z, BlockState state) implements Element {
|
||||
@Override
|
||||
public void toBuffer(RegistryByteBuf buffer) {
|
||||
buffer.writeByte(1);
|
||||
buffer.writeInt(x);
|
||||
buffer.writeInt(y);
|
||||
buffer.writeInt(z);
|
||||
buffer.writeInt(Block.getRawIdFromState(state));
|
||||
}
|
||||
|
||||
}
|
||||
record Fill(int x1, int y1, int z1, int x2, int y2, int z2, BlockState state) implements Element {
|
||||
@Override
|
||||
public void toBuffer(RegistryByteBuf buffer) {
|
||||
buffer.writeByte(2);
|
||||
buffer.writeInt(x1);
|
||||
buffer.writeInt(y1);
|
||||
buffer.writeInt(z1);
|
||||
buffer.writeInt(x2);
|
||||
buffer.writeInt(y2);
|
||||
buffer.writeInt(z2);
|
||||
buffer.writeInt(Block.getRawIdFromState(state));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
record Ingredients(List<Element> entries) implements Element {
|
||||
@Deprecated
|
||||
static Element loadIngredient(JsonObject json) {
|
||||
int count = JsonHelper.getInt(json, "count", 1);
|
||||
if (json.has("item")) {
|
||||
return new Multi(count, new Id((byte)1, Identifier.tryParse(json.get("item").getAsString())));
|
||||
}
|
||||
|
||||
if (json.has("trait")) {
|
||||
return new Multi(count, new Id((byte)2, Trait.fromId(json.get("trait").getAsString()).orElseThrow().getId()));
|
||||
}
|
||||
|
||||
if (json.has("spell")) {
|
||||
return new Multi(count, new Id((byte)4, Identifier.tryParse(json.get("spell").getAsString())));
|
||||
}
|
||||
|
||||
return new Multi(count, new TextBlock(readText(json.get("text"))));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void toBuffer(RegistryByteBuf buffer) {
|
||||
buffer.writeByte(4);
|
||||
buffer.writeCollection(entries, (b, c) -> c.toBuffer(buffer));
|
||||
}
|
||||
}
|
||||
|
||||
static void write(PacketByteBuf buffer, Element element) {
|
||||
element.toBuffer((RegistryByteBuf)buffer);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
static Element read(JsonElement json) {
|
||||
if (!json.isJsonPrimitive()) {
|
||||
JsonObject el = JsonHelper.asObject(json, "element");
|
||||
if (el.has("texture")) {
|
||||
return new Image(
|
||||
Identifier.of(JsonHelper.getString(el, "texture")),
|
||||
boundsFromJson(el),
|
||||
Flow.valueOf(JsonHelper.getString(el, "flow", "RIGHT"))
|
||||
);
|
||||
}
|
||||
|
||||
if (el.has("recipe")) {
|
||||
return new Id((byte)1, Identifier.of(JsonHelper.getString(el, "recipe")));
|
||||
}
|
||||
|
||||
if (el.has("item")) {
|
||||
return new Stack(IngredientWithSpell.CODEC.decode(JsonOps.INSTANCE, el.get("item")).result().get().getFirst(), boundsFromJson(el));
|
||||
}
|
||||
|
||||
if (el.has("ingredients")) {
|
||||
return new Ingredients(JsonHelper.getArray(el, "ingredients").asList().stream()
|
||||
.map(JsonElement::getAsJsonObject)
|
||||
.map(Ingredients::loadIngredient)
|
||||
.toList()
|
||||
);
|
||||
}
|
||||
|
||||
if (el.has("structure")) {
|
||||
return new Structure(JsonHelper.getArray(el, "structure").asList().stream()
|
||||
.map(JsonElement::getAsJsonObject)
|
||||
.map(Structure::loadCommand)
|
||||
.toList()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return new TextBlock(readText(json));
|
||||
}
|
||||
|
||||
private static Bounds boundsFromJson(JsonObject el) {
|
||||
return new Bounds(
|
||||
JsonHelper.getInt(el, "y", 0),
|
||||
JsonHelper.getInt(el, "x", 0),
|
||||
JsonHelper.getInt(el, "width", 0),
|
||||
JsonHelper.getInt(el, "height", 0)
|
||||
);
|
||||
}
|
||||
|
||||
private static void boundsToBuffer(Bounds bounds, PacketByteBuf buffer) {
|
||||
buffer.writeInt(bounds.top);
|
||||
buffer.writeInt(bounds.left);
|
||||
buffer.writeInt(bounds.width);
|
||||
buffer.writeInt(bounds.height);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,63 @@
|
|||
package com.minelittlepony.unicopia.container.spellbook;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.mojang.serialization.Codec;
|
||||
import com.mojang.serialization.codecs.RecordCodecBuilder;
|
||||
|
||||
import net.minecraft.network.PacketByteBuf;
|
||||
import net.minecraft.network.RegistryByteBuf;
|
||||
import net.minecraft.text.Text;
|
||||
import net.minecraft.text.TextCodecs;
|
||||
import net.minecraft.text.TextColor;
|
||||
|
||||
public record Chapter (
|
||||
TabSide side,
|
||||
int tabY,
|
||||
int color,
|
||||
Chapter.Contents contents) {
|
||||
public static final Codec<Chapter> CODEC = RecordCodecBuilder.create(instance -> instance.group(
|
||||
TabSide.CODEC.fieldOf("side").forGetter(Chapter::side),
|
||||
Codec.INT.fieldOf("y_position").forGetter(Chapter::tabY),
|
||||
Codec.INT.optionalFieldOf("color", 0).forGetter(Chapter::color),
|
||||
Contents.CODEC.fieldOf("contents").forGetter(Chapter::contents)
|
||||
).apply(instance, Chapter::new));
|
||||
|
||||
record Contents(List<Page> pages) {
|
||||
public static final Codec<Chapter.Contents> CODEC = RecordCodecBuilder.create(instance -> instance.group(
|
||||
Page.CODEC.listOf().fieldOf("pages").forGetter(Contents::pages)
|
||||
).apply(instance, Chapter.Contents::new));
|
||||
|
||||
public record Page (
|
||||
Text title,
|
||||
int level,
|
||||
int color,
|
||||
List<ChapterPageElement> elements
|
||||
) {
|
||||
public static final Codec<Page> CODEC = RecordCodecBuilder.create(instance -> instance.group(
|
||||
TextCodecs.CODEC.fieldOf("title").forGetter(Page::title),
|
||||
Codec.INT.fieldOf("level").forGetter(Page::level),
|
||||
TextColor.CODEC.fieldOf("color").xmap(TextColor::getRgb, TextColor::fromRgb).forGetter(Page::level),
|
||||
ChapterPageElement.CODEC.listOf().fieldOf("elements").forGetter(Page::elements)
|
||||
).apply(instance, Page::new));
|
||||
|
||||
public void toBuffer(RegistryByteBuf buffer) {
|
||||
TextCodecs.PACKET_CODEC.encode(buffer, title);
|
||||
buffer.writeInt(level);
|
||||
buffer.writeInt(color);
|
||||
buffer.writeCollection(elements, ChapterPageElement::write);
|
||||
}
|
||||
|
||||
public static void write(PacketByteBuf buffer, Page page) {
|
||||
page.toBuffer((RegistryByteBuf)buffer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void write(RegistryByteBuf buffer) {
|
||||
buffer.writeEnumConstant(side);
|
||||
buffer.writeInt(tabY);
|
||||
buffer.writeInt(color);
|
||||
buffer.writeCollection(contents.pages(), Contents.Page::write);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,219 @@
|
|||
package com.minelittlepony.unicopia.container.spellbook;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.minelittlepony.common.client.gui.dimension.Bounds;
|
||||
import com.minelittlepony.unicopia.ability.magic.spell.crafting.IngredientWithSpell;
|
||||
import com.minelittlepony.unicopia.ability.magic.spell.trait.Trait;
|
||||
import com.minelittlepony.unicopia.block.state.StateUtil;
|
||||
import com.mojang.serialization.Codec;
|
||||
import com.mojang.serialization.JsonOps;
|
||||
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.network.PacketByteBuf;
|
||||
import net.minecraft.network.RegistryByteBuf;
|
||||
import net.minecraft.registry.DynamicRegistryManager;
|
||||
import net.minecraft.text.Text;
|
||||
import net.minecraft.text.TextCodecs;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.JsonHelper;
|
||||
import net.minecraft.util.dynamic.Codecs;
|
||||
|
||||
public interface ChapterPageElement {
|
||||
byte IMAGE = 0;
|
||||
byte RECIPE = 1;
|
||||
byte STACK = 2;
|
||||
byte TEXT_BLOCK = 3;
|
||||
byte INGREDIENTS = 4;
|
||||
byte STRUCTURE = 5;
|
||||
|
||||
Codec<ChapterPageElement> CODEC = Codecs.JSON_ELEMENT.xmap(json -> {
|
||||
if (!json.isJsonPrimitive()) {
|
||||
JsonObject el = JsonHelper.asObject(json, "element");
|
||||
if (el.has("texture")) return new Image(el);
|
||||
if (el.has("recipe")) return new Recipe(el);
|
||||
if (el.has("item")) return new Stack(el);
|
||||
if (el.has("ingredients")) return new Ingredients(el);
|
||||
if (el.has("structure")) return new Structure(el);
|
||||
}
|
||||
return new TextBlock(json);
|
||||
}, page -> {
|
||||
throw new RuntimeException();
|
||||
});
|
||||
|
||||
static void write(PacketByteBuf buffer, ChapterPageElement element) {
|
||||
element.toBuffer((RegistryByteBuf)buffer);
|
||||
}
|
||||
|
||||
private static Bounds boundsFromJson(JsonObject el) {
|
||||
return new Bounds(
|
||||
JsonHelper.getInt(el, "y", 0),
|
||||
JsonHelper.getInt(el, "x", 0),
|
||||
JsonHelper.getInt(el, "width", 0),
|
||||
JsonHelper.getInt(el, "height", 0)
|
||||
);
|
||||
}
|
||||
|
||||
private static void boundsToBuffer(Bounds bounds, PacketByteBuf buffer) {
|
||||
buffer.writeInt(bounds.top);
|
||||
buffer.writeInt(bounds.left);
|
||||
buffer.writeInt(bounds.width);
|
||||
buffer.writeInt(bounds.height);
|
||||
}
|
||||
|
||||
void toBuffer(RegistryByteBuf buffer);
|
||||
|
||||
record Image (Identifier texture, Bounds bounds, Flow flow) implements ChapterPageElement {
|
||||
public Image(JsonObject json) {
|
||||
this(
|
||||
Identifier.of(JsonHelper.getString(json, "texture")),
|
||||
boundsFromJson(json),
|
||||
Flow.valueOf(JsonHelper.getString(json, "flow", "RIGHT"))
|
||||
);
|
||||
}
|
||||
@Override
|
||||
public void toBuffer(RegistryByteBuf buffer) {
|
||||
buffer.writeByte(IMAGE);
|
||||
buffer.writeIdentifier(texture);
|
||||
boundsToBuffer(bounds, buffer);
|
||||
buffer.writeEnumConstant(flow);
|
||||
}
|
||||
}
|
||||
|
||||
record Recipe(Identifier value) implements ChapterPageElement {
|
||||
public Recipe(JsonObject json) {
|
||||
this(Identifier.of(JsonHelper.getString(json, "recipe")));
|
||||
}
|
||||
@Override
|
||||
public void toBuffer(RegistryByteBuf buffer) {
|
||||
buffer.writeByte(RECIPE);
|
||||
buffer.writeIdentifier(value);
|
||||
}
|
||||
}
|
||||
|
||||
record Stack (IngredientWithSpell ingredient, Bounds bounds) implements ChapterPageElement {
|
||||
public Stack(JsonObject json) {
|
||||
this(IngredientWithSpell.CODEC.decode(JsonOps.INSTANCE, json.get("item")).result().get().getFirst(), boundsFromJson(json));
|
||||
}
|
||||
@Override
|
||||
public void toBuffer(RegistryByteBuf buffer) {
|
||||
buffer.writeByte(STACK);
|
||||
IngredientWithSpell.PACKET_CODEC.encode(buffer, ingredient);
|
||||
boundsToBuffer(bounds, buffer);
|
||||
}
|
||||
}
|
||||
|
||||
record TextBlock (Text text) implements ChapterPageElement {
|
||||
public TextBlock(JsonElement json) {
|
||||
this(json.isJsonPrimitive() ? Text.translatable(json.getAsString()) : Text.Serialization.fromJsonTree(json, DynamicRegistryManager.EMPTY));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void toBuffer(RegistryByteBuf buffer) {
|
||||
buffer.writeByte(TEXT_BLOCK);
|
||||
TextCodecs.PACKET_CODEC.encode(buffer, text);
|
||||
}
|
||||
}
|
||||
|
||||
record Ingredients(List<ChapterPageElement> entries) implements ChapterPageElement {
|
||||
public Ingredients(JsonObject json) {
|
||||
this(JsonHelper.getArray(json, "ingredients").asList().stream()
|
||||
.map(JsonElement::getAsJsonObject)
|
||||
.map(Ingredients::loadIngredient)
|
||||
.toList());
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
static ChapterPageElement loadIngredient(JsonObject json) {
|
||||
int count = JsonHelper.getInt(json, "count", 1);
|
||||
if (json.has("item")) return new Multi(count, new Id((byte)1, Identifier.tryParse(json.get("item").getAsString())));
|
||||
if (json.has("trait")) return new Multi(count, new Id((byte)2, Trait.fromId(json.get("trait").getAsString()).orElseThrow().getId()));
|
||||
if (json.has("spell")) return new Multi(count, new Id((byte)4, Identifier.tryParse(json.get("spell").getAsString())));
|
||||
return new Multi(count, new TextBlock(json.get("text")));
|
||||
}
|
||||
|
||||
record Id(byte id, Identifier value) implements ChapterPageElement {
|
||||
@Override
|
||||
public void toBuffer(RegistryByteBuf buffer) {
|
||||
buffer.writeByte(id);
|
||||
buffer.writeIdentifier(value);
|
||||
}
|
||||
}
|
||||
|
||||
record Multi(int count, ChapterPageElement element) implements ChapterPageElement {
|
||||
@Override
|
||||
public void toBuffer(RegistryByteBuf buffer) {
|
||||
buffer.writeVarInt(count);
|
||||
element.toBuffer(buffer);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void toBuffer(RegistryByteBuf buffer) {
|
||||
buffer.writeByte(INGREDIENTS);
|
||||
buffer.writeCollection(entries, (b, c) -> c.toBuffer(buffer));
|
||||
}
|
||||
}
|
||||
|
||||
record Structure(List<ChapterPageElement> commands) implements ChapterPageElement {
|
||||
public Structure(JsonObject json) {
|
||||
this(JsonHelper.getArray(json, "structure").asList().stream()
|
||||
.map(JsonElement::getAsJsonObject)
|
||||
.map(Structure::loadCommand)
|
||||
.toList());
|
||||
}
|
||||
|
||||
static ChapterPageElement loadCommand(JsonObject json) {
|
||||
if (json.has("pos")) {
|
||||
var pos = JsonHelper.getArray(json, "pos");
|
||||
return new Set(
|
||||
pos.get(0).getAsInt(), pos.get(1).getAsInt(), pos.get(2).getAsInt(),
|
||||
StateUtil.stateFromString(json.get("state").getAsString())
|
||||
);
|
||||
}
|
||||
|
||||
var min = JsonHelper.getArray(json, "min");
|
||||
var max = JsonHelper.getArray(json, "max");
|
||||
return new Fill(
|
||||
min.get(0).getAsInt(), min.get(1).getAsInt(), min.get(2).getAsInt(),
|
||||
max.get(0).getAsInt(), max.get(1).getAsInt(), max.get(2).getAsInt(),
|
||||
StateUtil.stateFromString(json.get("state").getAsString())
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void toBuffer(RegistryByteBuf buffer) {
|
||||
buffer.writeByte(STRUCTURE);
|
||||
buffer.writeCollection(commands, (b, c) -> c.toBuffer(buffer));
|
||||
}
|
||||
|
||||
record Set(int x, int y, int z, BlockState state) implements ChapterPageElement {
|
||||
@Override
|
||||
public void toBuffer(RegistryByteBuf buffer) {
|
||||
buffer.writeByte(1);
|
||||
buffer.writeInt(x);
|
||||
buffer.writeInt(y);
|
||||
buffer.writeInt(z);
|
||||
buffer.writeInt(Block.getRawIdFromState(state));
|
||||
}
|
||||
|
||||
}
|
||||
record Fill(int x1, int y1, int z1, int x2, int y2, int z2, BlockState state) implements ChapterPageElement {
|
||||
@Override
|
||||
public void toBuffer(RegistryByteBuf buffer) {
|
||||
buffer.writeByte(2);
|
||||
buffer.writeInt(x1);
|
||||
buffer.writeInt(y1);
|
||||
buffer.writeInt(z1);
|
||||
buffer.writeInt(x2);
|
||||
buffer.writeInt(y2);
|
||||
buffer.writeInt(z2);
|
||||
buffer.writeInt(Block.getRawIdFromState(state));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
package com.minelittlepony.unicopia.container.spellbook;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
import com.minelittlepony.unicopia.util.serialization.PacketCodecUtils;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import net.minecraft.network.codec.PacketCodec;
|
||||
import net.minecraft.util.StringIdentifiable;
|
||||
|
||||
public enum Flow implements StringIdentifiable {
|
||||
NONE, LEFT, RIGHT;
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
public static final EnumCodec<Flow> CODEC = StringIdentifiable.createCodec(Flow::values);
|
||||
public static final PacketCodec<ByteBuf, Flow> PACKET_CODEC = PacketCodecUtils.ofEnum(Flow.class);
|
||||
|
||||
private final String name = name().toLowerCase(Locale.ROOT);
|
||||
|
||||
@Override
|
||||
public String asString() {
|
||||
return name;
|
||||
}
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package com.minelittlepony.unicopia.container;
|
||||
package com.minelittlepony.unicopia.container.spellbook;
|
||||
|
||||
import com.minelittlepony.unicopia.InteractionManager;
|
||||
|
||||
|
@ -7,7 +7,7 @@ import net.minecraft.network.codec.PacketCodec;
|
|||
|
||||
public interface SpellbookChapter {
|
||||
PacketCodec<RegistryByteBuf, SpellbookChapter> PACKET_CODEC = PacketCodec.ofStatic(
|
||||
(buffer, chapter) -> ((SpellbookChapterLoader.Chapter)chapter).write(buffer),
|
||||
(buffer, chapter) -> ((SpellbookChapterLoader.IdentifiableChapter)chapter).write(buffer),
|
||||
buffer -> InteractionManager.getInstance().readChapter(buffer)
|
||||
);
|
||||
}
|
|
@ -0,0 +1,90 @@
|
|||
package com.minelittlepony.unicopia.container.spellbook;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.concurrent.*;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
|
||||
import com.google.gson.*;
|
||||
import com.minelittlepony.unicopia.Debug;
|
||||
import com.minelittlepony.unicopia.Unicopia;
|
||||
import com.minelittlepony.unicopia.network.Channel;
|
||||
import com.minelittlepony.unicopia.network.MsgServerResources;
|
||||
import com.minelittlepony.unicopia.util.Resources;
|
||||
import com.mojang.datafixers.util.Pair;
|
||||
import com.mojang.logging.LogUtils;
|
||||
import com.mojang.serialization.JsonOps;
|
||||
|
||||
import net.fabricmc.fabric.api.resource.IdentifiableResourceReloadListener;
|
||||
import net.minecraft.network.RegistryByteBuf;
|
||||
import net.minecraft.resource.JsonDataLoader;
|
||||
import net.minecraft.resource.ResourceManager;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.Util;
|
||||
import net.minecraft.util.profiler.Profiler;
|
||||
|
||||
public class SpellbookChapterLoader extends JsonDataLoader implements IdentifiableResourceReloadListener {
|
||||
private static final Logger LOGGER = LogUtils.getLogger();
|
||||
private static final Identifier ID = Unicopia.id("spellbook/chapters");
|
||||
private static final Executor EXECUTOR = CompletableFuture.delayedExecutor(5, TimeUnit.SECONDS);
|
||||
|
||||
public static final SpellbookChapterLoader INSTANCE = new SpellbookChapterLoader();
|
||||
|
||||
private boolean dirty;
|
||||
private Map<Identifier, SpellbookChapter> chapters = new HashMap<>();
|
||||
|
||||
public SpellbookChapterLoader() {
|
||||
super(Resources.GSON, ID.getPath());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Identifier getFabricId() {
|
||||
return ID;
|
||||
}
|
||||
|
||||
public Map<Identifier, SpellbookChapter> getChapters() {
|
||||
return chapters;
|
||||
}
|
||||
|
||||
public void sendUpdate(MinecraftServer server) {
|
||||
if (dirty) {
|
||||
dirty = false;
|
||||
Channel.SERVER_RESOURCES.sendToAllPlayers(new MsgServerResources(), server);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void apply(Map<Identifier, JsonElement> data, ResourceManager manager, Profiler profiler) {
|
||||
try {
|
||||
chapters = data.entrySet().stream().map(entry -> {
|
||||
return Chapter.CODEC.decode(JsonOps.INSTANCE, entry.getValue())
|
||||
.result()
|
||||
.map(Pair::getFirst)
|
||||
.map(chapter -> new IdentifiableChapter(entry.getKey(), chapter))
|
||||
.orElse(null);
|
||||
}).filter(Objects::nonNull).collect(Collectors.toMap(IdentifiableChapter::id, Function.identity()));
|
||||
} catch (IllegalStateException | JsonParseException e) {
|
||||
LOGGER.error("Could not load spellbook chapters due to exception", e);
|
||||
}
|
||||
|
||||
if (Debug.SPELLBOOK_CHAPTERS) {
|
||||
CompletableFuture.runAsync(() -> {
|
||||
try {
|
||||
Util.waitAndApply(executor -> reload(CompletableFuture::completedFuture, manager, profiler, profiler, Util.getMainWorkerExecutor(), executor)).get();
|
||||
} catch (InterruptedException | ExecutionException e) {
|
||||
}
|
||||
dirty = true;
|
||||
}, EXECUTOR);
|
||||
}
|
||||
}
|
||||
|
||||
record IdentifiableChapter(Identifier id, Chapter chapter) implements SpellbookChapter {
|
||||
public void write(RegistryByteBuf buffer) {
|
||||
buffer.writeIdentifier(id);
|
||||
chapter.write(buffer);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
package com.minelittlepony.unicopia.container.spellbook;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
import com.minelittlepony.unicopia.util.serialization.PacketCodecUtils;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import net.minecraft.network.codec.PacketCodec;
|
||||
import net.minecraft.util.StringIdentifiable;
|
||||
|
||||
public enum TabSide implements StringIdentifiable {
|
||||
LEFT,
|
||||
RIGHT;
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
public static final EnumCodec<TabSide> CODEC = StringIdentifiable.createCodec(TabSide::values);
|
||||
public static final PacketCodec<ByteBuf, TabSide> PACKET_CODEC = PacketCodecUtils.ofEnum(TabSide.class);
|
||||
|
||||
private final String name = name().toLowerCase(Locale.ROOT);
|
||||
|
||||
@Override
|
||||
public String asString() {
|
||||
return name;
|
||||
}
|
||||
}
|
|
@ -4,8 +4,8 @@ import java.util.*;
|
|||
|
||||
import com.minelittlepony.unicopia.ability.data.tree.TreeTypeLoader;
|
||||
import com.minelittlepony.unicopia.ability.magic.spell.trait.SpellTraits;
|
||||
import com.minelittlepony.unicopia.container.SpellbookChapter;
|
||||
import com.minelittlepony.unicopia.container.SpellbookChapterLoader;
|
||||
import com.minelittlepony.unicopia.container.spellbook.SpellbookChapter;
|
||||
import com.minelittlepony.unicopia.container.spellbook.SpellbookChapterLoader;
|
||||
import com.minelittlepony.unicopia.diet.PonyDiets;
|
||||
import net.minecraft.network.RegistryByteBuf;
|
||||
import net.minecraft.network.codec.PacketCodec;
|
||||
|
|
Loading…
Reference in a new issue