From 36d44b3f4dbb450405c948f218e6e0b00e13d621 Mon Sep 17 00:00:00 2001 From: LimonBlaze <94544333+LimonBlaze@users.noreply.github.com> Date: Thu, 19 May 2022 16:55:51 +0800 Subject: [PATCH] Reworked the Badge system, added badge for RecipePower (#537) * Reworked the Badge system, added badge for RecipePower * Added AutoBadgeCallback * Reworked the BadgeManager using DataObjectRegistry * Optimized subpower badge loading logic * Optimized subpower badge loading logic * Optimized imports * Fixed subpower badge loading logic --- .../io/github/apace100/origins/Origins.java | 6 +- .../github/apace100/origins/badge/Badge.java | 39 +++++ .../origins/badge/BadgeFactories.java | 28 ++++ .../apace100/origins/badge/BadgeFactory.java | 26 +++ .../apace100/origins/badge/BadgeManager.java | 156 ++++++++++++++++++ .../origins/badge/CraftingRecipeBadge.java | 84 ++++++++++ .../apace100/origins/badge/SpriteBadge.java | 38 +++++ .../apace100/origins/badge/TooltipBadge.java | 54 ++++++ .../integration/AutoBadgeCallback.java | 30 ++++ .../integration/OriginDataLoadedCallback.java | 7 +- .../apace100/origins/mixin/LoginMixin.java | 9 +- .../origins/mixin/ScreenAccessor.java | 17 ++ .../origins/mixin/WaterBreathingMixin.java | 1 - .../origins/networking/ModPacketsS2C.java | 20 ++- .../apace100/origins/registry/ModTags.java | 1 - .../github/apace100/origins/screen/Badge.java | 48 ------ .../apace100/origins/screen/BadgeManager.java | 97 ----------- .../origins/screen/OriginDisplayScreen.java | 105 +++++------- .../CraftingRecipeTooltipComponent.java | 58 +++++++ .../apace100/origins/util/Constants.java | 3 +- .../resources/assets/origins/lang/de_de.json | 5 +- .../resources/assets/origins/lang/en_us.json | 2 + .../resources/assets/origins/lang/es_ar.json | 8 +- .../resources/assets/origins/lang/es_cl.json | 8 +- .../resources/assets/origins/lang/es_ec.json | 8 +- .../resources/assets/origins/lang/es_es.json | 8 +- .../resources/assets/origins/lang/es_mx.json | 8 +- .../resources/assets/origins/lang/es_uy.json | 8 +- .../resources/assets/origins/lang/es_ve.json | 8 +- .../resources/assets/origins/lang/fr_fr.json | 5 +- .../resources/assets/origins/lang/he_il.json | 5 +- .../resources/assets/origins/lang/id_id.json | 5 +- .../resources/assets/origins/lang/it_it.json | 5 +- .../resources/assets/origins/lang/ja_jp.json | 5 +- .../resources/assets/origins/lang/ko_kr.json | 5 +- .../resources/assets/origins/lang/nl_nl.json | 5 +- .../resources/assets/origins/lang/pl_pl.json | 5 +- .../resources/assets/origins/lang/pt_br.json | 5 +- .../resources/assets/origins/lang/ro_ro.json | 5 +- .../resources/assets/origins/lang/ru_ru.json | 5 +- .../resources/assets/origins/lang/tr_tr.json | 6 +- .../resources/assets/origins/lang/zh_cn.json | 9 +- .../origins/textures/gui/badge/recipe.png | Bin 0 -> 156 bytes .../textures/gui/tooltip/recipe_tooltip.png | Bin 0 -> 797 bytes src/main/resources/origins.mixins.json | 1 + 45 files changed, 704 insertions(+), 257 deletions(-) create mode 100644 src/main/java/io/github/apace100/origins/badge/Badge.java create mode 100644 src/main/java/io/github/apace100/origins/badge/BadgeFactories.java create mode 100644 src/main/java/io/github/apace100/origins/badge/BadgeFactory.java create mode 100644 src/main/java/io/github/apace100/origins/badge/BadgeManager.java create mode 100644 src/main/java/io/github/apace100/origins/badge/CraftingRecipeBadge.java create mode 100644 src/main/java/io/github/apace100/origins/badge/SpriteBadge.java create mode 100644 src/main/java/io/github/apace100/origins/badge/TooltipBadge.java create mode 100644 src/main/java/io/github/apace100/origins/integration/AutoBadgeCallback.java create mode 100644 src/main/java/io/github/apace100/origins/mixin/ScreenAccessor.java delete mode 100644 src/main/java/io/github/apace100/origins/screen/Badge.java delete mode 100644 src/main/java/io/github/apace100/origins/screen/BadgeManager.java create mode 100644 src/main/java/io/github/apace100/origins/screen/tooltip/CraftingRecipeTooltipComponent.java create mode 100644 src/main/resources/assets/origins/textures/gui/badge/recipe.png create mode 100644 src/main/resources/assets/origins/textures/gui/tooltip/recipe_tooltip.png diff --git a/src/main/java/io/github/apace100/origins/Origins.java b/src/main/java/io/github/apace100/origins/Origins.java index ac28a8a4..0e959b6a 100644 --- a/src/main/java/io/github/apace100/origins/Origins.java +++ b/src/main/java/io/github/apace100/origins/Origins.java @@ -7,6 +7,7 @@ import io.github.apace100.apoli.util.NamespaceAlias; import io.github.apace100.calio.mixin.CriteriaRegistryInvoker; import io.github.apace100.calio.util.OrderedResourceListeners; +import io.github.apace100.origins.badge.BadgeManager; import io.github.apace100.origins.command.LayerArgumentType; import io.github.apace100.origins.command.OriginArgumentType; import io.github.apace100.origins.command.OriginCommand; @@ -17,7 +18,6 @@ import io.github.apace100.origins.power.OriginsEntityConditions; import io.github.apace100.origins.power.OriginsPowerTypes; import io.github.apace100.origins.registry.*; -import io.github.apace100.origins.screen.BadgeManager; import io.github.apace100.origins.util.ChoseOriginCriterion; import io.github.apace100.origins.util.OriginsConfigSerializer; import io.github.apace100.origins.util.OriginsJsonConfigSerializer; @@ -45,8 +45,6 @@ public class Origins implements ModInitializer { public static ServerConfig config; private static ConfigSerializer configSerializer; - public static BadgeManager badgeManager; - @Override public void onInitialize() { FabricLoader.getInstance().getModContainer(MODID).ifPresent(modContainer -> { @@ -97,7 +95,7 @@ public void onInitialize() { OrderedResourceListeners.register(new OriginManager()).after(new Identifier("apoli", "powers")).complete(); OrderedResourceListeners.register(new OriginLayers()).after(new Identifier(Origins.MODID, "origins")).complete(); - badgeManager = new BadgeManager(); + BadgeManager.init(); } public static void serializeConfig() { diff --git a/src/main/java/io/github/apace100/origins/badge/Badge.java b/src/main/java/io/github/apace100/origins/badge/Badge.java new file mode 100644 index 00000000..834e93cf --- /dev/null +++ b/src/main/java/io/github/apace100/origins/badge/Badge.java @@ -0,0 +1,39 @@ +package io.github.apace100.origins.badge; + +import io.github.apace100.calio.data.SerializableData; +import io.github.apace100.calio.registry.DataObject; +import io.github.apace100.calio.registry.DataObjectFactory; +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; +import net.minecraft.client.font.TextRenderer; +import net.minecraft.client.gui.tooltip.TooltipComponent; +import net.minecraft.network.PacketByteBuf; +import net.minecraft.util.Identifier; + +import java.util.List; + +public interface Badge extends DataObject { + + Identifier spriteId(); + + boolean hasTooltip(); + + @Environment(EnvType.CLIENT) + List getTooltipComponents(TextRenderer textRenderer, int widthLimit, float time); + + SerializableData.Instance toData(SerializableData.Instance instance); + + BadgeFactory getBadgeFactory(); + + @Override + default DataObjectFactory getFactory() { + return this.getBadgeFactory(); + } + + default void writeBuf(PacketByteBuf buf) { + DataObjectFactory factory = this.getFactory(); + buf.writeIdentifier(this.getBadgeFactory().id()); + factory.getData().write(buf, factory.toData(this)); + } + +} diff --git a/src/main/java/io/github/apace100/origins/badge/BadgeFactories.java b/src/main/java/io/github/apace100/origins/badge/BadgeFactories.java new file mode 100644 index 00000000..3d443c3a --- /dev/null +++ b/src/main/java/io/github/apace100/origins/badge/BadgeFactories.java @@ -0,0 +1,28 @@ +package io.github.apace100.origins.badge; + +import io.github.apace100.calio.data.SerializableData; +import io.github.apace100.calio.data.SerializableDataTypes; +import io.github.apace100.origins.Origins; + +public final class BadgeFactories { + + public static final BadgeFactory SPRITE = new BadgeFactory(Origins.identifier("sprite"), + new SerializableData() + .add("sprite", SerializableDataTypes.IDENTIFIER), + SpriteBadge::new); + + public static final BadgeFactory TOOLTIP = new BadgeFactory(Origins.identifier("tooltip"), + new SerializableData() + .add("sprite", SerializableDataTypes.IDENTIFIER) + .add("text", SerializableDataTypes.TEXT), + TooltipBadge::new); + + public static final BadgeFactory CRAFTING_RECIPE = new BadgeFactory(Origins.identifier("crafting_recipe"), + new SerializableData() + .add("sprite", SerializableDataTypes.IDENTIFIER) + .add("recipe", SerializableDataTypes.RECIPE) + .add("prefix", SerializableDataTypes.TEXT, null) + .add("suffix", SerializableDataTypes.TEXT, null), + CraftingRecipeBadge::new); + +} diff --git a/src/main/java/io/github/apace100/origins/badge/BadgeFactory.java b/src/main/java/io/github/apace100/origins/badge/BadgeFactory.java new file mode 100644 index 00000000..f2a68ef3 --- /dev/null +++ b/src/main/java/io/github/apace100/origins/badge/BadgeFactory.java @@ -0,0 +1,26 @@ +package io.github.apace100.origins.badge; + +import io.github.apace100.calio.data.SerializableData; +import io.github.apace100.calio.registry.DataObjectFactory; +import net.minecraft.util.Identifier; + +import java.util.function.Function; + +public record BadgeFactory(Identifier id, SerializableData data, Function factory) implements DataObjectFactory { + + @Override + public SerializableData getData() { + return data; + } + + @Override + public Badge fromData(SerializableData.Instance instance) { + return factory.apply(instance); + } + + @Override + public SerializableData.Instance toData(Badge badge) { + return badge.toData(data.new Instance()); + } + +} \ No newline at end of file diff --git a/src/main/java/io/github/apace100/origins/badge/BadgeManager.java b/src/main/java/io/github/apace100/origins/badge/BadgeManager.java new file mode 100644 index 00000000..2e05c917 --- /dev/null +++ b/src/main/java/io/github/apace100/origins/badge/BadgeManager.java @@ -0,0 +1,156 @@ +package io.github.apace100.origins.badge; + +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import io.github.apace100.apoli.integration.PostPowerLoadCallback; +import io.github.apace100.apoli.integration.PostPowerReloadCallback; +import io.github.apace100.apoli.integration.PrePowerReloadCallback; +import io.github.apace100.apoli.power.*; +import io.github.apace100.calio.registry.DataObjectRegistry; +import io.github.apace100.origins.Origins; +import io.github.apace100.origins.integration.AutoBadgeCallback; +import io.github.apace100.origins.networking.ModPackets; +import io.github.apace100.origins.util.PowerKeyManager; +import io.netty.buffer.Unpooled; +import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking; +import net.minecraft.client.option.KeyBinding; +import net.minecraft.inventory.CraftingInventory; +import net.minecraft.network.PacketByteBuf; +import net.minecraft.recipe.Recipe; +import net.minecraft.recipe.ShapedRecipe; +import net.minecraft.server.network.ServerPlayerEntity; +import net.minecraft.text.LiteralText; +import net.minecraft.text.Text; +import net.minecraft.text.TranslatableText; +import net.minecraft.util.Identifier; + +import java.util.*; + +public final class BadgeManager { + public static final DataObjectRegistry REGISTRY = new DataObjectRegistry.Builder<>(Origins.identifier("badge"), Badge.class) + .readFromData("badges", true) + .dataErrorHandler((id, exception) -> Origins.LOGGER.error("Failed to read badge " + ", caused by", exception)) + .defaultFactory(BadgeFactories.TOOLTIP) + .buildAndRegister(); + private static final Map> BADGES = new HashMap<>(); + private static final Map> MULTIPLE_POWERS = new HashMap<>(); + + private static final Identifier TOGGLE_BADGE_SPRITE = Origins.identifier("textures/gui/badge/toggle.png"); + private static final Identifier ACTIVE_BADGE_SPRITE = Origins.identifier("textures/gui/badge/active.png"); + private static final Identifier RECIPE_BADGE_SPRITE = Origins.identifier("textures/gui/badge/recipe.png"); + + public static void init() { + //register builtin badge types + register(BadgeFactories.SPRITE); + register(BadgeFactories.TOOLTIP); + register(BadgeFactories.CRAFTING_RECIPE); + //register callbacks + PrePowerReloadCallback.EVENT.register(BadgeManager::clear); + PowerTypes.registerAdditionalData("badges", BadgeManager::readCustomBadges); + PostPowerLoadCallback.EVENT.register(BadgeManager::readAutoBadges); + AutoBadgeCallback.EVENT.register(BadgeManager::createAutoBadges); + PostPowerReloadCallback.EVENT.register(BadgeManager::mergeMultiplePowerBadges); + } + + public static void register(BadgeFactory factory) { + REGISTRY.registerFactory(factory.id(), factory); + } + + public static void putPowerBadge(Identifier powerId, Badge badge) { + List badgeList = BADGES.computeIfAbsent(powerId, id -> new LinkedList<>()); + badgeList.add(badge); + } + + public static List getPowerBadges(Identifier powerId) { + return BADGES.computeIfAbsent(powerId, id -> new LinkedList<>()); + } + + public static void clear() { + BADGES.clear(); + } + + public static void sync(ServerPlayerEntity player) { + REGISTRY.sync(player); + PacketByteBuf badgeData = new PacketByteBuf(Unpooled.buffer()); + badgeData.writeInt(BADGES.size()); + BADGES.forEach((id, list) -> { + badgeData.writeIdentifier(id); + badgeData.writeInt(list.size()); + list.forEach(badge -> badge.writeBuf(badgeData)); + }); + ServerPlayNetworking.send(player, ModPackets.BADGE_LIST, badgeData); + } + + public static void readCustomBadges(Identifier powerId, Identifier factoryId, boolean isSubPower, JsonElement data, PowerType powerType) { + if(!powerType.isHidden() || isSubPower) { + if(data.isJsonArray()) { + for(JsonElement badgeJson : data.getAsJsonArray()) { + if(badgeJson.isJsonPrimitive()) { + Identifier badgeId = Identifier.tryParse(badgeJson.getAsString()); + if(badgeId != null) { + Badge badge = REGISTRY.get(badgeId); + if(badge != null) { + putPowerBadge(powerId, badge); + } else { + Origins.LOGGER.error("\"badges\" field in power \"{}\" is referring a undefined badge \"{}\" !", powerId, badgeId); + } + } else { + Origins.LOGGER.error("\"badges\" field in power \"{}\" is not a valid identifier!", powerId); + } + } else if(badgeJson.isJsonObject()) { + try { + putPowerBadge(powerId, REGISTRY.readDataObject(badgeJson)); + } catch(Exception exception) { + Origins.LOGGER.error("\"badges\" field in power \"" + powerId + + "\" contained an JSON object entry that cannot be resolved!", exception); + } + } else { + Origins.LOGGER.error("\"badges\" field in power \"" + powerId + + "\" contained an entry that was a JSON array, which is not allowed!"); + } + } + } else { + Origins.LOGGER.error("\"badges\" field in power \"" + powerId + "\" should be an array."); + } + } + } + + public static void readAutoBadges(Identifier powerId, Identifier factoryId, boolean isSubPower, JsonObject json, PowerType powerType) { + if(powerType instanceof MultiplePowerType mp) { + MULTIPLE_POWERS.put(powerId, mp.getSubPowers()); + } else if((!BADGES.containsKey(powerId) || BADGES.get(powerId).size() == 0) && (!powerType.isHidden() || isSubPower)) { + AutoBadgeCallback.EVENT.invoker().createAutoBadge(powerId, powerType); + } + } + + public static void createAutoBadges(Identifier powerId, PowerType powerType) { + Power power = powerType.create(null); + if(power instanceof Active active) { + boolean toggle = active instanceof TogglePower || active instanceof ToggleNightVisionPower; + Text keyText = new LiteralText("[") + .append(KeyBinding.getLocalizedName(PowerKeyManager.getKeyIdentifier(powerId)).get()) + .append(new LiteralText("]")); + putPowerBadge(powerId, new TooltipBadge(toggle ? TOGGLE_BADGE_SPRITE : ACTIVE_BADGE_SPRITE, + toggle ? new TranslatableText("origins.gui.badge.toggle", keyText) + : new TranslatableText("origins.gui.badge.active", keyText) + )); + } else if(power instanceof RecipePower recipePower) { + Recipe recipe = recipePower.getRecipe(); + String type = recipe instanceof ShapedRecipe ? "shaped" : "shapeless"; + putPowerBadge(powerId, new CraftingRecipeBadge(RECIPE_BADGE_SPRITE, recipe, + new TranslatableText("origins.gui.badge.recipe.crafting." + type), null + )); + } + } + + public static void mergeMultiplePowerBadges() { + MULTIPLE_POWERS.forEach((powerId, subPowerIds) -> + subPowerIds.forEach(subPowerId -> + BADGES.computeIfAbsent(powerId, id -> new LinkedList<>()) + .addAll(BADGES.computeIfAbsent(subPowerId, id -> new LinkedList<>())) + ) + ); + MULTIPLE_POWERS.clear(); + } + +} diff --git a/src/main/java/io/github/apace100/origins/badge/CraftingRecipeBadge.java b/src/main/java/io/github/apace100/origins/badge/CraftingRecipeBadge.java new file mode 100644 index 00000000..a9fc8dab --- /dev/null +++ b/src/main/java/io/github/apace100/origins/badge/CraftingRecipeBadge.java @@ -0,0 +1,84 @@ +package io.github.apace100.origins.badge; + +import io.github.apace100.calio.data.SerializableData; +import io.github.apace100.origins.screen.tooltip.CraftingRecipeTooltipComponent; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.font.TextRenderer; +import net.minecraft.client.gui.tooltip.TooltipComponent; +import net.minecraft.inventory.CraftingInventory; +import net.minecraft.item.ItemStack; +import net.minecraft.recipe.Ingredient; +import net.minecraft.recipe.Recipe; +import net.minecraft.text.LiteralText; +import net.minecraft.text.Text; +import net.minecraft.util.Formatting; +import net.minecraft.util.Identifier; +import net.minecraft.util.collection.DefaultedList; +import net.minecraft.util.math.MathHelper; + +import javax.annotation.Nullable; +import java.util.LinkedList; +import java.util.List; + +public record CraftingRecipeBadge(Identifier spriteId, + Recipe recipe, + @Nullable Text prefix, + @Nullable Text suffix) implements Badge { + + public CraftingRecipeBadge(SerializableData.Instance instance) { + this(instance.getId("sprite"), + instance.get("recipe"), + instance.get("prefix"), + instance.get("suffix")); + } + + @Override + public boolean hasTooltip() { + return true; + } + + public DefaultedList peekInputs(float time) { + int seed = MathHelper.floor(time / 30); + DefaultedList inputs = DefaultedList.ofSize(9, ItemStack.EMPTY); + List ingredients = this.recipe.getIngredients(); + for(int index = 0; index < ingredients.size(); ++index) { + ItemStack[] stacks = ingredients.get(index).getMatchingStacks(); + if(stacks.length > 0) inputs.set(index, stacks[seed % stacks.length]); + } + return inputs; + } + + @Override + public List getTooltipComponents(TextRenderer textRenderer, int widthLimit, float time) { + List tooltips = new LinkedList<>(); + if(MinecraftClient.getInstance().options.advancedItemTooltips) { + Text recipeIdText = new LiteralText(recipe.getId().toString()).formatted(Formatting.DARK_GRAY); + widthLimit = Math.max(130, textRenderer.getWidth(recipeIdText)); + if(prefix != null) TooltipBadge.addLines(tooltips, prefix, textRenderer, widthLimit); + tooltips.add(new CraftingRecipeTooltipComponent(this.peekInputs(time), this.recipe.getOutput())); + if(suffix != null) TooltipBadge.addLines(tooltips, suffix, textRenderer, widthLimit); + TooltipBadge.addLines(tooltips, recipeIdText, textRenderer, widthLimit); + } else { + widthLimit = 130; + if(prefix != null) TooltipBadge.addLines(tooltips, prefix, textRenderer, widthLimit); + tooltips.add(new CraftingRecipeTooltipComponent(this.peekInputs(time), this.recipe.getOutput())); + if(suffix != null) TooltipBadge.addLines(tooltips, suffix, textRenderer, widthLimit); + } + return tooltips; + } + + @Override + public SerializableData.Instance toData(SerializableData.Instance instance) { + instance.set("sprite", spriteId); + instance.set("recipe", recipe); + instance.set("prefix", prefix); + instance.set("suffix", suffix); + return instance; + } + + @Override + public BadgeFactory getBadgeFactory() { + return BadgeFactories.CRAFTING_RECIPE; + } + +} diff --git a/src/main/java/io/github/apace100/origins/badge/SpriteBadge.java b/src/main/java/io/github/apace100/origins/badge/SpriteBadge.java new file mode 100644 index 00000000..ce2a930a --- /dev/null +++ b/src/main/java/io/github/apace100/origins/badge/SpriteBadge.java @@ -0,0 +1,38 @@ +package io.github.apace100.origins.badge; + +import io.github.apace100.calio.data.SerializableData; +import net.minecraft.client.font.TextRenderer; +import net.minecraft.client.gui.tooltip.TooltipComponent; +import net.minecraft.util.Identifier; + +import java.util.ArrayList; +import java.util.List; + +public record SpriteBadge(Identifier spriteId) implements Badge { + + public SpriteBadge(SerializableData.Instance instance) { + this(instance.getId("sprite")); + } + + @Override + public boolean hasTooltip() { + return false; + } + + @Override + public List getTooltipComponents(TextRenderer textRenderer, int widthLimit, float time) { + return new ArrayList<>(); + } + + @Override + public SerializableData.Instance toData(SerializableData.Instance instance) { + instance.set("sprite", spriteId); + return instance; + } + + @Override + public BadgeFactory getBadgeFactory() { + return BadgeFactories.SPRITE; + } + +} diff --git a/src/main/java/io/github/apace100/origins/badge/TooltipBadge.java b/src/main/java/io/github/apace100/origins/badge/TooltipBadge.java new file mode 100644 index 00000000..91a55667 --- /dev/null +++ b/src/main/java/io/github/apace100/origins/badge/TooltipBadge.java @@ -0,0 +1,54 @@ +package io.github.apace100.origins.badge; + +import io.github.apace100.calio.data.SerializableData; +import net.minecraft.client.font.TextRenderer; +import net.minecraft.client.gui.tooltip.OrderedTextTooltipComponent; +import net.minecraft.client.gui.tooltip.TooltipComponent; +import net.minecraft.text.OrderedText; +import net.minecraft.text.Text; +import net.minecraft.util.Identifier; + +import java.util.LinkedList; +import java.util.List; + +public record TooltipBadge(Identifier spriteId, Text text) implements Badge { + + public TooltipBadge(SerializableData.Instance instance) { + this(instance.getId("sprite"), instance.get("text")); + } + + @Override + public boolean hasTooltip() { + return true; + } + + public static void addLines(List tooltips, Text text, TextRenderer textRenderer, int widthLimit) { + if(textRenderer.getWidth(text) > widthLimit) { + for(OrderedText orderedText : textRenderer.wrapLines(text, widthLimit)) { + tooltips.add(new OrderedTextTooltipComponent(orderedText)); + } + } else { + tooltips.add(new OrderedTextTooltipComponent(text.asOrderedText())); + } + } + + @Override + public List getTooltipComponents(TextRenderer textRenderer, int widthLimit, float time) { + List tooltips = new LinkedList<>(); + addLines(tooltips, text, textRenderer, widthLimit); + return tooltips; + } + + @Override + public SerializableData.Instance toData(SerializableData.Instance instance) { + instance.set("sprite", spriteId); + instance.set("text", text); + return instance; + } + + @Override + public BadgeFactory getBadgeFactory() { + return BadgeFactories.TOOLTIP; + } + +} diff --git a/src/main/java/io/github/apace100/origins/integration/AutoBadgeCallback.java b/src/main/java/io/github/apace100/origins/integration/AutoBadgeCallback.java new file mode 100644 index 00000000..ba4f17d9 --- /dev/null +++ b/src/main/java/io/github/apace100/origins/integration/AutoBadgeCallback.java @@ -0,0 +1,30 @@ +package io.github.apace100.origins.integration; + +import io.github.apace100.apoli.power.PowerType; +import io.github.apace100.apoli.integration.PostPowerReloadCallback; +import io.github.apace100.origins.badge.Badge; +import io.github.apace100.origins.badge.BadgeManager; +import net.fabricmc.fabric.api.event.Event; +import net.fabricmc.fabric.api.event.EventFactory; +import net.minecraft.util.Identifier; + +/** + * Callback which is called when a power hasn't got any badges from json and was expecting a fallback
+ * Badge fallbacks can be added on this callback.
+ * The callback is not informing whether the power is a subpower,
+ * as all badges from subpowers will be merged to the main power on {@link PostPowerReloadCallback}.
+ * Use {@link BadgeManager#putPowerBadge(Identifier, Badge)} to put a badge to the {@link BadgeManager}
+ */ +public interface AutoBadgeCallback { + + Event EVENT = EventFactory.createArrayBacked(AutoBadgeCallback.class, + (listeners) -> (powerId, powerType) -> { + for(AutoBadgeCallback listener : listeners) { + listener.createAutoBadge(powerId, powerType); + } + } + ); + + void createAutoBadge(Identifier powerId, PowerType powerType); + +} diff --git a/src/main/java/io/github/apace100/origins/integration/OriginDataLoadedCallback.java b/src/main/java/io/github/apace100/origins/integration/OriginDataLoadedCallback.java index df2488d4..9a56a5b9 100644 --- a/src/main/java/io/github/apace100/origins/integration/OriginDataLoadedCallback.java +++ b/src/main/java/io/github/apace100/origins/integration/OriginDataLoadedCallback.java @@ -4,11 +4,10 @@ import net.fabricmc.fabric.api.event.EventFactory; /** - * Callback which is called when all of Origins data is loaded. - * This includes powers, origins and layers. + * Callback which is called when all of Origins data is loaded.
+ * This includes powers, origins and layers.
* It is not only called on the server, but also on the client when they - * have received this data from the server and incorporated it into the registries. - * + * have received this data from the server and incorporated it into the registries.
*/ public interface OriginDataLoadedCallback { Event EVENT = EventFactory.createArrayBacked(OriginDataLoadedCallback.class, diff --git a/src/main/java/io/github/apace100/origins/mixin/LoginMixin.java b/src/main/java/io/github/apace100/origins/mixin/LoginMixin.java index c586f857..49146513 100644 --- a/src/main/java/io/github/apace100/origins/mixin/LoginMixin.java +++ b/src/main/java/io/github/apace100/origins/mixin/LoginMixin.java @@ -1,14 +1,13 @@ package io.github.apace100.origins.mixin; import dev.onyxstudios.cca.api.v3.component.ComponentProvider; -import io.github.apace100.origins.Origins; +import io.github.apace100.origins.badge.BadgeManager; import io.github.apace100.origins.component.OriginComponent; import io.github.apace100.origins.networking.ModPackets; import io.github.apace100.origins.origin.Origin; import io.github.apace100.origins.origin.OriginLayers; import io.github.apace100.origins.origin.OriginRegistry; import io.github.apace100.origins.registry.ModComponents; -import io.github.apace100.origins.screen.BadgeManager; import io.netty.buffer.Unpooled; import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking; import net.minecraft.network.ClientConnection; @@ -29,7 +28,7 @@ public abstract class LoginMixin { @Shadow public abstract List getPlayerList(); - @Inject(at = @At("TAIL"), method = "Lnet/minecraft/server/PlayerManager;onPlayerConnect(Lnet/minecraft/network/ClientConnection;Lnet/minecraft/server/network/ServerPlayerEntity;)V") + @Inject(at = @At("TAIL"), method = "onPlayerConnect(Lnet/minecraft/network/ClientConnection;Lnet/minecraft/server/network/ServerPlayerEntity;)V") private void openOriginsGui(ClientConnection connection, ServerPlayerEntity player, CallbackInfo info) { OriginComponent component = ModComponents.ORIGIN.get(player); @@ -56,9 +55,7 @@ private void openOriginsGui(ClientConnection connection, ServerPlayerEntity play ServerPlayNetworking.send(player, ModPackets.ORIGIN_LIST, originListData); ServerPlayNetworking.send(player, ModPackets.LAYER_LIST, originLayerData); - PacketByteBuf badgeData = new PacketByteBuf(Unpooled.buffer()); - Origins.badgeManager.writeSyncData(badgeData); - ServerPlayNetworking.send(player, ModPackets.BADGE_LIST, badgeData); + BadgeManager.sync(player); List playerList = getPlayerList(); playerList.forEach(spe -> ModComponents.ORIGIN.syncWith(spe, ComponentProvider.fromEntity(player))); diff --git a/src/main/java/io/github/apace100/origins/mixin/ScreenAccessor.java b/src/main/java/io/github/apace100/origins/mixin/ScreenAccessor.java new file mode 100644 index 00000000..dd6031a9 --- /dev/null +++ b/src/main/java/io/github/apace100/origins/mixin/ScreenAccessor.java @@ -0,0 +1,17 @@ +package io.github.apace100.origins.mixin; + +import net.minecraft.client.gui.screen.Screen; +import net.minecraft.client.gui.tooltip.TooltipComponent; +import net.minecraft.client.util.math.MatrixStack; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Invoker; + +import java.util.List; + +@Mixin(Screen.class) +public interface ScreenAccessor { + + @Invoker("renderTooltipFromComponents") + void invokeRenderTooltipFromComponents(MatrixStack matrices, List components, int x, int y); + +} diff --git a/src/main/java/io/github/apace100/origins/mixin/WaterBreathingMixin.java b/src/main/java/io/github/apace100/origins/mixin/WaterBreathingMixin.java index 1c0bbac2..fe2b03b4 100644 --- a/src/main/java/io/github/apace100/origins/mixin/WaterBreathingMixin.java +++ b/src/main/java/io/github/apace100/origins/mixin/WaterBreathingMixin.java @@ -11,7 +11,6 @@ import net.minecraft.fluid.Fluid; import net.minecraft.particle.ParticleTypes; import net.minecraft.tag.FluidTags; -import net.minecraft.tag.Tag; import net.minecraft.tag.TagKey; import net.minecraft.world.World; import org.spongepowered.asm.mixin.Mixin; diff --git a/src/main/java/io/github/apace100/origins/networking/ModPacketsS2C.java b/src/main/java/io/github/apace100/origins/networking/ModPacketsS2C.java index a5218a8d..77c7eee7 100644 --- a/src/main/java/io/github/apace100/origins/networking/ModPacketsS2C.java +++ b/src/main/java/io/github/apace100/origins/networking/ModPacketsS2C.java @@ -3,6 +3,8 @@ import io.github.apace100.calio.data.SerializableData; import io.github.apace100.origins.Origins; import io.github.apace100.origins.OriginsClient; +import io.github.apace100.origins.badge.Badge; +import io.github.apace100.origins.badge.BadgeManager; import io.github.apace100.origins.component.OriginComponent; import io.github.apace100.origins.integration.OriginDataLoadedCallback; import io.github.apace100.origins.origin.Origin; @@ -10,7 +12,6 @@ import io.github.apace100.origins.origin.OriginLayers; import io.github.apace100.origins.origin.OriginRegistry; import io.github.apace100.origins.registry.ModComponents; -import io.github.apace100.origins.screen.Badge; import io.github.apace100.origins.screen.ChooseOriginScreen; import io.github.apace100.origins.screen.WaitForNextLayerScreen; import io.netty.util.concurrent.Future; @@ -137,18 +138,21 @@ private static void receiveBadgeList(MinecraftClient minecraftClient, ClientPlay List badgeList = new LinkedList<>(); int badgeCount = packetByteBuf.readInt(); for(int j = 0; j < badgeCount; j++) { - Badge badge = Badge.fromData(Badge.DATA.read(packetByteBuf)); + Badge badge = BadgeManager.REGISTRY.receiveDataObject(packetByteBuf); badgeList.add(badge); } badges.put(powerId, badgeList); } minecraftClient.execute(() -> { - Origins.badgeManager.clear(); - badges.forEach((id, list) -> { - list.forEach(badge -> { - Origins.badgeManager.addBadge(id, badge); - }); - }); + BadgeManager.clear(); + int badgeCount = 0; + for(Map.Entry> badgeEntry : badges.entrySet()) { + for(Badge badge : badgeEntry.getValue()) { + BadgeManager.putPowerBadge(badgeEntry.getKey(), badge); + badgeCount++; + } + } + Origins.LOGGER.info("Recieved {} badges from server!", badgeCount); }); } catch (Exception e) { Origins.LOGGER.error(e); diff --git a/src/main/java/io/github/apace100/origins/registry/ModTags.java b/src/main/java/io/github/apace100/origins/registry/ModTags.java index 4558e4b6..c61ba220 100644 --- a/src/main/java/io/github/apace100/origins/registry/ModTags.java +++ b/src/main/java/io/github/apace100/origins/registry/ModTags.java @@ -3,7 +3,6 @@ import io.github.apace100.origins.Origins; import net.minecraft.block.Block; import net.minecraft.item.Item; -import net.minecraft.tag.Tag; import net.minecraft.tag.TagKey; import net.minecraft.util.Identifier; import net.minecraft.util.registry.Registry; diff --git a/src/main/java/io/github/apace100/origins/screen/Badge.java b/src/main/java/io/github/apace100/origins/screen/Badge.java deleted file mode 100644 index a733a3be..00000000 --- a/src/main/java/io/github/apace100/origins/screen/Badge.java +++ /dev/null @@ -1,48 +0,0 @@ -package io.github.apace100.origins.screen; - -import io.github.apace100.calio.data.SerializableData; -import io.github.apace100.calio.data.SerializableDataTypes; -import io.github.apace100.origins.Origins; -import net.minecraft.util.Identifier; - -public class Badge { - - public static final SerializableData DATA = new SerializableData() - .add("sprite", SerializableDataTypes.IDENTIFIER) - .add("text", SerializableDataTypes.STRING); - - public static final Badge ACTIVE = new Badge( - Origins.identifier("textures/gui/badge/active.png"), - "origins.gui.badge.active"); - - public static final Badge TOGGLE = new Badge( - Origins.identifier("textures/gui/badge/toggle.png"), - "origins.gui.badge.toggle"); - - private final Identifier spriteLocation; - private final String hoverText; - - public Badge(Identifier spriteLocation, String hoverText) { - this.spriteLocation = spriteLocation; - this.hoverText = hoverText; - } - - public String getHoverText() { - return hoverText; - } - - public Identifier getSpriteLocation() { - return spriteLocation; - } - - public SerializableData.Instance getData() { - SerializableData.Instance data = DATA.new Instance(); - data.set("sprite", spriteLocation); - data.set("text", hoverText); - return data; - } - - public static Badge fromData(SerializableData.Instance data) { - return new Badge(data.getId("sprite"), data.getString("text")); - } -} diff --git a/src/main/java/io/github/apace100/origins/screen/BadgeManager.java b/src/main/java/io/github/apace100/origins/screen/BadgeManager.java deleted file mode 100644 index 93183fee..00000000 --- a/src/main/java/io/github/apace100/origins/screen/BadgeManager.java +++ /dev/null @@ -1,97 +0,0 @@ -package io.github.apace100.origins.screen; - -import com.google.common.collect.Lists; -import io.github.apace100.apoli.integration.PostPowerLoadCallback; -import io.github.apace100.apoli.integration.PowerReloadCallback; -import io.github.apace100.apoli.power.*; -import io.github.apace100.origins.Origins; -import net.minecraft.network.PacketByteBuf; -import net.minecraft.util.Identifier; - -import java.util.HashMap; -import java.util.LinkedList; -import java.util.List; - -public class BadgeManager { - - private final HashMap> badges = new HashMap<>(); - - public BadgeManager() { - PowerReloadCallback.EVENT.register(this::clear); - PowerTypes.registerAdditionalData("badges", (powerId, factoryId, isSubPower, data, powerType) -> { - if(!powerType.isHidden()) { - if(data.isJsonArray()) { - badges.put(powerId, new LinkedList<>()); - data.getAsJsonArray().forEach(badgeJson -> { - if(badgeJson.isJsonObject()) { - Badge badge = Badge.fromData(Badge.DATA.read(badgeJson.getAsJsonObject())); - addBadge(powerId, badge); - } else { - Origins.LOGGER.error("\"badges\" field in power \"" + powerId - + "\" contained an entry that was not a JSON object."); - } - }); - } else { - Origins.LOGGER.error("\"badges\" field in power \"" + powerId + "\" should be an array."); - } - } - }); - PostPowerLoadCallback.EVENT.register((powerId, factoryId, isSubPower, data, powerType) -> { - if(!badges.containsKey(powerId) || badges.get(powerId).size() == 0) { - Power power = powerType.create(null); - Badge autoBadge = null; - if(power instanceof TogglePower || power instanceof ToggleNightVisionPower) { - autoBadge = Badge.TOGGLE; - } else if(power instanceof Active) { - autoBadge = Badge.ACTIVE; - } - if(autoBadge == null) { - if(powerType instanceof MultiplePowerType mp) { - for(Identifier subPower : mp.getSubPowers()) { - if(PowerTypeRegistry.contains(subPower)) { - Power sp = PowerTypeRegistry.get(subPower).create(null); - if(sp instanceof TogglePower || sp instanceof ToggleNightVisionPower) { - autoBadge = Badge.TOGGLE; - break; - } else if(sp instanceof Active) { - autoBadge = Badge.ACTIVE; - break; - } - } - } - } - } - if(autoBadge != null) { - addBadge(powerId, autoBadge); - } - } - }); - } - - public void clear() { - badges.clear(); - } - - public void addBadge(Identifier powerId, Badge badge) { - List badgeList = badges.computeIfAbsent(powerId, id -> new LinkedList<>()); - badgeList.add(badge); - } - - public List getBadges(Identifier powerId) { - if(!badges.containsKey(powerId)) { - return Lists.newArrayList(); - } - return badges.get(powerId); - } - - public void writeSyncData(PacketByteBuf buf) { - buf.writeInt(badges.size()); - badges.forEach((id, list) -> { - buf.writeIdentifier(id); - buf.writeInt(list.size()); - list.forEach(badge -> { - Badge.DATA.write(buf, badge.getData()); - }); - }); - } -} diff --git a/src/main/java/io/github/apace100/origins/screen/OriginDisplayScreen.java b/src/main/java/io/github/apace100/origins/screen/OriginDisplayScreen.java index 4a23359a..12c82a66 100644 --- a/src/main/java/io/github/apace100/origins/screen/OriginDisplayScreen.java +++ b/src/main/java/io/github/apace100/origins/screen/OriginDisplayScreen.java @@ -3,12 +3,15 @@ import com.mojang.blaze3d.systems.RenderSystem; import io.github.apace100.apoli.power.PowerType; import io.github.apace100.origins.Origins; +import io.github.apace100.origins.badge.Badge; +import io.github.apace100.origins.badge.BadgeManager; +import io.github.apace100.origins.mixin.ScreenAccessor; import io.github.apace100.origins.origin.Impact; import io.github.apace100.origins.origin.Origin; import io.github.apace100.origins.origin.OriginLayer; -import io.github.apace100.origins.util.PowerKeyManager; +import net.minecraft.client.font.TextRenderer; import net.minecraft.client.gui.screen.Screen; -import net.minecraft.client.option.KeyBinding; +import net.minecraft.client.gui.tooltip.TooltipComponent; import net.minecraft.client.util.math.MatrixStack; import net.minecraft.item.ItemStack; import net.minecraft.text.*; @@ -22,7 +25,6 @@ public class OriginDisplayScreen extends Screen { private static final Identifier WINDOW = new Identifier(Origins.MODID, "textures/gui/choose_origin.png"); - private Origin origin; private OriginLayer layer; private boolean isOriginRandom; @@ -32,23 +34,25 @@ public class OriginDisplayScreen extends Screen { protected static final int windowHeight = 182; protected int scrollPos = 0; private int currentMaxScroll = 0; + private float time = 0; protected int guiTop, guiLeft; protected final boolean showDirtBackground; - private final List renderedBadges = new LinkedList<>(); + private final LinkedList renderedBadges = new LinkedList<>(); public OriginDisplayScreen(Text title, boolean showDirtBackground) { super(title); this.showDirtBackground = showDirtBackground; } - public void showOrigin(Origin origin, OriginLayer layer, boolean isRandom) { + public void showOrigin(Origin origin,OriginLayer layer, boolean isRandom) { this.origin = origin; this.layer = layer; this.isOriginRandom = isRandom; this.scrollPos = 0; + this.time = 0; } public void setRandomOriginText(Text text) { @@ -82,6 +86,7 @@ public void renderBackground(MatrixStack matrices, int vOffset) { @Override public void render(MatrixStack matrices, int mouseX, int mouseY, float delta) { renderedBadges.clear(); + this.time += delta; this.renderBackground(matrices); this.renderOriginWindow(matrices, mouseX, mouseY); super.render(matrices, mouseX, mouseY, delta); @@ -158,51 +163,14 @@ public boolean mouseDragged(double mouseX, double mouseY, int button, double del } private void renderBadgeTooltip(MatrixStack matrices, int mouseX, int mouseY) { - for(RenderedBadge badge : renderedBadges) { - if(mouseX >= badge.x && mouseX < badge.x + 9) { - if(mouseY >= badge.y && mouseY < badge.y + 9) { - String hoverText = badge.badge.getHoverText(); - String keyId = PowerKeyManager.getKeyIdentifier(badge.power); - Text keybindText = KeyBinding.getLocalizedName(keyId).get(); - if(keybindText.getString().isEmpty()) { - keybindText = new TranslatableText(keyId).formatted(Formatting.ITALIC); - } - Text keyText = new LiteralText("[") - .append(keybindText) - .append("]"); - int maxWidth = width - mouseX - 24; - if(mouseX > width / 2) { - maxWidth = mouseX - 24; - } - if(hoverText.contains("\n")) { - List lines = new LinkedList<>(); - String[] texts = hoverText.split("\n"); - for (String text : texts) { - Text t = new TranslatableText(text, keyText); - if(textRenderer.getWidth(t) > maxWidth) { - List wrapped = textRenderer.wrapLines(t, maxWidth); - lines.addAll(wrapped); - } else { - lines.add(t.asOrderedText()); - } - } - renderOrderedTooltip(matrices, lines, mouseX, mouseY); - } else { - Text text = new TranslatableText( - hoverText, - keyText - ); - - if(textRenderer.getWidth(text) > maxWidth) { - List wrapped = textRenderer.wrapLines(text, maxWidth); - renderOrderedTooltip(matrices, wrapped, mouseX, mouseY); - } else { - renderTooltip(matrices, text, mouseX, mouseY); - } - - } - break; - } + for(RenderedBadge rb : renderedBadges) { + if(mouseX >= rb.x && + mouseX < rb.x + 9 && + mouseY >= rb.y && + mouseY < rb.y + 9 && + rb.hasTooltip()) { + int widthLimit = width - mouseX - 24; + ((ScreenAccessor)this).invokeRenderTooltipFromComponents(matrices, rb.getTooltipComponents(textRenderer, widthLimit), mouseX, mouseY); } } } @@ -321,18 +289,14 @@ private void renderOriginContent(MatrixStack matrices, int mouseX, int mouseY) { if(y >= startY - 24 && y <= endY + 12) { textRenderer.draw(matrices, name, x, y, 0xFFFFFF); int tw = textRenderer.getWidth(name); - List badges = Origins.badgeManager.getBadges(p.getIdentifier()); + List badges = BadgeManager.getPowerBadges(p.getIdentifier()); int xStart = x + tw + 4; int bi = 0; for(Badge badge : badges) { - RenderSystem.setShaderTexture(0, badge.getSpriteLocation()); + RenderedBadge renderedBadge = new RenderedBadge(badge,xStart + 10 * bi, y - 1); + renderedBadges.add(renderedBadge); + RenderSystem.setShaderTexture(0, badge.spriteId()); drawTexture(matrices, xStart + 10 * bi, y - 1, 0, 0, 9, 9, 9, 9); - RenderedBadge rb = new RenderedBadge(); - rb.badge = badge; - rb.power = p.getIdentifier(); - rb.x = xStart + 10 * bi; - rb.y = y - 1; - renderedBadges.add(rb); bi++; } } @@ -354,10 +318,25 @@ private void renderOriginContent(MatrixStack matrices, int mouseX, int mouseY) { } } - private static class RenderedBadge { - Identifier power; - Badge badge; - int x; - int y; + private class RenderedBadge { + private final Badge badge; + private final int x; + private final int y; + + public RenderedBadge(Badge badge, int x, int y) { + this.badge = badge; + this.x = x; + this.y = y; + } + + public boolean hasTooltip() { + return badge.hasTooltip(); + } + + public List getTooltipComponents(TextRenderer textRenderer, int widthLimit) { + return badge.getTooltipComponents(textRenderer, widthLimit, OriginDisplayScreen.this.time); + } + } + } diff --git a/src/main/java/io/github/apace100/origins/screen/tooltip/CraftingRecipeTooltipComponent.java b/src/main/java/io/github/apace100/origins/screen/tooltip/CraftingRecipeTooltipComponent.java new file mode 100644 index 00000000..0bf717a5 --- /dev/null +++ b/src/main/java/io/github/apace100/origins/screen/tooltip/CraftingRecipeTooltipComponent.java @@ -0,0 +1,58 @@ +package io.github.apace100.origins.screen.tooltip; + +import com.mojang.blaze3d.systems.RenderSystem; +import io.github.apace100.origins.Origins; +import net.minecraft.client.font.TextRenderer; +import net.minecraft.client.gui.DrawableHelper; +import net.minecraft.client.gui.tooltip.TooltipComponent; +import net.minecraft.client.render.item.ItemRenderer; +import net.minecraft.client.util.math.MatrixStack; +import net.minecraft.item.ItemStack; +import net.minecraft.util.Identifier; +import net.minecraft.util.collection.DefaultedList; + +/**A {@link TooltipComponent} used for {@link io.github.apace100.origins.screen.badge.CraftingRecipeBadge} + * Draws a snapshot of a 3x3 crafting recipe in the tooltip*/ +public class CraftingRecipeTooltipComponent implements TooltipComponent { + private final DefaultedList inputs; + private final ItemStack output; + private static final Identifier TEXTURE = Origins.identifier("textures/gui/tooltip/recipe_tooltip.png"); + + public CraftingRecipeTooltipComponent(DefaultedList inputs, ItemStack output) { + this.inputs = inputs; + this.output = output; + } + + @Override + public int getHeight() { + return 68; + } + + @Override + public int getWidth(TextRenderer textRenderer) { + return 130; + } + + @Override + public void drawItems(TextRenderer textRenderer, int x, int y, MatrixStack matrices, ItemRenderer itemRenderer, int z) { + this.drawBackGround(matrices, x, y, z); + for(int column = 0; column < 3; ++column) { + for(int row = 0; row < 3; ++row) { + int index = column + row * 3; + int slotX = x + 8 + column * 18; + int slotY = y + 8 + row * 18; + ItemStack stack = inputs.get(index); + itemRenderer.renderInGuiWithOverrides(stack, slotX, slotY, index); + itemRenderer.renderGuiItemOverlay(textRenderer, stack, slotX, slotY); + } + } + itemRenderer.renderInGuiWithOverrides(output, x + 101, y + 25, 10); + } + + public void drawBackGround(MatrixStack matrices, int x, int y, int z) { + RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); + RenderSystem.setShaderTexture(0, TEXTURE); + DrawableHelper.drawTexture(matrices, x, y, z, 0, 0, 130, 86, 256, 256); + } + +} diff --git a/src/main/java/io/github/apace100/origins/util/Constants.java b/src/main/java/io/github/apace100/origins/util/Constants.java index cee1add3..7dd7d3c1 100644 --- a/src/main/java/io/github/apace100/origins/util/Constants.java +++ b/src/main/java/io/github/apace100/origins/util/Constants.java @@ -2,5 +2,6 @@ public class Constants { - public static final int[] LIGHT_ARMOR_MAX_PROTECTION = new int[] { 1, 4, 5, 2}; + public static final int[] LIGHT_ARMOR_MAX_PROTECTION = new int[] {1, 4, 5, 2}; + } diff --git a/src/main/resources/assets/origins/lang/de_de.json b/src/main/resources/assets/origins/lang/de_de.json index 6f8ab51c..10ceb5d2 100644 --- a/src/main/resources/assets/origins/lang/de_de.json +++ b/src/main/resources/assets/origins/lang/de_de.json @@ -214,5 +214,8 @@ "commands.origin.get.result": "%s has the following %s: %s (%s)", "commands.origin.gui.all": "Opened the selection GUI for %s players.", "commands.origin.gui.layer": "Opened the \"%2$s\" selection GUI for %1$s players.", - "origins.avian_sleep_fail": "You need fresh air to sleep" + "origins.avian_sleep_fail": "You need fresh air to sleep", + "enchantment.origins.water_protection.desc": "Delays damage from hydrophobia.", + "origins.gui.badge.recipe.crafting.shaped": "Crafting recipe (Shaped) provided by the power:", + "origins.gui.badge.recipe.crafting.shapeless": "Crafting recipe (Shapeless) provided by the power:" } \ No newline at end of file diff --git a/src/main/resources/assets/origins/lang/en_us.json b/src/main/resources/assets/origins/lang/en_us.json index 06018a60..28744d9e 100644 --- a/src/main/resources/assets/origins/lang/en_us.json +++ b/src/main/resources/assets/origins/lang/en_us.json @@ -211,6 +211,8 @@ "origins.gui.badge.active": "Active ability, use with %s.", "origins.gui.badge.toggle": "Toggle with %s.", + "origins.gui.badge.recipe.crafting.shaped": "Crafting recipe (Shaped) provided by the power:", + "origins.gui.badge.recipe.crafting.shapeless": "Crafting recipe (Shapeless) provided by the power:", "origins.gui.unbound_key": "§ounbound§r", diff --git a/src/main/resources/assets/origins/lang/es_ar.json b/src/main/resources/assets/origins/lang/es_ar.json index 3821c5b3..1979d5b5 100644 --- a/src/main/resources/assets/origins/lang/es_ar.json +++ b/src/main/resources/assets/origins/lang/es_ar.json @@ -160,5 +160,11 @@ "origins.gui.badge.toggle": "Alternar con %s.", "origins.gui.unbound_key": "§ono asignado§r", "commands.origin.gui.all": "Se le ha abierto la pantalla de selección a %s jugadores.", - "commands.origin.gui.layer": "Se le ha abierto la pantalla de selección de \"%2$s\" a %1$s jugadores." + "commands.origin.gui.layer": "Se le ha abierto la pantalla de selección de \"%2$s\" a %1$s jugadores.", + "text.autoconfig.origins.title": "Origins Configuration", + "text.autoconfig.origins.option.xOffset": "Cooldown Bar Offset X", + "text.autoconfig.origins.option.yOffset": "Cooldown Bar Offset Y", + "text.autoconfig.origins.option.phantomizedOverlayStrength": "Phantomized Overlay Strength", + "origins.gui.badge.recipe.crafting.shaped": "Crafting recipe (Shaped) provided by the power:", + "origins.gui.badge.recipe.crafting.shapeless": "Crafting recipe (Shapeless) provided by the power:" } \ No newline at end of file diff --git a/src/main/resources/assets/origins/lang/es_cl.json b/src/main/resources/assets/origins/lang/es_cl.json index 3821c5b3..1979d5b5 100644 --- a/src/main/resources/assets/origins/lang/es_cl.json +++ b/src/main/resources/assets/origins/lang/es_cl.json @@ -160,5 +160,11 @@ "origins.gui.badge.toggle": "Alternar con %s.", "origins.gui.unbound_key": "§ono asignado§r", "commands.origin.gui.all": "Se le ha abierto la pantalla de selección a %s jugadores.", - "commands.origin.gui.layer": "Se le ha abierto la pantalla de selección de \"%2$s\" a %1$s jugadores." + "commands.origin.gui.layer": "Se le ha abierto la pantalla de selección de \"%2$s\" a %1$s jugadores.", + "text.autoconfig.origins.title": "Origins Configuration", + "text.autoconfig.origins.option.xOffset": "Cooldown Bar Offset X", + "text.autoconfig.origins.option.yOffset": "Cooldown Bar Offset Y", + "text.autoconfig.origins.option.phantomizedOverlayStrength": "Phantomized Overlay Strength", + "origins.gui.badge.recipe.crafting.shaped": "Crafting recipe (Shaped) provided by the power:", + "origins.gui.badge.recipe.crafting.shapeless": "Crafting recipe (Shapeless) provided by the power:" } \ No newline at end of file diff --git a/src/main/resources/assets/origins/lang/es_ec.json b/src/main/resources/assets/origins/lang/es_ec.json index 3821c5b3..1979d5b5 100644 --- a/src/main/resources/assets/origins/lang/es_ec.json +++ b/src/main/resources/assets/origins/lang/es_ec.json @@ -160,5 +160,11 @@ "origins.gui.badge.toggle": "Alternar con %s.", "origins.gui.unbound_key": "§ono asignado§r", "commands.origin.gui.all": "Se le ha abierto la pantalla de selección a %s jugadores.", - "commands.origin.gui.layer": "Se le ha abierto la pantalla de selección de \"%2$s\" a %1$s jugadores." + "commands.origin.gui.layer": "Se le ha abierto la pantalla de selección de \"%2$s\" a %1$s jugadores.", + "text.autoconfig.origins.title": "Origins Configuration", + "text.autoconfig.origins.option.xOffset": "Cooldown Bar Offset X", + "text.autoconfig.origins.option.yOffset": "Cooldown Bar Offset Y", + "text.autoconfig.origins.option.phantomizedOverlayStrength": "Phantomized Overlay Strength", + "origins.gui.badge.recipe.crafting.shaped": "Crafting recipe (Shaped) provided by the power:", + "origins.gui.badge.recipe.crafting.shapeless": "Crafting recipe (Shapeless) provided by the power:" } \ No newline at end of file diff --git a/src/main/resources/assets/origins/lang/es_es.json b/src/main/resources/assets/origins/lang/es_es.json index 3821c5b3..1979d5b5 100644 --- a/src/main/resources/assets/origins/lang/es_es.json +++ b/src/main/resources/assets/origins/lang/es_es.json @@ -160,5 +160,11 @@ "origins.gui.badge.toggle": "Alternar con %s.", "origins.gui.unbound_key": "§ono asignado§r", "commands.origin.gui.all": "Se le ha abierto la pantalla de selección a %s jugadores.", - "commands.origin.gui.layer": "Se le ha abierto la pantalla de selección de \"%2$s\" a %1$s jugadores." + "commands.origin.gui.layer": "Se le ha abierto la pantalla de selección de \"%2$s\" a %1$s jugadores.", + "text.autoconfig.origins.title": "Origins Configuration", + "text.autoconfig.origins.option.xOffset": "Cooldown Bar Offset X", + "text.autoconfig.origins.option.yOffset": "Cooldown Bar Offset Y", + "text.autoconfig.origins.option.phantomizedOverlayStrength": "Phantomized Overlay Strength", + "origins.gui.badge.recipe.crafting.shaped": "Crafting recipe (Shaped) provided by the power:", + "origins.gui.badge.recipe.crafting.shapeless": "Crafting recipe (Shapeless) provided by the power:" } \ No newline at end of file diff --git a/src/main/resources/assets/origins/lang/es_mx.json b/src/main/resources/assets/origins/lang/es_mx.json index 3821c5b3..1979d5b5 100644 --- a/src/main/resources/assets/origins/lang/es_mx.json +++ b/src/main/resources/assets/origins/lang/es_mx.json @@ -160,5 +160,11 @@ "origins.gui.badge.toggle": "Alternar con %s.", "origins.gui.unbound_key": "§ono asignado§r", "commands.origin.gui.all": "Se le ha abierto la pantalla de selección a %s jugadores.", - "commands.origin.gui.layer": "Se le ha abierto la pantalla de selección de \"%2$s\" a %1$s jugadores." + "commands.origin.gui.layer": "Se le ha abierto la pantalla de selección de \"%2$s\" a %1$s jugadores.", + "text.autoconfig.origins.title": "Origins Configuration", + "text.autoconfig.origins.option.xOffset": "Cooldown Bar Offset X", + "text.autoconfig.origins.option.yOffset": "Cooldown Bar Offset Y", + "text.autoconfig.origins.option.phantomizedOverlayStrength": "Phantomized Overlay Strength", + "origins.gui.badge.recipe.crafting.shaped": "Crafting recipe (Shaped) provided by the power:", + "origins.gui.badge.recipe.crafting.shapeless": "Crafting recipe (Shapeless) provided by the power:" } \ No newline at end of file diff --git a/src/main/resources/assets/origins/lang/es_uy.json b/src/main/resources/assets/origins/lang/es_uy.json index 3821c5b3..1979d5b5 100644 --- a/src/main/resources/assets/origins/lang/es_uy.json +++ b/src/main/resources/assets/origins/lang/es_uy.json @@ -160,5 +160,11 @@ "origins.gui.badge.toggle": "Alternar con %s.", "origins.gui.unbound_key": "§ono asignado§r", "commands.origin.gui.all": "Se le ha abierto la pantalla de selección a %s jugadores.", - "commands.origin.gui.layer": "Se le ha abierto la pantalla de selección de \"%2$s\" a %1$s jugadores." + "commands.origin.gui.layer": "Se le ha abierto la pantalla de selección de \"%2$s\" a %1$s jugadores.", + "text.autoconfig.origins.title": "Origins Configuration", + "text.autoconfig.origins.option.xOffset": "Cooldown Bar Offset X", + "text.autoconfig.origins.option.yOffset": "Cooldown Bar Offset Y", + "text.autoconfig.origins.option.phantomizedOverlayStrength": "Phantomized Overlay Strength", + "origins.gui.badge.recipe.crafting.shaped": "Crafting recipe (Shaped) provided by the power:", + "origins.gui.badge.recipe.crafting.shapeless": "Crafting recipe (Shapeless) provided by the power:" } \ No newline at end of file diff --git a/src/main/resources/assets/origins/lang/es_ve.json b/src/main/resources/assets/origins/lang/es_ve.json index 3821c5b3..1979d5b5 100644 --- a/src/main/resources/assets/origins/lang/es_ve.json +++ b/src/main/resources/assets/origins/lang/es_ve.json @@ -160,5 +160,11 @@ "origins.gui.badge.toggle": "Alternar con %s.", "origins.gui.unbound_key": "§ono asignado§r", "commands.origin.gui.all": "Se le ha abierto la pantalla de selección a %s jugadores.", - "commands.origin.gui.layer": "Se le ha abierto la pantalla de selección de \"%2$s\" a %1$s jugadores." + "commands.origin.gui.layer": "Se le ha abierto la pantalla de selección de \"%2$s\" a %1$s jugadores.", + "text.autoconfig.origins.title": "Origins Configuration", + "text.autoconfig.origins.option.xOffset": "Cooldown Bar Offset X", + "text.autoconfig.origins.option.yOffset": "Cooldown Bar Offset Y", + "text.autoconfig.origins.option.phantomizedOverlayStrength": "Phantomized Overlay Strength", + "origins.gui.badge.recipe.crafting.shaped": "Crafting recipe (Shaped) provided by the power:", + "origins.gui.badge.recipe.crafting.shapeless": "Crafting recipe (Shapeless) provided by the power:" } \ No newline at end of file diff --git a/src/main/resources/assets/origins/lang/fr_fr.json b/src/main/resources/assets/origins/lang/fr_fr.json index a68bf6aa..5421ff17 100644 --- a/src/main/resources/assets/origins/lang/fr_fr.json +++ b/src/main/resources/assets/origins/lang/fr_fr.json @@ -224,5 +224,8 @@ "commands.origin.get.result": "%s has the following %s: %s (%s)", "commands.origin.gui.all": "Opened the selection GUI for %s players.", "commands.origin.gui.layer": "Opened the \"%2$s\" selection GUI for %1$s players.", - "origins.avian_sleep_fail": "You need fresh air to sleep" + "origins.avian_sleep_fail": "You need fresh air to sleep", + "enchantment.origins.water_protection.desc": "Delays damage from hydrophobia.", + "origins.gui.badge.recipe.crafting.shaped": "Crafting recipe (Shaped) provided by the power:", + "origins.gui.badge.recipe.crafting.shapeless": "Crafting recipe (Shapeless) provided by the power:" } diff --git a/src/main/resources/assets/origins/lang/he_il.json b/src/main/resources/assets/origins/lang/he_il.json index a6a55e8b..007b33ae 100644 --- a/src/main/resources/assets/origins/lang/he_il.json +++ b/src/main/resources/assets/origins/lang/he_il.json @@ -228,5 +228,8 @@ "origins.gui.unbound_key": "§ounbound§r", "commands.origin.get.result": "%s has the following %s: %s (%s)", "commands.origin.gui.all": "Opened the selection GUI for %s players.", - "commands.origin.gui.layer": "Opened the \"%2$s\" selection GUI for %1$s players." + "commands.origin.gui.layer": "Opened the \"%2$s\" selection GUI for %1$s players.", + "enchantment.origins.water_protection.desc": "Delays damage from hydrophobia.", + "origins.gui.badge.recipe.crafting.shaped": "Crafting recipe (Shaped) provided by the power:", + "origins.gui.badge.recipe.crafting.shapeless": "Crafting recipe (Shapeless) provided by the power:" } \ No newline at end of file diff --git a/src/main/resources/assets/origins/lang/id_id.json b/src/main/resources/assets/origins/lang/id_id.json index ce945a6d..df4e87eb 100644 --- a/src/main/resources/assets/origins/lang/id_id.json +++ b/src/main/resources/assets/origins/lang/id_id.json @@ -229,5 +229,8 @@ "origins.gui.unbound_key": "§ounbound§r", "commands.origin.get.result": "%s has the following %s: %s (%s)", "commands.origin.gui.all": "Opened the selection GUI for %s players.", - "commands.origin.gui.layer": "Opened the \"%2$s\" selection GUI for %1$s players." + "commands.origin.gui.layer": "Opened the \"%2$s\" selection GUI for %1$s players.", + "enchantment.origins.water_protection.desc": "Delays damage from hydrophobia.", + "origins.gui.badge.recipe.crafting.shaped": "Crafting recipe (Shaped) provided by the power:", + "origins.gui.badge.recipe.crafting.shapeless": "Crafting recipe (Shapeless) provided by the power:" } \ No newline at end of file diff --git a/src/main/resources/assets/origins/lang/it_it.json b/src/main/resources/assets/origins/lang/it_it.json index f070e68c..c8904d85 100644 --- a/src/main/resources/assets/origins/lang/it_it.json +++ b/src/main/resources/assets/origins/lang/it_it.json @@ -214,5 +214,8 @@ "commands.origin.get.result": "%s has the following %s: %s (%s)", "commands.origin.gui.all": "Opened the selection GUI for %s players.", "commands.origin.gui.layer": "Opened the \"%2$s\" selection GUI for %1$s players.", - "origins.avian_sleep_fail": "You need fresh air to sleep" + "origins.avian_sleep_fail": "You need fresh air to sleep", + "enchantment.origins.water_protection.desc": "Delays damage from hydrophobia.", + "origins.gui.badge.recipe.crafting.shaped": "Crafting recipe (Shaped) provided by the power:", + "origins.gui.badge.recipe.crafting.shapeless": "Crafting recipe (Shapeless) provided by the power:" } \ No newline at end of file diff --git a/src/main/resources/assets/origins/lang/ja_jp.json b/src/main/resources/assets/origins/lang/ja_jp.json index 04a90b61..6d931288 100644 --- a/src/main/resources/assets/origins/lang/ja_jp.json +++ b/src/main/resources/assets/origins/lang/ja_jp.json @@ -229,5 +229,8 @@ "origins.gui.badge.toggle": "Toggle with %s.", "origins.gui.unbound_key": "§ounbound§r", "commands.origin.gui.all": "Opened the selection GUI for %s players.", - "commands.origin.gui.layer": "Opened the \"%2$s\" selection GUI for %1$s players." + "commands.origin.gui.layer": "Opened the \"%2$s\" selection GUI for %1$s players.", + "enchantment.origins.water_protection.desc": "Delays damage from hydrophobia.", + "origins.gui.badge.recipe.crafting.shaped": "Crafting recipe (Shaped) provided by the power:", + "origins.gui.badge.recipe.crafting.shapeless": "Crafting recipe (Shapeless) provided by the power:" } \ No newline at end of file diff --git a/src/main/resources/assets/origins/lang/ko_kr.json b/src/main/resources/assets/origins/lang/ko_kr.json index 8014706e..7894196a 100644 --- a/src/main/resources/assets/origins/lang/ko_kr.json +++ b/src/main/resources/assets/origins/lang/ko_kr.json @@ -229,5 +229,8 @@ "origins.gui.unbound_key": "§ounbound§r", "commands.origin.get.result": "%s has the following %s: %s (%s)", "commands.origin.gui.all": "Opened the selection GUI for %s players.", - "commands.origin.gui.layer": "Opened the \"%2$s\" selection GUI for %1$s players." + "commands.origin.gui.layer": "Opened the \"%2$s\" selection GUI for %1$s players.", + "enchantment.origins.water_protection.desc": "Delays damage from hydrophobia.", + "origins.gui.badge.recipe.crafting.shaped": "Crafting recipe (Shaped) provided by the power:", + "origins.gui.badge.recipe.crafting.shapeless": "Crafting recipe (Shapeless) provided by the power:" } \ No newline at end of file diff --git a/src/main/resources/assets/origins/lang/nl_nl.json b/src/main/resources/assets/origins/lang/nl_nl.json index 7ec90d8c..ce0f28ad 100644 --- a/src/main/resources/assets/origins/lang/nl_nl.json +++ b/src/main/resources/assets/origins/lang/nl_nl.json @@ -225,5 +225,8 @@ "commands.origin.get.result": "%s has the following %s: %s (%s)", "commands.origin.gui.all": "Opened the selection GUI for %s players.", "commands.origin.gui.layer": "Opened the \"%2$s\" selection GUI for %1$s players.", - "origins.avian_sleep_fail": "You need fresh air to sleep" + "origins.avian_sleep_fail": "You need fresh air to sleep", + "enchantment.origins.water_protection.desc": "Delays damage from hydrophobia.", + "origins.gui.badge.recipe.crafting.shaped": "Crafting recipe (Shaped) provided by the power:", + "origins.gui.badge.recipe.crafting.shapeless": "Crafting recipe (Shapeless) provided by the power:" } diff --git a/src/main/resources/assets/origins/lang/pl_pl.json b/src/main/resources/assets/origins/lang/pl_pl.json index 667f2deb..fed4232e 100644 --- a/src/main/resources/assets/origins/lang/pl_pl.json +++ b/src/main/resources/assets/origins/lang/pl_pl.json @@ -229,5 +229,8 @@ "origins.gui.unbound_key": "§ounbound§r", "commands.origin.get.result": "%s has the following %s: %s (%s)", "commands.origin.gui.all": "Opened the selection GUI for %s players.", - "commands.origin.gui.layer": "Opened the \"%2$s\" selection GUI for %1$s players." + "commands.origin.gui.layer": "Opened the \"%2$s\" selection GUI for %1$s players.", + "enchantment.origins.water_protection.desc": "Delays damage from hydrophobia.", + "origins.gui.badge.recipe.crafting.shaped": "Crafting recipe (Shaped) provided by the power:", + "origins.gui.badge.recipe.crafting.shapeless": "Crafting recipe (Shapeless) provided by the power:" } diff --git a/src/main/resources/assets/origins/lang/pt_br.json b/src/main/resources/assets/origins/lang/pt_br.json index 7f347ddd..5298fc74 100644 --- a/src/main/resources/assets/origins/lang/pt_br.json +++ b/src/main/resources/assets/origins/lang/pt_br.json @@ -230,5 +230,8 @@ "layer.origins.origin.name": "Origin", "commands.origin.get.result": "%s has the following %s: %s (%s)", "commands.origin.gui.all": "Opened the selection GUI for %s players.", - "commands.origin.gui.layer": "Opened the \"%2$s\" selection GUI for %1$s players." + "commands.origin.gui.layer": "Opened the \"%2$s\" selection GUI for %1$s players.", + "enchantment.origins.water_protection.desc": "Delays damage from hydrophobia.", + "origins.gui.badge.recipe.crafting.shaped": "Crafting recipe (Shaped) provided by the power:", + "origins.gui.badge.recipe.crafting.shapeless": "Crafting recipe (Shapeless) provided by the power:" } diff --git a/src/main/resources/assets/origins/lang/ro_ro.json b/src/main/resources/assets/origins/lang/ro_ro.json index 6188555c..764a0627 100644 --- a/src/main/resources/assets/origins/lang/ro_ro.json +++ b/src/main/resources/assets/origins/lang/ro_ro.json @@ -229,5 +229,8 @@ "origins.gui.unbound_key": "§ounbound§r", "commands.origin.get.result": "%s has the following %s: %s (%s)", "commands.origin.gui.all": "Opened the selection GUI for %s players.", - "commands.origin.gui.layer": "Opened the \"%2$s\" selection GUI for %1$s players." + "commands.origin.gui.layer": "Opened the \"%2$s\" selection GUI for %1$s players.", + "enchantment.origins.water_protection.desc": "Delays damage from hydrophobia.", + "origins.gui.badge.recipe.crafting.shaped": "Crafting recipe (Shaped) provided by the power:", + "origins.gui.badge.recipe.crafting.shapeless": "Crafting recipe (Shapeless) provided by the power:" } \ No newline at end of file diff --git a/src/main/resources/assets/origins/lang/ru_ru.json b/src/main/resources/assets/origins/lang/ru_ru.json index b16532f7..c8ad2988 100644 --- a/src/main/resources/assets/origins/lang/ru_ru.json +++ b/src/main/resources/assets/origins/lang/ru_ru.json @@ -229,5 +229,8 @@ "origins.gui.unbound_key": "§ounbound§r", "commands.origin.get.result": "%s has the following %s: %s (%s)", "commands.origin.gui.all": "Opened the selection GUI for %s players.", - "commands.origin.gui.layer": "Opened the \"%2$s\" selection GUI for %1$s players." + "commands.origin.gui.layer": "Opened the \"%2$s\" selection GUI for %1$s players.", + "enchantment.origins.water_protection.desc": "Delays damage from hydrophobia.", + "origins.gui.badge.recipe.crafting.shaped": "Crafting recipe (Shaped) provided by the power:", + "origins.gui.badge.recipe.crafting.shapeless": "Crafting recipe (Shapeless) provided by the power:" } diff --git a/src/main/resources/assets/origins/lang/tr_tr.json b/src/main/resources/assets/origins/lang/tr_tr.json index a97ff628..0b550d07 100644 --- a/src/main/resources/assets/origins/lang/tr_tr.json +++ b/src/main/resources/assets/origins/lang/tr_tr.json @@ -230,7 +230,9 @@ "power.origins.velvet_paws.name": "Kadife Patiler", "power.origins.velvet_paws.description": "Adımlarınız yakındaki diğer yaşam formları tarafından algılanacak titreşimler oluşturmaz.", "item.origins.orb_of_origin.layer_generic": "Yeni bir %s şeçmenizi sağlar.", - "item.origins.orb_of_origin.layer_specific": "%1$s'nızı \"%2$s\'ye ayarlar".", + "item.origins.orb_of_origin.layer_specific": "%1$s'nızı \"%2$s\"ye ayarlar.", "commands.origin.gui.all": "%s oyuncular için şeçim GUI'si açıldı.", - "commands.origin.gui.layer": "%1$s oyuncuları için \"%2$s\" şeçim GUI'si açıldı." + "commands.origin.gui.layer": "%1$s oyuncuları için \"%2$s\" şeçim GUI'si açıldı.", + "origins.gui.badge.recipe.crafting.shaped": "Crafting recipe (Shaped) provided by the power:", + "origins.gui.badge.recipe.crafting.shapeless": "Crafting recipe (Shapeless) provided by the power:" } diff --git a/src/main/resources/assets/origins/lang/zh_cn.json b/src/main/resources/assets/origins/lang/zh_cn.json index 8bf6f0ce..9f6d3bbe 100644 --- a/src/main/resources/assets/origins/lang/zh_cn.json +++ b/src/main/resources/assets/origins/lang/zh_cn.json @@ -210,6 +210,8 @@ "origins.gui.badge.active": "主动能力,按下%s键使用", "origins.gui.badge.toggle": "使用%s键开关", + "origins.gui.badge.recipe.crafting.shaped": "能力提供的有序合成配方:", + "origins.gui.badge.recipe.crafting.shapeless": "能力提供的无序合成配方:", "origins.gui.unbound_key": "§o未绑定§r", @@ -228,11 +230,12 @@ "death.attack.genericDamageOverTime.player":"%1$s在与%2$s战斗时被持续性伤害效果杀死了", "commands.origin.origin_not_found":"未知起源:%s", - "commands.origin.set.success.single":"已将%s的%s层起源设置为:%s", - "commands.origin.set.success.multiple":"已将%s个目标的%s层起源设置为:%s", + "commands.origin.set.success.single":"已将%s的%s设置为:%s", + "commands.origin.set.success.multiple":"已将%s个目标的%s设置为:%s", "commands.origin.get.result": "%s拥有以下%s:%s(%s)", "commands.origin.gui.all": "为%s个玩家打开了选择GUI", "commands.origin.gui.layer": "为%1$s个玩家打开了 %2$s 的选择GUI", - "origins.avian_sleep_fail":"你需要新鲜空气才能正常入睡" + "origins.avian_sleep_fail":"你需要新鲜空气才能正常入睡", + "enchantment.origins.water_protection.desc": "Delays damage from hydrophobia." } diff --git a/src/main/resources/assets/origins/textures/gui/badge/recipe.png b/src/main/resources/assets/origins/textures/gui/badge/recipe.png new file mode 100644 index 0000000000000000000000000000000000000000..639473ba4cd2fe16ea815b49bdfbddfb1df40878 GIT binary patch literal 156 zcmeAS@N?(olHy`uVBq!ia0vp^oFL4>1|%O$WD@{VjKx9jP7LeL$-D$|!aQ9ZLnNm5 zPPoW3fo+G*x5JytQd4u^GNpa6ey;D;GVxKlu``cq z-R$O^Q}@&l?0c8rP&w~xz1h+!9D*KiwR!5JE}OVU{9GFLNRi?C>(c$3AFkcCuDhdS z-+SdXEJ441eda#Qzq4lVKfwpVoD3@8{=S(#{dDR_ZWCYO!v-Oxb3Xsv^TXl;=R7ur zM`i}zTXLmAqB7U59vl;65E5qa@L^CeWNbLXf|C<>kLSp@YdcYZ*U*(RcBh8BIBO; zupovx;-W=g^?as3!i*6!ISN#mHZTf4&|pbWRyrWaaiGnm;nq);2hCgCuhp}!m??Td zI)XDmo3Vmfn;|Qe`@@6!_OJQ%PkHT4H#6Os@Njt<(+0uA=YjgzcDd!-N^?OpZzG7#))AxMCQuo89PU2zgLrcYE3f?r0*s4h)pf zE(#uNT#neBFLr6MzBK9OE=pNb2jHY#`u|V9wN~=dOr5vv