mirror of
https://github.com/Sollace/Unicopia.git
synced 2024-11-27 15:17:59 +01:00
Spellbook chapters are now server-controlled
This commit is contained in:
parent
e721568312
commit
17d3d92416
18 changed files with 308 additions and 143 deletions
|
@ -19,6 +19,7 @@ import com.minelittlepony.unicopia.advancement.UCriteria;
|
||||||
import com.minelittlepony.unicopia.block.UBlocks;
|
import com.minelittlepony.unicopia.block.UBlocks;
|
||||||
import com.minelittlepony.unicopia.block.state.StateMapLoader;
|
import com.minelittlepony.unicopia.block.state.StateMapLoader;
|
||||||
import com.minelittlepony.unicopia.command.Commands;
|
import com.minelittlepony.unicopia.command.Commands;
|
||||||
|
import com.minelittlepony.unicopia.container.SpellbookChapterLoader;
|
||||||
import com.minelittlepony.unicopia.container.UScreenHandlers;
|
import com.minelittlepony.unicopia.container.UScreenHandlers;
|
||||||
import com.minelittlepony.unicopia.entity.UEntities;
|
import com.minelittlepony.unicopia.entity.UEntities;
|
||||||
import com.minelittlepony.unicopia.entity.effect.UPotions;
|
import com.minelittlepony.unicopia.entity.effect.UPotions;
|
||||||
|
@ -62,6 +63,7 @@ public class Unicopia implements ModInitializer {
|
||||||
ResourceManagerHelper.get(ResourceType.SERVER_DATA).registerReloadListener(UEnchantments.POISONED_JOKE);
|
ResourceManagerHelper.get(ResourceType.SERVER_DATA).registerReloadListener(UEnchantments.POISONED_JOKE);
|
||||||
ResourceManagerHelper.get(ResourceType.SERVER_DATA).registerReloadListener(new TraitLoader());
|
ResourceManagerHelper.get(ResourceType.SERVER_DATA).registerReloadListener(new TraitLoader());
|
||||||
ResourceManagerHelper.get(ResourceType.SERVER_DATA).registerReloadListener(StateMapLoader.INSTANCE);
|
ResourceManagerHelper.get(ResourceType.SERVER_DATA).registerReloadListener(StateMapLoader.INSTANCE);
|
||||||
|
ResourceManagerHelper.get(ResourceType.SERVER_DATA).registerReloadListener(SpellbookChapterLoader.INSTANCE);
|
||||||
|
|
||||||
UBlocks.bootstrap();
|
UBlocks.bootstrap();
|
||||||
UItems.bootstrap();
|
UItems.bootstrap();
|
||||||
|
|
|
@ -10,7 +10,6 @@ import com.minelittlepony.unicopia.Race;
|
||||||
import com.minelittlepony.unicopia.Unicopia;
|
import com.minelittlepony.unicopia.Unicopia;
|
||||||
import com.minelittlepony.unicopia.client.gui.LanSettingsScreen;
|
import com.minelittlepony.unicopia.client.gui.LanSettingsScreen;
|
||||||
import com.minelittlepony.unicopia.client.gui.UHud;
|
import com.minelittlepony.unicopia.client.gui.UHud;
|
||||||
import com.minelittlepony.unicopia.client.gui.spellbook.SpellbookChapterLoader;
|
|
||||||
import com.minelittlepony.unicopia.client.gui.spellbook.SpellbookScreen;
|
import com.minelittlepony.unicopia.client.gui.spellbook.SpellbookScreen;
|
||||||
import com.minelittlepony.unicopia.client.minelittlepony.MineLPConnector;
|
import com.minelittlepony.unicopia.client.minelittlepony.MineLPConnector;
|
||||||
import com.minelittlepony.unicopia.container.*;
|
import com.minelittlepony.unicopia.container.*;
|
||||||
|
@ -19,14 +18,12 @@ import com.minelittlepony.unicopia.entity.player.Pony;
|
||||||
import net.fabricmc.api.ClientModInitializer;
|
import net.fabricmc.api.ClientModInitializer;
|
||||||
import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents;
|
import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents;
|
||||||
import net.fabricmc.fabric.api.client.item.v1.ItemTooltipCallback;
|
import net.fabricmc.fabric.api.client.item.v1.ItemTooltipCallback;
|
||||||
import net.fabricmc.fabric.api.resource.ResourceManagerHelper;
|
|
||||||
import net.minecraft.client.MinecraftClient;
|
import net.minecraft.client.MinecraftClient;
|
||||||
import net.minecraft.client.gui.screen.OpenToLanScreen;
|
import net.minecraft.client.gui.screen.OpenToLanScreen;
|
||||||
import net.minecraft.client.gui.screen.Screen;
|
import net.minecraft.client.gui.screen.Screen;
|
||||||
import net.minecraft.client.gui.screen.ingame.HandledScreens;
|
import net.minecraft.client.gui.screen.ingame.HandledScreens;
|
||||||
import net.minecraft.client.gui.screen.world.CreateWorldScreen;
|
import net.minecraft.client.gui.screen.world.CreateWorldScreen;
|
||||||
import net.minecraft.entity.player.PlayerEntity;
|
import net.minecraft.entity.player.PlayerEntity;
|
||||||
import net.minecraft.resource.ResourceType;
|
|
||||||
import net.minecraft.text.Text;
|
import net.minecraft.text.Text;
|
||||||
|
|
||||||
public class UnicopiaClient implements ClientModInitializer {
|
public class UnicopiaClient implements ClientModInitializer {
|
||||||
|
@ -66,7 +63,6 @@ public class UnicopiaClient implements ClientModInitializer {
|
||||||
URenderers.bootstrap();
|
URenderers.bootstrap();
|
||||||
|
|
||||||
HandledScreens.register(UScreenHandlers.SPELL_BOOK, SpellbookScreen::new);
|
HandledScreens.register(UScreenHandlers.SPELL_BOOK, SpellbookScreen::new);
|
||||||
ResourceManagerHelper.get(ResourceType.CLIENT_RESOURCES).registerReloadListener(SpellbookChapterLoader.INSTANCE);
|
|
||||||
|
|
||||||
ClientTickEvents.END_CLIENT_TICK.register(this::onTick);
|
ClientTickEvents.END_CLIENT_TICK.register(this::onTick);
|
||||||
ScreenInitCallback.EVENT.register(this::onScreenInit);
|
ScreenInitCallback.EVENT.register(this::onScreenInit);
|
||||||
|
|
|
@ -0,0 +1,28 @@
|
||||||
|
package com.minelittlepony.unicopia.client.gui.spellbook;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
import com.minelittlepony.unicopia.client.gui.spellbook.SpellbookChapterList.*;
|
||||||
|
import net.minecraft.network.PacketByteBuf;
|
||||||
|
import net.minecraft.util.*;
|
||||||
|
|
||||||
|
public class ClientChapters {
|
||||||
|
private static Map<Identifier, Chapter> CHAPTERS = new HashMap<>();
|
||||||
|
|
||||||
|
public static Set<SpellbookChapterList.Chapter> getChapters() {
|
||||||
|
return new HashSet<>(CHAPTERS.values());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void load(Map<Identifier, Chapter> chapters) {
|
||||||
|
CHAPTERS = chapters;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Chapter loadChapter(PacketByteBuf buffer) {
|
||||||
|
return new Chapter(
|
||||||
|
buffer.readIdentifier(),
|
||||||
|
buffer.readEnumConstant(TabSide.class),
|
||||||
|
buffer.readInt(),
|
||||||
|
buffer.readInt(),
|
||||||
|
buffer.readOptional(DynamicContent::new)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,16 +2,17 @@ package com.minelittlepony.unicopia.client.gui.spellbook;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
import com.google.gson.*;
|
|
||||||
import com.minelittlepony.common.client.gui.IViewRoot;
|
import com.minelittlepony.common.client.gui.IViewRoot;
|
||||||
import com.minelittlepony.common.client.gui.dimension.Bounds;
|
import com.minelittlepony.common.client.gui.dimension.Bounds;
|
||||||
import com.minelittlepony.unicopia.client.gui.DrawableUtil;
|
import com.minelittlepony.unicopia.client.gui.DrawableUtil;
|
||||||
import com.minelittlepony.unicopia.client.gui.spellbook.SpellbookChapterList.Content;
|
import com.minelittlepony.unicopia.client.gui.spellbook.SpellbookChapterList.Content;
|
||||||
import com.minelittlepony.unicopia.client.gui.spellbook.SpellbookChapterList.Drawable;
|
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.SpellbookState;
|
||||||
import com.minelittlepony.unicopia.entity.player.Pony;
|
import com.minelittlepony.unicopia.entity.player.Pony;
|
||||||
import net.minecraft.client.MinecraftClient;
|
import net.minecraft.client.MinecraftClient;
|
||||||
import net.minecraft.client.util.math.MatrixStack;
|
import net.minecraft.client.util.math.MatrixStack;
|
||||||
|
import net.minecraft.network.PacketByteBuf;
|
||||||
import net.minecraft.text.Text;
|
import net.minecraft.text.Text;
|
||||||
import net.minecraft.util.*;
|
import net.minecraft.util.*;
|
||||||
|
|
||||||
|
@ -20,12 +21,12 @@ public class DynamicContent implements Content {
|
||||||
private static final Text UNKNOWN_LEVEL = Text.literal("Level: ???").formatted(Formatting.DARK_GREEN);
|
private static final Text UNKNOWN_LEVEL = Text.literal("Level: ???").formatted(Formatting.DARK_GREEN);
|
||||||
|
|
||||||
private SpellbookState.PageState state = new SpellbookState.PageState();
|
private SpellbookState.PageState state = new SpellbookState.PageState();
|
||||||
private final List<Page> pages = new ArrayList<>();
|
private final List<Page> pages;
|
||||||
|
|
||||||
private Bounds bounds = Bounds.empty();
|
private Bounds bounds = Bounds.empty();
|
||||||
|
|
||||||
public DynamicContent(JsonArray json) {
|
public DynamicContent(PacketByteBuf buffer) {
|
||||||
json.forEach(element -> pages.add(new Page(element.getAsJsonObject())));
|
pages = buffer.readList(Page::new);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -76,21 +77,19 @@ public class DynamicContent implements Content {
|
||||||
}
|
}
|
||||||
|
|
||||||
class Page implements Drawable {
|
class Page implements Drawable {
|
||||||
private final List<PageElement> elements = new ArrayList<>();
|
|
||||||
|
|
||||||
private final Text title;
|
private final Text title;
|
||||||
private final int level;
|
private final int level;
|
||||||
|
|
||||||
|
private final List<PageElement> elements;
|
||||||
|
|
||||||
private boolean compiled;
|
private boolean compiled;
|
||||||
|
|
||||||
private Bounds bounds = Bounds.empty();
|
private Bounds bounds = Bounds.empty();
|
||||||
|
|
||||||
public Page(JsonObject json) {
|
public Page(PacketByteBuf buffer) {
|
||||||
title = Text.Serializer.fromJson(json.get("title"));
|
title = buffer.readText();
|
||||||
level = JsonHelper.getInt(json, "level", 0);
|
level = buffer.readInt();
|
||||||
JsonHelper.getArray(json, "elements", new JsonArray()).forEach(element -> {
|
elements = buffer.readList(r -> PageElement.read(this, r));
|
||||||
elements.add(PageElement.fromJson(this, element));
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected int getLineLimitAt(int yPosition) {
|
protected int getLineLimitAt(int yPosition) {
|
||||||
|
@ -104,7 +103,7 @@ public class DynamicContent implements Content {
|
||||||
|
|
||||||
protected int getLeftMarginAt(int yPosition) {
|
protected int getLeftMarginAt(int yPosition) {
|
||||||
return elements.stream()
|
return elements.stream()
|
||||||
.filter(p -> p.flow() == PageElement.Flow.LEFT)
|
.filter(p -> p.flow() == Flow.LEFT)
|
||||||
.map(PageElement::bounds)
|
.map(PageElement::bounds)
|
||||||
.filter(b -> b.containsY(yPosition))
|
.filter(b -> b.containsY(yPosition))
|
||||||
.mapToInt(b -> b.width)
|
.mapToInt(b -> b.width)
|
||||||
|
|
|
@ -3,14 +3,13 @@ package com.minelittlepony.unicopia.client.gui.spellbook;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import com.google.gson.JsonElement;
|
|
||||||
import com.google.gson.JsonObject;
|
|
||||||
import com.minelittlepony.common.client.gui.IViewRoot;
|
import com.minelittlepony.common.client.gui.IViewRoot;
|
||||||
import com.minelittlepony.common.client.gui.dimension.Bounds;
|
import com.minelittlepony.common.client.gui.dimension.Bounds;
|
||||||
import com.minelittlepony.unicopia.ability.magic.spell.crafting.IngredientWithSpell;
|
import com.minelittlepony.unicopia.ability.magic.spell.crafting.IngredientWithSpell;
|
||||||
import com.minelittlepony.unicopia.ability.magic.spell.crafting.SpellbookRecipe;
|
import com.minelittlepony.unicopia.ability.magic.spell.crafting.SpellbookRecipe;
|
||||||
import com.minelittlepony.unicopia.client.gui.ParagraphWrappingVisitor;
|
import com.minelittlepony.unicopia.client.gui.ParagraphWrappingVisitor;
|
||||||
import com.minelittlepony.unicopia.client.gui.spellbook.SpellbookChapterList.Drawable;
|
import com.minelittlepony.unicopia.client.gui.spellbook.SpellbookChapterList.Drawable;
|
||||||
|
import com.minelittlepony.unicopia.container.SpellbookChapterLoader.Flow;
|
||||||
import com.minelittlepony.unicopia.entity.player.Pony;
|
import com.minelittlepony.unicopia.entity.player.Pony;
|
||||||
import com.mojang.blaze3d.systems.RenderSystem;
|
import com.mojang.blaze3d.systems.RenderSystem;
|
||||||
|
|
||||||
|
@ -18,6 +17,7 @@ import net.minecraft.client.MinecraftClient;
|
||||||
import net.minecraft.client.font.TextRenderer;
|
import net.minecraft.client.font.TextRenderer;
|
||||||
import net.minecraft.client.gui.DrawableHelper;
|
import net.minecraft.client.gui.DrawableHelper;
|
||||||
import net.minecraft.client.util.math.MatrixStack;
|
import net.minecraft.client.util.math.MatrixStack;
|
||||||
|
import net.minecraft.network.PacketByteBuf;
|
||||||
import net.minecraft.text.Style;
|
import net.minecraft.text.Style;
|
||||||
import net.minecraft.text.Text;
|
import net.minecraft.text.Text;
|
||||||
import net.minecraft.util.*;
|
import net.minecraft.util.*;
|
||||||
|
@ -44,37 +44,19 @@ interface PageElement extends Drawable {
|
||||||
|
|
||||||
default void compile(int y, IViewRoot Container) {}
|
default void compile(int y, IViewRoot Container) {}
|
||||||
|
|
||||||
static PageElement fromJson(DynamicContent.Page page, JsonElement element) {
|
static PageElement read(DynamicContent.Page page, PacketByteBuf buffer) {
|
||||||
if (element.isJsonPrimitive()) {
|
byte type = buffer.readByte();
|
||||||
return new TextBlock(page, Text.Serializer.fromJson(element));
|
return (switch (type) {
|
||||||
}
|
case 0 -> new Image(buffer.readIdentifier(), boundsFromBuffer(buffer), buffer.readEnumConstant(Flow.class));
|
||||||
|
case 1 -> new Recipe(page, buffer.readIdentifier(), Bounds.empty());
|
||||||
JsonObject el = JsonHelper.asObject(element, "element");
|
case 2 -> new Stack(page, IngredientWithSpell.fromPacket(buffer), boundsFromBuffer(buffer));
|
||||||
if (el.has("texture")) {
|
case 3 -> new TextBlock(page, buffer.readText());
|
||||||
return new Image(
|
default -> throw new IllegalArgumentException("Unexpected value: " + type);
|
||||||
new Identifier(JsonHelper.getString(el, "texture")),
|
});
|
||||||
boundsFromJson(el),
|
|
||||||
Flow.valueOf(JsonHelper.getString(el, "flow", "RIGHT"))
|
|
||||||
);
|
|
||||||
}
|
|
||||||
if (el.has("recipe")) {
|
|
||||||
return new Recipe(page, new Identifier(JsonHelper.getString(el, "recipe")), new Bounds(0, 0, 0, 0));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (el.has("item")) {
|
|
||||||
return new Stack(page, IngredientWithSpell.fromJson(el.get("item")), boundsFromJson(el));
|
|
||||||
}
|
|
||||||
|
|
||||||
return new TextBlock(page, Text.Serializer.fromJson(element));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Bounds boundsFromJson(JsonObject el) {
|
private static Bounds boundsFromBuffer(PacketByteBuf buffer) {
|
||||||
return new Bounds(
|
return new Bounds(buffer.readInt(), buffer.readInt(), buffer.readInt(), buffer.readInt());
|
||||||
JsonHelper.getInt(el, "y", 0),
|
|
||||||
JsonHelper.getInt(el, "x", 0),
|
|
||||||
JsonHelper.getInt(el, "width", 0),
|
|
||||||
JsonHelper.getInt(el, "height", 0)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
record Image(
|
record Image(
|
||||||
|
@ -171,8 +153,4 @@ interface PageElement extends Drawable {
|
||||||
bounds.height = tree.build(container) - 10;
|
bounds.height = tree.build(container) - 10;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
enum Flow {
|
|
||||||
NONE, LEFT, RIGHT
|
|
||||||
}
|
|
||||||
}
|
}
|
|
@ -6,6 +6,7 @@ import java.util.stream.Stream;
|
||||||
|
|
||||||
import com.minelittlepony.common.client.gui.IViewRoot;
|
import com.minelittlepony.common.client.gui.IViewRoot;
|
||||||
import com.minelittlepony.unicopia.Unicopia;
|
import com.minelittlepony.unicopia.Unicopia;
|
||||||
|
import com.minelittlepony.unicopia.container.SpellbookChapterLoader;
|
||||||
|
|
||||||
import net.minecraft.client.util.math.MatrixStack;
|
import net.minecraft.client.util.math.MatrixStack;
|
||||||
import net.minecraft.util.Identifier;
|
import net.minecraft.util.Identifier;
|
||||||
|
@ -24,7 +25,7 @@ public class SpellbookChapterList {
|
||||||
public SpellbookChapterList(SpellbookScreen screen, Chapter craftingChapter, Chapter... builtIn) {
|
public SpellbookChapterList(SpellbookScreen screen, Chapter craftingChapter, Chapter... builtIn) {
|
||||||
this.screen = screen;
|
this.screen = screen;
|
||||||
this.craftingChapter = craftingChapter;
|
this.craftingChapter = craftingChapter;
|
||||||
SpellbookChapterLoader.INSTANCE.getChapters().forEach(chapter -> {
|
ClientChapters.getChapters().forEach(chapter -> {
|
||||||
chapters.put(chapter.id(), chapter);
|
chapters.put(chapter.id(), chapter);
|
||||||
});
|
});
|
||||||
chapters.put(craftingChapter.id(), craftingChapter);
|
chapters.put(craftingChapter.id(), craftingChapter);
|
||||||
|
@ -39,7 +40,7 @@ public class SpellbookChapterList {
|
||||||
|
|
||||||
public Chapter getCurrentChapter() {
|
public Chapter getCurrentChapter() {
|
||||||
if (SpellbookChapterLoader.DEBUG) {
|
if (SpellbookChapterLoader.DEBUG) {
|
||||||
SpellbookChapterLoader.INSTANCE.getChapters().forEach(chapter -> {
|
ClientChapters.getChapters().forEach(chapter -> {
|
||||||
Optional.ofNullable(chapters.get(chapter.id())).flatMap(Chapter::content).ifPresent(old -> {
|
Optional.ofNullable(chapters.get(chapter.id())).flatMap(Chapter::content).ifPresent(old -> {
|
||||||
chapter.content().ifPresent(neu -> neu.copyStateFrom(old));
|
chapter.content().ifPresent(neu -> neu.copyStateFrom(old));
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,74 +0,0 @@
|
||||||
package com.minelittlepony.unicopia.client.gui.spellbook;
|
|
||||||
|
|
||||||
import java.util.*;
|
|
||||||
import java.util.concurrent.*;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
|
|
||||||
import com.google.gson.*;
|
|
||||||
import com.minelittlepony.unicopia.Unicopia;
|
|
||||||
import com.minelittlepony.unicopia.client.gui.spellbook.SpellbookChapterList.*;
|
|
||||||
import com.minelittlepony.unicopia.util.Resources;
|
|
||||||
import com.mojang.logging.LogUtils;
|
|
||||||
|
|
||||||
import net.fabricmc.fabric.api.resource.IdentifiableResourceReloadListener;
|
|
||||||
import net.minecraft.client.MinecraftClient;
|
|
||||||
import net.minecraft.resource.JsonDataLoader;
|
|
||||||
import net.minecraft.resource.ResourceManager;
|
|
||||||
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 boolean DEBUG = false;
|
|
||||||
|
|
||||||
public static final SpellbookChapterLoader INSTANCE = new SpellbookChapterLoader();
|
|
||||||
|
|
||||||
private Map<Identifier, Chapter> chapters = new HashMap<>();
|
|
||||||
|
|
||||||
public SpellbookChapterLoader() {
|
|
||||||
super(Resources.GSON, ID.getPath());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Identifier getFabricId() {
|
|
||||||
return ID;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Set<SpellbookChapterList.Chapter> getChapters() {
|
|
||||||
return new HashSet<>(chapters.values());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void apply(Map<Identifier, JsonElement> data, ResourceManager manager, Profiler profiler) {
|
|
||||||
try {
|
|
||||||
chapters = data.entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey, entry -> {
|
|
||||||
JsonObject json = JsonHelper.asObject(entry.getValue(), "root");
|
|
||||||
|
|
||||||
return new Chapter(entry.getKey(),
|
|
||||||
TabSide.valueOf(JsonHelper.getString(json, "side")),
|
|
||||||
JsonHelper.getInt(json, "y_position"),
|
|
||||||
JsonHelper.getInt(json, "color", 0),
|
|
||||||
loadContent(JsonHelper.getObject(json, "content", new JsonObject()))
|
|
||||||
);
|
|
||||||
}));
|
|
||||||
} catch (IllegalStateException | JsonParseException e) {
|
|
||||||
LOGGER.error("Could not load spellbook chapters due to exception", e);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (DEBUG) {
|
|
||||||
CompletableFuture.runAsync(() -> {
|
|
||||||
reload(CompletableFuture::completedFuture, manager, profiler, profiler, Util.getMainWorkerExecutor(), MinecraftClient.getInstance());
|
|
||||||
}, EXECUTOR);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private Optional<Content> loadContent(JsonObject json) {
|
|
||||||
return Optional.of(JsonHelper.getArray(json, "pages", new JsonArray()))
|
|
||||||
.filter(pages -> pages.size() > 0)
|
|
||||||
.map(DynamicContent::new);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,218 @@
|
||||||
|
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.Unicopia;
|
||||||
|
import com.minelittlepony.unicopia.ability.magic.spell.crafting.IngredientWithSpell;
|
||||||
|
import com.minelittlepony.unicopia.client.gui.spellbook.SpellbookChapterList.*;
|
||||||
|
import com.minelittlepony.unicopia.util.Resources;
|
||||||
|
import com.mojang.logging.LogUtils;
|
||||||
|
|
||||||
|
import net.fabricmc.fabric.api.resource.IdentifiableResourceReloadListener;
|
||||||
|
import net.minecraft.client.MinecraftClient;
|
||||||
|
import net.minecraft.network.PacketByteBuf;
|
||||||
|
import net.minecraft.resource.JsonDataLoader;
|
||||||
|
import net.minecraft.resource.ResourceManager;
|
||||||
|
import net.minecraft.text.Text;
|
||||||
|
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 boolean DEBUG = false;
|
||||||
|
|
||||||
|
public static final SpellbookChapterLoader INSTANCE = new SpellbookChapterLoader();
|
||||||
|
|
||||||
|
private Map<Identifier, Chapter> chapters = new HashMap<>();
|
||||||
|
|
||||||
|
public SpellbookChapterLoader() {
|
||||||
|
super(Resources.GSON, ID.getPath());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Identifier getFabricId() {
|
||||||
|
return ID;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<Identifier, Chapter> getChapters() {
|
||||||
|
return chapters;
|
||||||
|
}
|
||||||
|
|
||||||
|
@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) {
|
||||||
|
CompletableFuture.runAsync(() -> {
|
||||||
|
reload(CompletableFuture::completedFuture, manager, profiler, profiler, Util.getMainWorkerExecutor(), MinecraftClient.getInstance());
|
||||||
|
}, EXECUTOR);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public record Chapter (
|
||||||
|
Identifier id,
|
||||||
|
TabSide side,
|
||||||
|
int tabY,
|
||||||
|
int color,
|
||||||
|
List<Page> pages) {
|
||||||
|
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()))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
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::new)
|
||||||
|
.toList();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void write(PacketByteBuf 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,
|
||||||
|
List<Element> elements
|
||||||
|
) {
|
||||||
|
public Page(JsonElement json) {
|
||||||
|
this(json.getAsJsonObject());
|
||||||
|
}
|
||||||
|
|
||||||
|
public Page(JsonObject json) {
|
||||||
|
this(
|
||||||
|
Text.Serializer.fromJson(json.get("title")),
|
||||||
|
JsonHelper.getInt(json, "level", 0),
|
||||||
|
new ArrayList<Element>()
|
||||||
|
);
|
||||||
|
JsonHelper.getArray(json, "elements", new JsonArray()).forEach(element -> {
|
||||||
|
elements.add(Element.read(element));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public void toBuffer(PacketByteBuf buffer) {
|
||||||
|
buffer.writeText(title);
|
||||||
|
buffer.writeInt(level);
|
||||||
|
buffer.writeCollection(elements, Element::write);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void write(PacketByteBuf buffer, Page page) {
|
||||||
|
page.toBuffer(buffer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum Flow {
|
||||||
|
NONE, LEFT, RIGHT
|
||||||
|
}
|
||||||
|
|
||||||
|
private interface Element {
|
||||||
|
void toBuffer(PacketByteBuf buffer);
|
||||||
|
|
||||||
|
record Image (Identifier texture, Bounds bounds, Flow flow) implements Element {
|
||||||
|
@Override
|
||||||
|
public void toBuffer(PacketByteBuf buffer) {
|
||||||
|
buffer.writeByte(0);
|
||||||
|
buffer.writeIdentifier(texture);
|
||||||
|
boundsToBuffer(bounds, buffer);
|
||||||
|
buffer.writeEnumConstant(flow);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
record Recipe (Identifier id) implements Element {
|
||||||
|
@Override
|
||||||
|
public void toBuffer(PacketByteBuf buffer) {
|
||||||
|
buffer.writeByte(1);
|
||||||
|
buffer.writeIdentifier(id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
record Stack (IngredientWithSpell ingredient, Bounds bounds) implements Element {
|
||||||
|
@Override
|
||||||
|
public void toBuffer(PacketByteBuf buffer) {
|
||||||
|
buffer.writeByte(2);
|
||||||
|
ingredient.write(buffer);
|
||||||
|
boundsToBuffer(bounds, buffer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
record TextBlock (Text text) implements Element {
|
||||||
|
@Override
|
||||||
|
public void toBuffer(PacketByteBuf buffer) {
|
||||||
|
buffer.writeByte(3);
|
||||||
|
buffer.writeText(text);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void write(PacketByteBuf buffer, Element element) {
|
||||||
|
element.toBuffer(buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
static Element read(JsonElement json) {
|
||||||
|
if (!json.isJsonPrimitive()) {
|
||||||
|
|
||||||
|
JsonObject el = JsonHelper.asObject(json, "element");
|
||||||
|
if (el.has("texture")) {
|
||||||
|
return new Image(
|
||||||
|
new Identifier(JsonHelper.getString(el, "texture")),
|
||||||
|
boundsFromJson(el),
|
||||||
|
Flow.valueOf(JsonHelper.getString(el, "flow", "RIGHT"))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (el.has("recipe")) {
|
||||||
|
return new Recipe(new Identifier(JsonHelper.getString(el, "recipe")));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (el.has("item")) {
|
||||||
|
return new Stack(IngredientWithSpell.fromJson(el.get("item")), boundsFromJson(el));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return new TextBlock(Text.Serializer.fromJson(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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,31 +2,41 @@ package com.minelittlepony.unicopia.network;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
|
import com.minelittlepony.unicopia.InteractionManager;
|
||||||
import com.minelittlepony.unicopia.ability.magic.spell.trait.SpellTraits;
|
import com.minelittlepony.unicopia.ability.magic.spell.trait.SpellTraits;
|
||||||
|
import com.minelittlepony.unicopia.client.gui.spellbook.ClientChapters;
|
||||||
|
import com.minelittlepony.unicopia.container.SpellbookChapterLoader;
|
||||||
import com.minelittlepony.unicopia.util.network.Packet;
|
import com.minelittlepony.unicopia.util.network.Packet;
|
||||||
|
|
||||||
|
import net.fabricmc.api.EnvType;
|
||||||
|
import net.fabricmc.api.Environment;
|
||||||
import net.minecraft.entity.player.PlayerEntity;
|
import net.minecraft.entity.player.PlayerEntity;
|
||||||
import net.minecraft.network.PacketByteBuf;
|
import net.minecraft.network.PacketByteBuf;
|
||||||
import net.minecraft.util.Identifier;
|
import net.minecraft.util.Identifier;
|
||||||
|
|
||||||
public class MsgServerResources implements Packet<PlayerEntity> {
|
public class MsgServerResources implements Packet<PlayerEntity> {
|
||||||
private final Map<Identifier, SpellTraits> entries;
|
public final Map<Identifier, SpellTraits> traits;
|
||||||
|
public final Map<Identifier, ?> chapters;
|
||||||
|
|
||||||
public MsgServerResources() {
|
public MsgServerResources() {
|
||||||
entries = SpellTraits.all();
|
traits = SpellTraits.all();
|
||||||
|
chapters = SpellbookChapterLoader.INSTANCE.getChapters();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Environment(EnvType.CLIENT)
|
||||||
public MsgServerResources(PacketByteBuf buffer) {
|
public MsgServerResources(PacketByteBuf buffer) {
|
||||||
entries = buffer.readMap(PacketByteBuf::readIdentifier, SpellTraits::fromPacket);
|
traits = buffer.readMap(PacketByteBuf::readIdentifier, SpellTraits::fromPacket);
|
||||||
|
chapters = buffer.readMap(PacketByteBuf::readIdentifier, ClientChapters::loadChapter);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void toBuffer(PacketByteBuf buffer) {
|
public void toBuffer(PacketByteBuf buffer) {
|
||||||
buffer.writeMap(entries, PacketByteBuf::writeIdentifier, (r, v) -> v.write(r));
|
buffer.writeMap(traits, PacketByteBuf::writeIdentifier, (r, v) -> v.write(r));
|
||||||
|
buffer.writeMap(chapters, PacketByteBuf::writeIdentifier, (r, v) -> ((SpellbookChapterLoader.Chapter)v).write(r));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void handle(PlayerEntity sender) {
|
public void handle(PlayerEntity sender) {
|
||||||
SpellTraits.load(entries);
|
InteractionManager.instance().getClientNetworkHandler().handleServerResources(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,6 @@
|
||||||
package com.minelittlepony.unicopia.network.handler;
|
package com.minelittlepony.unicopia.network.handler;
|
||||||
|
|
||||||
import com.minelittlepony.unicopia.network.MsgBlockDestruction;
|
import com.minelittlepony.unicopia.network.*;
|
||||||
import com.minelittlepony.unicopia.network.MsgCancelPlayerAbility;
|
|
||||||
import com.minelittlepony.unicopia.network.MsgSpawnProjectile;
|
|
||||||
import com.minelittlepony.unicopia.network.MsgTribeSelect;
|
|
||||||
import com.minelittlepony.unicopia.network.MsgUnlockTraits;
|
|
||||||
|
|
||||||
public interface ClientNetworkHandler {
|
public interface ClientNetworkHandler {
|
||||||
|
|
||||||
|
@ -17,4 +13,6 @@ public interface ClientNetworkHandler {
|
||||||
void handleCancelAbility(MsgCancelPlayerAbility packet);
|
void handleCancelAbility(MsgCancelPlayerAbility packet);
|
||||||
|
|
||||||
void handleUnlockTraits(MsgUnlockTraits packet);
|
void handleUnlockTraits(MsgUnlockTraits packet);
|
||||||
|
|
||||||
|
void handleServerResources(MsgServerResources packet);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,23 +1,25 @@
|
||||||
package com.minelittlepony.unicopia.network.handler;
|
package com.minelittlepony.unicopia.network.handler;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
import com.minelittlepony.unicopia.InteractionManager;
|
import com.minelittlepony.unicopia.InteractionManager;
|
||||||
import com.minelittlepony.unicopia.Owned;
|
import com.minelittlepony.unicopia.Owned;
|
||||||
import com.minelittlepony.unicopia.USounds;
|
import com.minelittlepony.unicopia.USounds;
|
||||||
|
import com.minelittlepony.unicopia.ability.magic.spell.trait.SpellTraits;
|
||||||
import com.minelittlepony.unicopia.ability.magic.spell.trait.Trait;
|
import com.minelittlepony.unicopia.ability.magic.spell.trait.Trait;
|
||||||
import com.minelittlepony.unicopia.client.ClientBlockDestructionManager;
|
import com.minelittlepony.unicopia.client.ClientBlockDestructionManager;
|
||||||
import com.minelittlepony.unicopia.client.DiscoveryToast;
|
import com.minelittlepony.unicopia.client.DiscoveryToast;
|
||||||
import com.minelittlepony.unicopia.client.gui.TribeSelectionScreen;
|
import com.minelittlepony.unicopia.client.gui.TribeSelectionScreen;
|
||||||
|
import com.minelittlepony.unicopia.client.gui.spellbook.ClientChapters;
|
||||||
|
import com.minelittlepony.unicopia.client.gui.spellbook.SpellbookChapterList.Chapter;
|
||||||
import com.minelittlepony.unicopia.entity.UEntities;
|
import com.minelittlepony.unicopia.entity.UEntities;
|
||||||
import com.minelittlepony.unicopia.entity.player.Pony;
|
import com.minelittlepony.unicopia.entity.player.Pony;
|
||||||
import com.minelittlepony.unicopia.network.MsgBlockDestruction;
|
import com.minelittlepony.unicopia.network.*;
|
||||||
import com.minelittlepony.unicopia.network.MsgCancelPlayerAbility;
|
|
||||||
import com.minelittlepony.unicopia.network.MsgSpawnProjectile;
|
|
||||||
import com.minelittlepony.unicopia.network.MsgTribeSelect;
|
|
||||||
import com.minelittlepony.unicopia.network.MsgUnlockTraits;
|
|
||||||
|
|
||||||
import net.minecraft.client.MinecraftClient;
|
import net.minecraft.client.MinecraftClient;
|
||||||
import net.minecraft.client.world.ClientWorld;
|
import net.minecraft.client.world.ClientWorld;
|
||||||
import net.minecraft.entity.Entity;
|
import net.minecraft.entity.Entity;
|
||||||
|
import net.minecraft.util.Identifier;
|
||||||
|
|
||||||
public class ClientNetworkHandlerImpl implements ClientNetworkHandler {
|
public class ClientNetworkHandlerImpl implements ClientNetworkHandler {
|
||||||
|
|
||||||
|
@ -74,4 +76,11 @@ public class ClientNetworkHandlerImpl implements ClientNetworkHandler {
|
||||||
DiscoveryToast.show(client.getToastManager(), trait.getSprite());
|
DiscoveryToast.show(client.getToastManager(), trait.getSprite());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
@Override
|
||||||
|
public void handleServerResources(MsgServerResources packet) {
|
||||||
|
SpellTraits.load(packet.traits);
|
||||||
|
ClientChapters.load((Map<Identifier, Chapter>)packet.chapters);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue