mirror of
https://github.com/Sollace/Unicopia.git
synced 2025-02-07 22:16:44 +01:00
Implement crafting using traits, and trait discovery, AND show known traits in item tooltips
This commit is contained in:
parent
1768420b66
commit
8aea7d326f
11 changed files with 443 additions and 32 deletions
|
@ -0,0 +1,26 @@
|
|||
package com.minelittlepony.unicopia.ability.magic.spell.crafting;
|
||||
|
||||
import com.minelittlepony.unicopia.container.SpellbookScreenHandler.SpellbookInventory;
|
||||
import com.minelittlepony.unicopia.item.UItems;
|
||||
import com.minelittlepony.unicopia.item.URecipes;
|
||||
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.recipe.Recipe;
|
||||
import net.minecraft.recipe.RecipeType;
|
||||
|
||||
public interface SpellbookRecipe extends Recipe<SpellbookInventory> {
|
||||
@Override
|
||||
default RecipeType<?> getType() {
|
||||
return URecipes.SPELLBOOK;
|
||||
}
|
||||
|
||||
@Override
|
||||
default String getGroup() {
|
||||
return "unicopia:spellbook";
|
||||
}
|
||||
|
||||
@Override
|
||||
default ItemStack createIcon() {
|
||||
return new ItemStack(UItems.SPELLBOOK);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,105 @@
|
|||
package com.minelittlepony.unicopia.ability.magic.spell.crafting;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
import com.minelittlepony.unicopia.ability.magic.spell.effect.SpellType;
|
||||
import com.minelittlepony.unicopia.ability.magic.spell.trait.SpellTraits;
|
||||
import com.minelittlepony.unicopia.container.SpellbookScreenHandler.SpellbookInventory;
|
||||
import com.minelittlepony.unicopia.item.GemstoneItem;
|
||||
import com.minelittlepony.unicopia.item.URecipes;
|
||||
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.network.PacketByteBuf;
|
||||
import net.minecraft.recipe.Ingredient;
|
||||
import net.minecraft.recipe.RecipeSerializer;
|
||||
import net.minecraft.recipe.ShapedRecipe;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.JsonHelper;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
public class TraitRequirementRecipe implements SpellbookRecipe {
|
||||
|
||||
private final Identifier id;
|
||||
private final Ingredient requirement;
|
||||
private final SpellTraits requiredTraits;
|
||||
private final ItemStack output;
|
||||
|
||||
private TraitRequirementRecipe(Identifier id, Ingredient requirement, SpellTraits requiredTraits, ItemStack output) {
|
||||
this.id = id;
|
||||
this.requirement = requirement;
|
||||
this.requiredTraits = requiredTraits;
|
||||
this.output = output;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matches(SpellbookInventory inventory, World world) {
|
||||
return requirement.test(inventory.getItemToModify())
|
||||
&& SpellTraits.of(inventory).includes(requiredTraits);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack craft(SpellbookInventory inventory) {
|
||||
return SpellTraits.union(
|
||||
SpellTraits.of(inventory.getItemToModify()),
|
||||
SpellTraits.of(inventory),
|
||||
SpellTraits.of(output)
|
||||
).applyTo(output);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean fits(int width, int height) {
|
||||
return (width * height) > 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack getOutput() {
|
||||
return output;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Identifier getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RecipeSerializer<?> getSerializer() {
|
||||
return URecipes.TRAIT_REQUIREMENT;
|
||||
}
|
||||
|
||||
public static ItemStack outputFromJson(JsonObject json) {
|
||||
ItemStack stack = ShapedRecipe.outputFromJson(json);
|
||||
SpellTraits.fromJson(JsonHelper.getObject(json, "traits", new JsonObject()))
|
||||
.map(traits -> traits.applyTo(stack)).orElse(stack);
|
||||
|
||||
SpellType<?> spell = SpellType.getKey(Identifier.tryParse(JsonHelper.getString(json, "spell", "")));
|
||||
if (spell != SpellType.EMPTY_KEY) {
|
||||
return GemstoneItem.enchanted(stack, spell);
|
||||
}
|
||||
return stack;
|
||||
}
|
||||
|
||||
public static class Serializer implements RecipeSerializer<TraitRequirementRecipe> {
|
||||
@Override
|
||||
public TraitRequirementRecipe read(Identifier id, JsonObject json) {
|
||||
return new TraitRequirementRecipe(id,
|
||||
Ingredient.fromJson(JsonHelper.getObject(json, "material")),
|
||||
SpellTraits.fromJson(JsonHelper.getObject(json, "traits")).get(),
|
||||
outputFromJson(JsonHelper.getObject(json, "result")));
|
||||
}
|
||||
|
||||
@Override
|
||||
public TraitRequirementRecipe read(Identifier id, PacketByteBuf buf) {
|
||||
return new TraitRequirementRecipe(id,
|
||||
Ingredient.fromPacket(buf),
|
||||
SpellTraits.fromPacket(buf).get(),
|
||||
buf.readItemStack()
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(PacketByteBuf buf, TraitRequirementRecipe recipe) {
|
||||
recipe.requirement.write(buf);
|
||||
recipe.requiredTraits.write(buf);
|
||||
buf.writeItemStack(recipe.output);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -90,7 +90,7 @@ public abstract class AbstractSpell implements Spell {
|
|||
}
|
||||
isDead = compound.getBoolean("dead");
|
||||
if (compound.contains("traits")) {
|
||||
traits = SpellTraits.readNbt(compound.getCompound("traits")).orElse(SpellTraits.EMPTY);
|
||||
traits = SpellTraits.fromNbt(compound.getCompound("traits")).orElse(SpellTraits.EMPTY);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,10 @@
|
|||
package com.minelittlepony.unicopia.ability.magic.spell.trait;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.EnumMap;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
|
@ -9,11 +12,18 @@ import java.util.Set;
|
|||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
import com.minelittlepony.unicopia.util.InventoryUtil;
|
||||
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.inventory.Inventory;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.nbt.NbtCompound;
|
||||
import net.minecraft.nbt.NbtElement;
|
||||
import net.minecraft.network.PacketByteBuf;
|
||||
import net.minecraft.text.LiteralText;
|
||||
import net.minecraft.text.Text;
|
||||
import net.minecraft.util.registry.Registry;
|
||||
|
||||
public final class SpellTraits {
|
||||
|
@ -29,6 +39,12 @@ public final class SpellTraits {
|
|||
return traits.isEmpty();
|
||||
}
|
||||
|
||||
public boolean includes(SpellTraits other) {
|
||||
return other.entries().stream().allMatch(pair -> {
|
||||
return getAmount(pair.getKey()) >= pair.getValue();
|
||||
});
|
||||
}
|
||||
|
||||
public Set<Map.Entry<Trait, Float>> entries() {
|
||||
return traits.entrySet();
|
||||
}
|
||||
|
@ -37,14 +53,46 @@ public final class SpellTraits {
|
|||
return traits.getOrDefault(trait, 0F);
|
||||
}
|
||||
|
||||
public void appendTooltip(List<Text> tooltip) {
|
||||
if (isEmpty()) {
|
||||
return;
|
||||
}
|
||||
tooltip.add(new LiteralText("Traits:"));
|
||||
traits.forEach((trait, amount) -> {
|
||||
tooltip.add(new LiteralText(trait.name().toLowerCase() + ": " + amount));
|
||||
});
|
||||
}
|
||||
|
||||
public NbtCompound toNbt() {
|
||||
NbtCompound nbt = new NbtCompound();
|
||||
traits.forEach((key, value) -> nbt.putFloat(key.name(), value));
|
||||
return nbt;
|
||||
}
|
||||
|
||||
public static Optional<SpellTraits> of(Collection<ItemStack> stacks) {
|
||||
return fromEntries(stacks.stream().flatMap(a -> of(a).entries().stream()));
|
||||
public void write(PacketByteBuf buf) {
|
||||
buf.writeInt(traits.size());
|
||||
traits.forEach((trait, value) -> {
|
||||
buf.writeIdentifier(trait.getId());
|
||||
buf.writeFloat(value);
|
||||
});
|
||||
}
|
||||
|
||||
public static SpellTraits union(SpellTraits...many) {
|
||||
Map<Trait, Float> traits = new HashMap<>();
|
||||
for (SpellTraits i : many) {
|
||||
combine(traits, i.traits);
|
||||
}
|
||||
return traits.isEmpty() ? EMPTY : new SpellTraits(traits);
|
||||
}
|
||||
|
||||
public static SpellTraits of(Inventory inventory) {
|
||||
List<ItemStack> stacks = new ArrayList<>();
|
||||
InventoryUtil.iterate(inventory).forEach(stacks::add);
|
||||
return of(stacks);
|
||||
}
|
||||
|
||||
public static SpellTraits of(Collection<ItemStack> stacks) {
|
||||
return fromEntries(stacks.stream().flatMap(a -> of(a).entries().stream())).orElse(SpellTraits.EMPTY);
|
||||
}
|
||||
|
||||
public static SpellTraits of(ItemStack stack) {
|
||||
|
@ -52,7 +100,7 @@ public final class SpellTraits {
|
|||
}
|
||||
|
||||
public static SpellTraits of(Item item) {
|
||||
return TraitLoader.INSTANCE.values.getOrDefault(Registry.ITEM.getId(item), null);
|
||||
return TraitLoader.INSTANCE.values.getOrDefault(Registry.ITEM.getId(item), EMPTY);
|
||||
}
|
||||
|
||||
public static SpellTraits of(Block block) {
|
||||
|
@ -63,13 +111,43 @@ public final class SpellTraits {
|
|||
if (!(stack.hasTag() && stack.getTag().contains("spell_traits", NbtElement.COMPOUND_TYPE))) {
|
||||
return Optional.empty();
|
||||
}
|
||||
return readNbt(stack.getTag().getCompound("spell_traits"));
|
||||
return fromNbt(stack.getTag().getCompound("spell_traits"));
|
||||
}
|
||||
|
||||
public static Optional<SpellTraits> readNbt(NbtCompound traits) {
|
||||
public ItemStack applyTo(ItemStack stack) {
|
||||
stack = stack.copy();
|
||||
stack.getOrCreateTag().put("spell_traits", toNbt());
|
||||
return stack;
|
||||
}
|
||||
|
||||
public static Optional<SpellTraits> fromNbt(NbtCompound traits) {
|
||||
return fromEntries(streamFromNbt(traits));
|
||||
}
|
||||
|
||||
public static Optional<SpellTraits> fromJson(JsonObject traits) {
|
||||
return fromEntries(streamFromJson(traits));
|
||||
}
|
||||
|
||||
public static Optional<SpellTraits> fromPacket(PacketByteBuf buf) {
|
||||
Map<Trait, Float> entries = new HashMap<>();
|
||||
int count = buf.readInt();
|
||||
if (count <= 0) {
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
for (int i = 0; i < count; i++) {
|
||||
Trait trait = Trait.REGISTRY.getOrDefault(buf.readIdentifier(), null);
|
||||
float value = buf.readFloat();
|
||||
if (trait != null) {
|
||||
entries.compute(trait, (k, v) -> v == null ? value : (v + value));
|
||||
}
|
||||
}
|
||||
if (entries.isEmpty()) {
|
||||
return Optional.empty();
|
||||
}
|
||||
return Optional.of(new SpellTraits(entries));
|
||||
}
|
||||
|
||||
public static Stream<Map.Entry<Trait, Float>> streamFromNbt(NbtCompound traits) {
|
||||
return traits.getKeys().stream().map(key -> {
|
||||
Trait trait = Trait.REGISTRY.get(key.toUpperCase());
|
||||
|
@ -80,6 +158,16 @@ public final class SpellTraits {
|
|||
});
|
||||
}
|
||||
|
||||
public static Stream<Map.Entry<Trait, Float>> streamFromJson(JsonObject traits) {
|
||||
return traits.entrySet().stream().map(entry -> {
|
||||
Trait trait = Trait.REGISTRY.get(entry.getKey().toUpperCase());
|
||||
if (trait == null && !entry.getValue().isJsonPrimitive() && !entry.getValue().getAsJsonPrimitive().isNumber()) {
|
||||
return null;
|
||||
}
|
||||
return Map.entry(trait, entry.getValue().getAsJsonPrimitive().getAsFloat());
|
||||
});
|
||||
}
|
||||
|
||||
public static Optional<SpellTraits> fromEntries(Stream<Map.Entry<Trait, Float>> entries) {
|
||||
var result = collect(entries);
|
||||
|
||||
|
@ -89,6 +177,12 @@ public final class SpellTraits {
|
|||
return Optional.of(new SpellTraits(result));
|
||||
}
|
||||
|
||||
static void combine(Map<Trait, Float> to, Map<Trait, Float> from) {
|
||||
from.forEach((trait, value) -> {
|
||||
to.compute(trait, (k, v) -> v == null ? value : (v + value));
|
||||
});
|
||||
}
|
||||
|
||||
static Map<Trait, Float> collect(Stream<Map.Entry<Trait, Float>> entries) {
|
||||
return entries.filter(Objects::nonNull)
|
||||
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (a, b) -> a + b, () -> new EnumMap<>(Trait.class)));
|
||||
|
|
|
@ -0,0 +1,115 @@
|
|||
package com.minelittlepony.unicopia.ability.magic.spell.trait;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import com.minelittlepony.unicopia.entity.player.Pony;
|
||||
import com.minelittlepony.unicopia.util.NbtSerialisable;
|
||||
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.item.Items;
|
||||
import net.minecraft.nbt.NbtCompound;
|
||||
import net.minecraft.nbt.NbtElement;
|
||||
import net.minecraft.nbt.NbtList;
|
||||
import net.minecraft.nbt.NbtString;
|
||||
import net.minecraft.text.Text;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.registry.Registry;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
public class TraitDiscovery implements NbtSerialisable {
|
||||
private final Set<Identifier> unreadTraits = new HashSet<>();
|
||||
|
||||
private final Set<Identifier> traits = new HashSet<>();
|
||||
private final Map<Identifier, SpellTraits> items = new HashMap<>();
|
||||
|
||||
private final Pony pony;
|
||||
|
||||
public TraitDiscovery(Pony pony) {
|
||||
this.pony = pony;
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
unreadTraits.clear();
|
||||
items.clear();
|
||||
traits.clear();
|
||||
pony.setDirty();
|
||||
}
|
||||
|
||||
public void markRead() {
|
||||
unreadTraits.clear();
|
||||
pony.setDirty();
|
||||
}
|
||||
|
||||
public void unlock(Item item) {
|
||||
if (item == Items.AIR) {
|
||||
return;
|
||||
}
|
||||
SpellTraits traits = SpellTraits.of(item);
|
||||
items.put(Registry.ITEM.getId(item), traits);
|
||||
traits.entries().forEach(e -> {
|
||||
if (this.traits.add(e.getKey().getId())) {
|
||||
unreadTraits.add(e.getKey().getId());
|
||||
}
|
||||
});
|
||||
pony.setDirty();
|
||||
}
|
||||
|
||||
public SpellTraits getKnownTraits(Item item) {
|
||||
return items.getOrDefault(Registry.ITEM.getId(item), SpellTraits.EMPTY);
|
||||
}
|
||||
|
||||
public void appendTooltip(ItemStack stack, @Nullable World world, List<Text> tooltip) {
|
||||
getKnownTraits(stack.getItem()).appendTooltip(tooltip);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void toNBT(NbtCompound compound) {
|
||||
NbtCompound disco = new NbtCompound();
|
||||
items.forEach((key, val) -> {
|
||||
disco.put(key.toString(), val.toNbt());
|
||||
});
|
||||
compound.put("items", disco);
|
||||
|
||||
NbtList a = new NbtList();
|
||||
this.traits.forEach(id -> a.add(NbtString.of(id.toString())));
|
||||
compound.put("traits", a);
|
||||
|
||||
NbtList b = new NbtList();
|
||||
unreadTraits.forEach(id -> b.add(NbtString.of(id.toString())));
|
||||
compound.put("unreadTraits", b);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fromNBT(NbtCompound compound) {
|
||||
clear();
|
||||
NbtCompound disco = compound.getCompound("items");
|
||||
disco.getKeys().forEach(key -> {
|
||||
Optional.ofNullable(Identifier.tryParse(key)).ifPresent(id -> {
|
||||
SpellTraits.fromNbt(disco.getCompound(key)).ifPresent(val -> {
|
||||
items.put(id, val);
|
||||
});
|
||||
});
|
||||
});
|
||||
compound.getList("traits", NbtElement.STRING_TYPE).forEach(el -> {
|
||||
Optional.ofNullable(Identifier.tryParse(el.asString())).ifPresent(this.traits::add);
|
||||
});
|
||||
compound.getList("unreadTraits", NbtElement.STRING_TYPE).forEach(el -> {
|
||||
Optional.ofNullable(Identifier.tryParse(el.asString())).ifPresent(this.unreadTraits::add);
|
||||
});
|
||||
}
|
||||
|
||||
public void copyFrom(TraitDiscovery old) {
|
||||
clear();
|
||||
unreadTraits.addAll(old.unreadTraits);
|
||||
traits.addAll(old.traits);
|
||||
items.putAll(old.items);
|
||||
}
|
||||
}
|
|
@ -42,7 +42,7 @@ public class TraitLoader extends SinglePreparationResourceReloader<Map<Identifie
|
|||
for (String namespace : manager.getAllNamespaces()) {
|
||||
profiler.push(namespace);
|
||||
try {
|
||||
for (Resource resource : manager.getAllResources(new Identifier(namespace, "items/traits"))) {
|
||||
for (Resource resource : manager.getAllResources(new Identifier(namespace, "traits/items.json"))) {
|
||||
profiler.push(resource.getResourcePackName());
|
||||
|
||||
try (InputStreamReader reader = new InputStreamReader(resource.getInputStream(), StandardCharsets.UTF_8)) {
|
||||
|
|
|
@ -5,7 +5,10 @@ import java.util.List;
|
|||
import java.util.Optional;
|
||||
|
||||
import com.minelittlepony.unicopia.EquinePredicates;
|
||||
import com.minelittlepony.unicopia.entity.player.Pony;
|
||||
import com.minelittlepony.unicopia.item.UItems;
|
||||
import com.minelittlepony.unicopia.item.URecipes;
|
||||
import com.minelittlepony.unicopia.util.InventoryUtil;
|
||||
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.entity.player.PlayerInventory;
|
||||
|
@ -13,11 +16,12 @@ import net.minecraft.inventory.CraftingInventory;
|
|||
import net.minecraft.inventory.CraftingResultInventory;
|
||||
import net.minecraft.inventory.Inventory;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.recipe.RecipeType;
|
||||
import net.minecraft.screen.ScreenHandler;
|
||||
import net.minecraft.screen.slot.CraftingResultSlot;
|
||||
import net.minecraft.screen.slot.Slot;
|
||||
import net.minecraft.server.network.ServerPlayerEntity;
|
||||
import net.minecraft.util.Pair;
|
||||
import net.minecraft.util.collection.DefaultedList;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
public class SpellbookScreenHandler extends ScreenHandler {
|
||||
|
@ -28,7 +32,7 @@ public class SpellbookScreenHandler extends ScreenHandler {
|
|||
private final int HOTBAR_START;
|
||||
private final int HOTBAR_END;
|
||||
|
||||
private final CraftingInventory input;
|
||||
private final SpellbookInventory input;
|
||||
|
||||
private OutputSlot gemSlot;
|
||||
private final CraftingResultInventory result = new CraftingResultInventory();
|
||||
|
@ -47,7 +51,7 @@ public class SpellbookScreenHandler extends ScreenHandler {
|
|||
HOTBAR_START = GEM_SLOT_INDEX + 1;
|
||||
HOTBAR_END = HOTBAR_START + 9;
|
||||
|
||||
input = new CraftingInventory(this, MAX_INGREDIENTS, 1);
|
||||
input = new SpellbookInventory(this, MAX_INGREDIENTS, 1);
|
||||
|
||||
for (int i = 0; i < MAX_INGREDIENTS; i++) {
|
||||
var pos = grid.get(i);
|
||||
|
@ -72,7 +76,8 @@ public class SpellbookScreenHandler extends ScreenHandler {
|
|||
public void onContentChanged(Inventory inventory) {
|
||||
World world = this.inventory.player.world;
|
||||
if (!world.isClient && !gemSlot.getStack().isEmpty()) {
|
||||
world.getServer().getRecipeManager().getFirstMatch(RecipeType.CRAFTING, input, world)
|
||||
world.getServer().getRecipeManager().getFirstMatch(URecipes.SPELLBOOK, input, world)
|
||||
.filter(recipe -> result.shouldCraftRecipe(world, (ServerPlayerEntity)this.inventory.player, recipe))
|
||||
.map(recipe -> recipe.craft(input))
|
||||
.ifPresentOrElse(gemSlot::setCrafted, gemSlot::setUncrafted);
|
||||
}
|
||||
|
@ -202,6 +207,17 @@ public class SpellbookScreenHandler extends ScreenHandler {
|
|||
|
||||
public interface SpellbookSlot {}
|
||||
|
||||
public class SpellbookInventory extends CraftingInventory {
|
||||
|
||||
public SpellbookInventory(ScreenHandler handler, int width, int height) {
|
||||
super(handler, width, height);
|
||||
}
|
||||
|
||||
public ItemStack getItemToModify() {
|
||||
return gemSlot.getStack();
|
||||
}
|
||||
}
|
||||
|
||||
public class InputSlot extends Slot implements SpellbookSlot {
|
||||
public InputSlot(Inventory inventory, int index, int xPosition, int yPosition) {
|
||||
super(inventory, index, xPosition, yPosition);
|
||||
|
@ -217,8 +233,11 @@ public class SpellbookScreenHandler extends ScreenHandler {
|
|||
|
||||
private Optional<ItemStack> uncrafted = Optional.empty();
|
||||
|
||||
public OutputSlot(PlayerEntity player, CraftingInventory input, Inventory inventory, int index, int x, int y) {
|
||||
private final SpellbookInventory input;
|
||||
|
||||
public OutputSlot(PlayerEntity player, SpellbookInventory input, Inventory inventory, int index, int x, int y) {
|
||||
super(player, input, inventory, index, x, y);
|
||||
this.input = input;
|
||||
}
|
||||
|
||||
public void setCrafted(ItemStack crafted) {
|
||||
|
@ -247,7 +266,34 @@ public class SpellbookScreenHandler extends ScreenHandler {
|
|||
public void onTakeItem(PlayerEntity player, ItemStack stack) {
|
||||
if (uncrafted.isPresent()) {
|
||||
uncrafted = Optional.empty();
|
||||
super.onTakeItem(player, stack);
|
||||
onCrafted(stack);
|
||||
|
||||
Pony pony = Pony.of(player);
|
||||
InventoryUtil.iterate(input).forEach(s -> {
|
||||
pony.getDiscoveries().unlock(s.getItem());
|
||||
});
|
||||
|
||||
DefaultedList<ItemStack> defaultedList = player.world.getRecipeManager().getRemainingStacks(URecipes.SPELLBOOK, input, player.world);
|
||||
|
||||
for (int i = 0; i < defaultedList.size(); ++i) {
|
||||
ItemStack itemStack = input.getStack(i);
|
||||
ItemStack itemStack2 = defaultedList.get(i);
|
||||
if (!itemStack.isEmpty()) {
|
||||
input.removeStack(i, 1);
|
||||
itemStack = input.getStack(i);
|
||||
}
|
||||
|
||||
if (!itemStack2.isEmpty()) {
|
||||
if (itemStack.isEmpty()) {
|
||||
input.setStack(i, itemStack2);
|
||||
} else if (ItemStack.areItemsEqualIgnoreDamage(itemStack, itemStack2) && ItemStack.areTagsEqual(itemStack, itemStack2)) {
|
||||
itemStack2.increment(itemStack.getCount());
|
||||
input.setStack(i, itemStack2);
|
||||
} else if (!player.getInventory().insertStack(itemStack2)) {
|
||||
player.dropItem(itemStack2, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,6 +18,7 @@ import com.minelittlepony.unicopia.ability.EarthPonyStompAbility;
|
|||
import com.minelittlepony.unicopia.ability.magic.Affine;
|
||||
import com.minelittlepony.unicopia.ability.magic.spell.Spell;
|
||||
import com.minelittlepony.unicopia.ability.magic.spell.effect.SpellType;
|
||||
import com.minelittlepony.unicopia.ability.magic.spell.trait.TraitDiscovery;
|
||||
import com.minelittlepony.unicopia.advancement.UCriteria;
|
||||
import com.minelittlepony.unicopia.entity.PonyContainer;
|
||||
import com.minelittlepony.unicopia.entity.Living;
|
||||
|
@ -77,6 +78,8 @@ public class Pony extends Living<PlayerEntity> implements Transmittable, Copieab
|
|||
private final PlayerCharmTracker charms = new PlayerCharmTracker(this);
|
||||
private final PlayerAttributes attributes = new PlayerAttributes(this);
|
||||
private final PlayerCamera camera = new PlayerCamera(this);
|
||||
private final TraitDiscovery discoveries = new TraitDiscovery(this);
|
||||
|
||||
private final ManaContainer mana;
|
||||
private final PlayerLevelStore levels;
|
||||
|
||||
|
@ -137,6 +140,10 @@ public class Pony extends Living<PlayerEntity> implements Transmittable, Copieab
|
|||
UCriteria.PLAYER_CHANGE_RACE.trigger(entity);
|
||||
}
|
||||
|
||||
public TraitDiscovery getDiscoveries() {
|
||||
return discoveries;
|
||||
}
|
||||
|
||||
public MagicReserves getMagicalReserves() {
|
||||
return mana;
|
||||
}
|
||||
|
@ -469,6 +476,7 @@ public class Pony extends Living<PlayerEntity> implements Transmittable, Copieab
|
|||
compound.put("powers", powers.toNBT());
|
||||
compound.put("gravity", gravity.toNBT());
|
||||
compound.put("charms", charms.toNBT());
|
||||
compound.put("discoveries", discoveries.toNBT());
|
||||
|
||||
getSpellSlot().get(true).ifPresent(effect ->{
|
||||
compound.put("effect", SpellType.toNBT(effect));
|
||||
|
@ -484,6 +492,7 @@ public class Pony extends Living<PlayerEntity> implements Transmittable, Copieab
|
|||
powers.fromNBT(compound.getCompound("powers"));
|
||||
gravity.fromNBT(compound.getCompound("gravity"));
|
||||
charms.fromNBT(compound.getCompound("charms"));
|
||||
discoveries.fromNBT(compound.getCompound("discoveries"));
|
||||
|
||||
magicExhaustion = compound.getFloat("magicExhaustion");
|
||||
|
||||
|
@ -500,6 +509,7 @@ public class Pony extends Living<PlayerEntity> implements Transmittable, Copieab
|
|||
}
|
||||
oldPlayer.setSpell(null);
|
||||
setSpecies(oldPlayer.getSpecies());
|
||||
getDiscoveries().copyFrom(oldPlayer.getDiscoveries());
|
||||
setDirty();
|
||||
}
|
||||
|
||||
|
|
|
@ -1,39 +1,27 @@
|
|||
package com.minelittlepony.unicopia.item;
|
||||
|
||||
import com.google.gson.JsonArray;
|
||||
import com.minelittlepony.unicopia.ability.magic.spell.crafting.SpellbookRecipe;
|
||||
import com.minelittlepony.unicopia.ability.magic.spell.crafting.TraitRequirementRecipe;
|
||||
|
||||
import net.fabricmc.fabric.api.loot.v1.FabricLootSupplier;
|
||||
import net.fabricmc.fabric.api.loot.v1.event.LootTableLoadingCallback;
|
||||
import net.minecraft.loot.LootTable;
|
||||
import net.minecraft.recipe.Ingredient;
|
||||
import net.minecraft.recipe.Recipe;
|
||||
import net.minecraft.recipe.RecipeSerializer;
|
||||
import net.minecraft.recipe.RecipeType;
|
||||
import net.minecraft.recipe.ShapelessRecipe;
|
||||
import net.minecraft.recipe.SpecialRecipeSerializer;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.collection.DefaultedList;
|
||||
import net.minecraft.util.registry.Registry;
|
||||
|
||||
public interface URecipes {
|
||||
RecipeType<SpellbookRecipe> SPELLBOOK = RecipeType.register("unicopia:spellbook");
|
||||
|
||||
RecipeSerializer<ShapelessRecipe> ZAP_APPLE_SERIALIZER = register("crafting_zap_apple", new ZapAppleRecipe.Serializer());
|
||||
RecipeSerializer<GlowingRecipe> GLOWING_SERIALIZER = register("crafting_glowing", new SpecialRecipeSerializer<>(GlowingRecipe::new));
|
||||
RecipeSerializer<JarInsertRecipe> JAR_INSERT_SERIALIZER = register("jar_insert", new SpecialRecipeSerializer<>(JarInsertRecipe::new));
|
||||
|
||||
static <T extends Recipe<?>> RecipeType<T> register(final String id) {
|
||||
return Registry.register(Registry.RECIPE_TYPE, new Identifier("unicopia", id), new RecipeType<T>() {
|
||||
@Override
|
||||
public String toString() {
|
||||
return id;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
static <S extends RecipeSerializer<T>, T extends Recipe<?>> S register(String id, S serializer) {
|
||||
return Registry.register(Registry.RECIPE_SERIALIZER, new Identifier("unicopia", id), serializer);
|
||||
}
|
||||
|
||||
RecipeSerializer<ShapelessRecipe> ZAP_APPLE_SERIALIZER = RecipeSerializer.register("unicopia:crafting_zap_apple", new ZapAppleRecipe.Serializer());
|
||||
RecipeSerializer<GlowingRecipe> GLOWING_SERIALIZER = RecipeSerializer.register("unicopia:crafting_glowing", new SpecialRecipeSerializer<>(GlowingRecipe::new));
|
||||
RecipeSerializer<JarInsertRecipe> JAR_INSERT_SERIALIZER = RecipeSerializer.register("unicopia:jar_insert", new SpecialRecipeSerializer<>(JarInsertRecipe::new));
|
||||
RecipeSerializer<TraitRequirementRecipe> TRAIT_REQUIREMENT = RecipeSerializer.register("unicopia:spellbook/crafting", new TraitRequirementRecipe.Serializer());
|
||||
|
||||
static DefaultedList<Ingredient> getIngredients(JsonArray json) {
|
||||
DefaultedList<Ingredient> defaultedList = DefaultedList.of();
|
||||
|
|
|
@ -7,6 +7,8 @@ import org.spongepowered.asm.mixin.Mixin;
|
|||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
import com.minelittlepony.unicopia.entity.player.Pony;
|
||||
import com.minelittlepony.unicopia.item.toxin.ToxicHolder;
|
||||
|
||||
import net.minecraft.client.MinecraftClient;
|
||||
|
@ -21,5 +23,8 @@ abstract class MixinItem implements ToxicHolder {
|
|||
@Inject(method = "appendTooltip", at = @At("RETURN"))
|
||||
private void onAppendTooltip(ItemStack stack, @Nullable World world, List<Text> tooltip, TooltipContext context, CallbackInfo into) {
|
||||
getToxic().ifPresent(t -> t.getAilmentFor(MinecraftClient.getInstance().player).appendTooltip(tooltip, context));
|
||||
if (MinecraftClient.getInstance().player != null) {
|
||||
Pony.of(MinecraftClient.getInstance().player).getDiscoveries().appendTooltip(stack, world, tooltip);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
package com.minelittlepony.unicopia.util;
|
||||
|
||||
import com.google.common.collect.AbstractIterator;
|
||||
|
||||
import net.minecraft.inventory.Inventory;
|
||||
import net.minecraft.item.ItemStack;
|
||||
|
||||
public interface InventoryUtil {
|
||||
static Iterable<ItemStack> iterate(Inventory inventory) {
|
||||
return () -> new AbstractIterator<>() {
|
||||
private int slot = 0;
|
||||
|
||||
@Override
|
||||
protected ItemStack computeNext() {
|
||||
if (slot >= inventory.size()) {
|
||||
return endOfData();
|
||||
}
|
||||
return inventory.getStack(slot++);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue