forked from apace100/origins-fabric
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Reworked the Badge system, added badge for RecipePower (apace100#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
- Loading branch information
1 parent
7c77c59
commit 36d44b3
Showing
45 changed files
with
704 additions
and
257 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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<Badge> { | ||
|
||
Identifier spriteId(); | ||
|
||
boolean hasTooltip(); | ||
|
||
@Environment(EnvType.CLIENT) | ||
List<TooltipComponent> getTooltipComponents(TextRenderer textRenderer, int widthLimit, float time); | ||
|
||
SerializableData.Instance toData(SerializableData.Instance instance); | ||
|
||
BadgeFactory getBadgeFactory(); | ||
|
||
@Override | ||
default DataObjectFactory<Badge> getFactory() { | ||
return this.getBadgeFactory(); | ||
} | ||
|
||
default void writeBuf(PacketByteBuf buf) { | ||
DataObjectFactory<Badge> factory = this.getFactory(); | ||
buf.writeIdentifier(this.getBadgeFactory().id()); | ||
factory.getData().write(buf, factory.toData(this)); | ||
} | ||
|
||
} |
28 changes: 28 additions & 0 deletions
28
src/main/java/io/github/apace100/origins/badge/BadgeFactories.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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); | ||
|
||
} |
26 changes: 26 additions & 0 deletions
26
src/main/java/io/github/apace100/origins/badge/BadgeFactory.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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<SerializableData.Instance, Badge> factory) implements DataObjectFactory<Badge> { | ||
|
||
@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()); | ||
} | ||
|
||
} |
156 changes: 156 additions & 0 deletions
156
src/main/java/io/github/apace100/origins/badge/BadgeManager.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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<Badge> 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<Identifier, List<Badge>> BADGES = new HashMap<>(); | ||
private static final Map<Identifier, List<Identifier>> 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<Badge> badgeList = BADGES.computeIfAbsent(powerId, id -> new LinkedList<>()); | ||
badgeList.add(badge); | ||
} | ||
|
||
public static List<Badge> 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<CraftingInventory> 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(); | ||
} | ||
|
||
} |
84 changes: 84 additions & 0 deletions
84
src/main/java/io/github/apace100/origins/badge/CraftingRecipeBadge.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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<CraftingInventory> 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<ItemStack> peekInputs(float time) { | ||
int seed = MathHelper.floor(time / 30); | ||
DefaultedList<ItemStack> inputs = DefaultedList.ofSize(9, ItemStack.EMPTY); | ||
List<Ingredient> 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<TooltipComponent> getTooltipComponents(TextRenderer textRenderer, int widthLimit, float time) { | ||
List<TooltipComponent> 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; | ||
} | ||
|
||
} |
Oops, something went wrong.