Update recipes and loot tables, ensure everything is obtainable that should be obtainable, and revamp the enchanting recipe system

This commit is contained in:
Sollace 2020-04-28 21:27:33 +02:00
parent 1ed4e719fd
commit 94952f5c16
148 changed files with 1393 additions and 1294 deletions

View file

@ -6,9 +6,38 @@ import net.minecraft.tag.Tag;
import net.minecraft.util.Identifier;
public interface UTags {
Tag<Item> CURSED_ARTEFACTS = TagRegistry.item(new Identifier("unicopia", "cursed_artefacts"));
Tag<Item> HAMMERPACE_IMMUNE = TagRegistry.item(new Identifier("unicopia", "hammerspace_immune"));
Tag<Item> APPLES = TagRegistry.item(new Identifier("unicopia", "apples"));
Tag<Item> CURSED_ARTEFACTS = register("cursed_artefacts");
Tag<Item> HAMMERPACE_IMMUNE = register("hammerspace_immune");
Tag<Item> APPLES = register("apples");
Tag<Item> FRESH_TOMATOES = register("fresh_tomatoes");
Tag<Item> FESH_APPLES = register("fresh_apples");
Tag<Item> SHARDS = register("shards");
Tag<Item> SHELLS = register("shells");
Tag<Item> FIRE_ELEMENTALS = register("fire_elementals");
Tag<Item> ICE_ELEMENTALS = register("ice_elementals");
Tag<Item> LIGHT_ELEMENTALS = register("light_elementals");
Tag<Item> DARK_ELEMENTALS = register("dark_elementals");
Tag<Item> LIFE_ELEMENTALS = register("life_elementals");
Tag<Item> ROTTING_ELEMENTALS = register("rotting_elementals");
Tag<Item> BLOOD_ELEMENTALS = register("death_elementals");
Tag<Item> UNALIGNED = register("harmonic_elementals");
Tag<Item> SIGHT_ELEMENTALS = register("sight_elementals");
Tag<Item> SOUND_ELEMENTALS = register("sound_elementals");
Tag<Item> MAGIC_ENERGIC = register("knowledge_elementals");
Tag<Item> APPLE_BLOOM_SPIRIT = register("apple_bloom_spirit");
Tag<Item> SCOOTALOO_SPIRIT = register("scootaloo_spirit");
Tag<Item> SWEETIE_BELLE_SPIRIT = register("sweetie_belle_spirit");
static Tag<Item> register(String name) {
return TagRegistry.item(new Identifier("unicopia", name));
}
static void bootstrap() { }
}

View file

@ -12,11 +12,10 @@ import com.minelittlepony.unicopia.block.UBlocks;
import com.minelittlepony.unicopia.command.Commands;
import com.minelittlepony.unicopia.container.UContainers;
import com.minelittlepony.unicopia.enchanting.Pages;
import com.minelittlepony.unicopia.enchanting.recipe.AffineIngredients;
import com.minelittlepony.unicopia.enchanting.recipe.URecipes;
import com.minelittlepony.unicopia.item.UItems;
import com.minelittlepony.unicopia.mixin.CriterionsRegistry;
import com.minelittlepony.unicopia.network.Channel;
import com.minelittlepony.unicopia.recipe.URecipes;
import com.minelittlepony.unicopia.structure.UStructures;
public class Unicopia implements ModInitializer {
@ -49,6 +48,5 @@ public class Unicopia implements ModInitializer {
CriterionsRegistry.register(BOHDeathCriterion.INSTANCE);
ResourceManagerHelper.get(ResourceType.SERVER_DATA).registerReloadListener(Pages.instance());
ResourceManagerHelper.get(ResourceType.CLIENT_RESOURCES).registerReloadListener(AffineIngredients.getInstance());
}
}

View file

@ -5,9 +5,9 @@ import javax.annotation.Nonnull;
import com.minelittlepony.unicopia.AwaitTickQueue;
import com.minelittlepony.unicopia.EquinePredicates;
import com.minelittlepony.unicopia.enchanting.IPageUnlockListener;
import com.minelittlepony.unicopia.enchanting.recipe.URecipes;
import com.minelittlepony.unicopia.entity.player.Pony;
import com.minelittlepony.unicopia.magic.spell.SpellRegistry;
import com.minelittlepony.unicopia.recipe.URecipes;
import net.minecraft.container.Container;
import net.minecraft.container.Slot;

View file

@ -2,10 +2,10 @@ package com.minelittlepony.unicopia.container;
import com.minelittlepony.unicopia.enchanting.IPageUnlockListener;
import com.minelittlepony.unicopia.enchanting.SpellCraftingEvent;
import com.minelittlepony.unicopia.enchanting.recipe.URecipes;
import com.minelittlepony.unicopia.entity.player.Pony;
import com.minelittlepony.unicopia.item.MagicGemItem;
import com.minelittlepony.unicopia.magic.spell.SpellRegistry;
import com.minelittlepony.unicopia.recipe.URecipes;
import com.mojang.datafixers.util.Pair;
import net.minecraft.container.PlayerContainer;

View file

@ -1,100 +0,0 @@
package com.minelittlepony.unicopia.enchanting.recipe;
import java.util.ArrayList;
import java.util.List;
import com.google.common.collect.Lists;
import com.minelittlepony.unicopia.container.SpellBookInventory;
import com.minelittlepony.unicopia.item.UItems;
import net.minecraft.inventory.CraftingInventory;
import net.minecraft.item.ItemStack;
import net.minecraft.recipe.Recipe;
import net.minecraft.util.DefaultedList;
import net.minecraft.util.Identifier;
import net.minecraft.world.World;
public abstract class AbstractSpecialRecipe implements Recipe<CraftingInventory> {
private final SpellIngredient spellitem;
private final DefaultedList<SpellIngredient> ingredients;
private final Identifier id;
public AbstractSpecialRecipe(Identifier id, SpellIngredient spellitem, DefaultedList<SpellIngredient> ingredients) {
this.id = id;
this.spellitem = spellitem;
this.ingredients = ingredients;
}
@Override
public boolean matches(CraftingInventory inv, World worldIn) {
ItemStack enchantedStack = ((SpellBookInventory)inv).getCraftResultMatrix().getInvStack(0);
if (enchantedStack.isEmpty() || enchantedStack.getItem() == null) {
return false;
}
if (!spellitem.matches(enchantedStack, enchantedStack.getCount())) {
return false;
}
int materialMult = enchantedStack.getCount();
ArrayList<SpellIngredient> toMatch = Lists.newArrayList(ingredients);
for (int i = 0; i < inv.getInvSize(); i++) {
ItemStack stack = inv.getInvStack(i);
if (!stack.isEmpty()) {
if (toMatch.isEmpty() || !removeMatch(toMatch, stack, materialMult)) {
return false;
}
}
}
return toMatch.isEmpty();
}
private boolean removeMatch(List<SpellIngredient> toMatch, ItemStack stack, int materialMult) {
return toMatch.stream()
.filter(s -> s.matches(stack, materialMult))
.findFirst()
.filter(toMatch::remove)
.isPresent();
}
@Override
public Identifier getId() {
return id;
}
@Override
public ItemStack craft(CraftingInventory inv) {
return getOutput();
}
@Override
public boolean fits(int width, int height) {
return width * height < ingredients.size();
}
@Override
public ItemStack getRecipeKindIcon() {
return new ItemStack(UItems.GEM);
}
public SpellIngredient getSpellItem() {
return spellitem;
}
public DefaultedList<SpellIngredient> getSpellIngredients() {
return ingredients;
}
@Override
public ItemStack getOutput() {
return spellitem.getStack();
}
}

View file

@ -1,62 +0,0 @@
package com.minelittlepony.unicopia.enchanting.recipe;
import java.util.stream.Stream;
import javax.annotation.Nonnull;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import net.minecraft.item.ItemStack;
import net.minecraft.util.Identifier;
import net.minecraft.util.PacketByteBuf;
class AffineIngredient implements SpellIngredient {
static final Serializer<AffineIngredient> SERIALIZER = new Serializer<AffineIngredient>() {
@Override
public AffineIngredient read(JsonElement json) {
return new AffineIngredient(new Identifier(json.getAsJsonObject().get("id").getAsString()));
}
@Override
public AffineIngredient read(PacketByteBuf buff) {
return new AffineIngredient(new Identifier(buff.readString()));
}
@Override
public void write(PacketByteBuf buff, AffineIngredient ingredient) {
buff.writeString(ingredient.res.toString());
}
};
private final Identifier res;
AffineIngredient(Identifier res) {
this.res = res;
}
@Override
public ItemStack getStack() {
return AffineIngredients.getInstance().getIngredient(res).getStack();
}
@Override
public Stream<ItemStack> getStacks() {
return AffineIngredients.getInstance().getIngredient(res).getStacks();
}
@Override
public boolean matches(ItemStack other, int materialMult) {
return AffineIngredients.getInstance().getIngredient(res).matches(other, materialMult);
}
@Nonnull
static SpellIngredient parse(JsonObject json) {
return SERIALIZER.read(json);
}
@Override
public Serializer<?> getSerializer() {
return SERIALIZER;
}
}

View file

@ -1,60 +0,0 @@
package com.minelittlepony.unicopia.enchanting.recipe;
import java.util.Map;
import com.google.common.collect.Maps;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonObject;
import net.fabricmc.fabric.api.resource.IdentifiableResourceReloadListener;
import net.minecraft.resource.JsonDataLoader;
import net.minecraft.resource.ResourceManager;
import net.minecraft.util.Identifier;
import net.minecraft.util.profiler.Profiler;
public class AffineIngredients extends JsonDataLoader implements IdentifiableResourceReloadListener {
private static final Identifier ID = new Identifier("unicopia", "ingredients");
private static final Gson GSON = new GsonBuilder()
.setPrettyPrinting()
.disableHtmlEscaping()
.create();
private static final AffineIngredients INSTANCE = new AffineIngredients();
public static AffineIngredients getInstance() {
return INSTANCE;
}
private final Map<Identifier, SpellIngredient> storedIngredients = Maps.newHashMap();
AffineIngredients() {
super(GSON, "ingredients");
}
@Override
public Identifier getFabricId() {
return ID;
}
@Override
protected void apply(Map<Identifier, JsonObject> data, ResourceManager manager, Profiler profiled) {
storedIngredients.clear();
data.forEach((id, json) -> {
SpellIngredient ingredient = SpellIngredient.parse(json.get("items"));
if (ingredient != null) {
storedIngredients.put(id, ingredient);
}
});
}
public SpellIngredient getIngredient(Identifier res) {
SpellIngredient result = storedIngredients.get(res);
if (result == null) {
new RuntimeException("Ingredient `" + res + "` was not found.").printStackTrace();
return SpellIngredient.EMPTY;
}
return result;
}
}

View file

@ -1,80 +0,0 @@
package com.minelittlepony.unicopia.enchanting.recipe;
import java.util.List;
import java.util.stream.Stream;
import com.google.common.collect.Lists;
import com.google.common.collect.Streams;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonParseException;
import net.minecraft.item.ItemStack;
import net.minecraft.util.PacketByteBuf;
class CompoundSpellIngredient implements SpellIngredient {
static final Serializer<CompoundSpellIngredient> SERIALIZER = new Serializer<CompoundSpellIngredient>() {
@Override
public CompoundSpellIngredient read(JsonElement json) {
JsonArray arr = json.getAsJsonArray();
if (arr.size() > 0) {
List<SpellIngredient> items = Lists.newArrayList();
for (JsonElement j : arr) {
SpellIngredient item = SpellIngredient.parse(j);
if (item != null) {
items.add(item);
}
}
if (!items.isEmpty()) {
return new CompoundSpellIngredient(items);
}
}
throw new JsonParseException("Invalid spell ingredient (compound)");
}
@Override
public CompoundSpellIngredient read(PacketByteBuf buff) {
return null;
}
@Override
public void write(PacketByteBuf buff, CompoundSpellIngredient recipe) {
}
};
private final List<SpellIngredient> items;
CompoundSpellIngredient(List<SpellIngredient> items) {
this.items = items;
}
@Override
public Stream<ItemStack> getStacks() {
Stream<ItemStack> stacks = Lists.<ItemStack>newArrayList().stream();
for (SpellIngredient i : items) {
stacks = Streams.concat(stacks, i.getStacks());
}
return stacks.distinct();
}
@Override
public ItemStack getStack() {
return items.get((int)(Math.random() * items.size())).getStack();
}
@Override
public boolean matches(ItemStack other, int materialMult) {
return items.stream().anyMatch(item -> item.matches(other, materialMult));
}
@Override
public Serializer<?> getSerializer() {
return SERIALIZER;
}
}

View file

@ -1,104 +0,0 @@
package com.minelittlepony.unicopia.enchanting.recipe;
import java.util.Optional;
import java.util.stream.Stream;
import com.google.common.collect.Streams;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParseException;
import com.minelittlepony.unicopia.magic.spell.SpellRegistry;
import net.minecraft.item.Item;
import net.minecraft.item.ItemGroup;
import net.minecraft.item.ItemStack;
import net.minecraft.util.DefaultedList;
import net.minecraft.util.Identifier;
import net.minecraft.util.PacketByteBuf;
import net.minecraft.util.registry.Registry;
class SingleSpellIngredient implements SpellIngredient {
static final Serializer<SpellIngredient> SERIALIZER = new Serializer<SpellIngredient>() {
@Override
public SpellIngredient read(JsonElement json) {
JsonObject obj = json.getAsJsonObject();
Item item = obj.has("item") ? Registry.ITEM.get(new Identifier(obj.get("item").getAsString())) : null;
if (item != null) {
int size = Math.max(1, obj.has("count") ? obj.get("count").getAsInt() : 1);
String spell = obj.has("spell") ? obj.get("spell").getAsString() : null;
ItemStack stack = new ItemStack(item, size);
if (spell != null) {
stack = SpellRegistry.instance().enchantStack(stack, spell);
}
return new SingleSpellIngredient(stack, !(obj.has("spell") || obj.has("data")));
}
if (obj.has("id")) {
return AffineIngredient.parse(obj);
}
throw new JsonParseException("Invalid spell ingredient (single)");
}
@Override
public SingleSpellIngredient read(PacketByteBuf buff) {
return null;
}
@Override
public void write(PacketByteBuf buff, SpellIngredient recipe) {
}
};
private final ItemStack contained;
SingleSpellIngredient(ItemStack stack, boolean meta) {
contained = stack;
}
@Override
public Stream<ItemStack> getStacks() {
if (!contained.isEmpty()) {
DefaultedList<ItemStack> subItems = DefaultedList.of();
contained.getItem().appendStacks(ItemGroup.SEARCH, subItems);
return subItems.stream();
}
return Streams.stream(Optional.ofNullable(contained));
}
@Override
public ItemStack getStack() {
return contained;
}
@Override
public boolean matches(ItemStack other, int materialMult) {
if (other.isEmpty() != contained.isEmpty()) {
return false;
} else if (other.isEmpty()) {
return true;
}
if (other.isEmpty()) {
return false;
}
if (contained.getItem() == other.getItem()
&& ItemStack.areItemsEqual(contained, other)) {
return other.getCount() >= (materialMult * contained.getCount());
}
return false;
}
@Override
public Serializer<?> getSerializer() {
return SERIALIZER;
}
}

View file

@ -1,68 +0,0 @@
package com.minelittlepony.unicopia.enchanting.recipe;
import com.google.gson.JsonObject;
import net.minecraft.item.ItemStack;
import net.minecraft.recipe.RecipeSerializer;
import net.minecraft.recipe.RecipeType;
import net.minecraft.util.DefaultedList;
import net.minecraft.util.Identifier;
import net.minecraft.util.PacketByteBuf;
public class SpecialRecipe extends AbstractSpecialRecipe {
private final SpellIngredient output;
public SpecialRecipe(Identifier id, SpellIngredient input, SpellIngredient output, DefaultedList<SpellIngredient> ingredients) {
super(id, input, ingredients);
this.output = output;
}
@Override
public ItemStack getOutput() {
return output.getStack();
}
@Override
public RecipeSerializer<?> getSerializer() {
return URecipes.SPECIAL_SERIALIZER;
}
@Override
public RecipeType<?> getType() {
return URecipes.SPELL_BOOK;
}
public static class Serializer implements RecipeSerializer<SpecialRecipe> {
@Override
public SpecialRecipe read(Identifier id, JsonObject json) {
return new SpecialRecipe(id,
SpellIngredient.single(json.get("input").getAsJsonObject()),
SpellIngredient.single(json.get("output").getAsJsonObject()),
SpellIngredient.multiple(json)
);
}
@Override
public SpecialRecipe read(Identifier id, PacketByteBuf buf) {
SpellIngredient input = SpellIngredient.SERIALIZER.read(buf);
SpellIngredient output = SpellIngredient.SERIALIZER.read(buf);
int length = buf.readInt();
DefaultedList<SpellIngredient> ingredients = DefaultedList.copyOf(SpellIngredient.EMPTY);
while (ingredients.size() < length) {
ingredients.add(SpellIngredient.SERIALIZER.read(buf));
}
return new SpecialRecipe(id, input, output, ingredients);
}
@Override
public void write(PacketByteBuf buf, SpecialRecipe recipe) {
recipe.getSpellItem().write(buf);
recipe.output.write(buf);
DefaultedList<SpellIngredient> ingredients = recipe.getSpellIngredients();
buf.writeInt(ingredients.size());
ingredients.forEach(i -> i.write(buf));
}
}
}

View file

@ -1,90 +0,0 @@
package com.minelittlepony.unicopia.enchanting.recipe;
import java.util.HashMap;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParseException;
import net.minecraft.item.ItemStack;
import net.minecraft.util.DefaultedList;
import net.minecraft.util.PacketByteBuf;
import net.minecraft.util.Util;
public interface SpellIngredient {
SpellIngredient EMPTY = new SingleSpellIngredient(ItemStack.EMPTY, false);
Map<String, Serializer<? extends SpellIngredient>> SERIALIZERS = Util.make(new HashMap<>(), map -> {
map.put("compound", CompoundSpellIngredient.SERIALIZER);
map.put("single", SingleSpellIngredient.SERIALIZER);
map.put("affine", AffineIngredient.SERIALIZER);
});
Map<Serializer<? extends SpellIngredient>, String> IDS = SERIALIZERS.entrySet().stream().collect(Collectors.toMap(Map.Entry::getValue, Map.Entry::getKey));
Serializer<SpellIngredient> SERIALIZER = new Serializer<SpellIngredient>() {
@Override
public SpellIngredient read(JsonElement json) {
if (json.isJsonArray()) {
return CompoundSpellIngredient.SERIALIZER.read(json);
}
return SingleSpellIngredient.SERIALIZER.read(json);
}
@Override
public SpellIngredient read(PacketByteBuf buff) {
String type = buff.readString();
return SERIALIZERS.get(type).read(buff);
}
@Override
public void write(PacketByteBuf buff, SpellIngredient recipe) {
buff.writeString(IDS.get(recipe.getSerializer()));
recipe.write(buff);
}
};
static SpellIngredient single(JsonObject json) {
return parse(json.get("item"));
}
static DefaultedList<SpellIngredient> multiple(JsonObject json) {
DefaultedList<SpellIngredient> ingredients = DefaultedList.of();
json.get("ingredients").getAsJsonArray().forEach(i -> ingredients.add(parse(i)));
if (ingredients.isEmpty()) {
throw new JsonParseException("Recipe cannot have 0 ingredients");
}
return ingredients;
}
static SpellIngredient parse(JsonElement json) {
return SERIALIZER.read(json);
}
boolean matches(ItemStack other, int materialMult);
ItemStack getStack();
Stream<ItemStack> getStacks();
Serializer<?> getSerializer();
@SuppressWarnings("unchecked")
default void write(PacketByteBuf buff) {
((Serializer<SpellIngredient>)getSerializer()).write(buff, this);
}
interface Serializer<T> {
T read(JsonElement json);
T read(PacketByteBuf buff);
void write(PacketByteBuf buff, T ingredient);
}
}

View file

@ -1,96 +0,0 @@
package com.minelittlepony.unicopia.enchanting.recipe;
import com.google.gson.JsonObject;
import com.minelittlepony.unicopia.container.SpellBookInventory;
import com.minelittlepony.unicopia.item.UItems;
import com.minelittlepony.unicopia.magic.spell.SpellRegistry;
import net.minecraft.inventory.CraftingInventory;
import net.minecraft.inventory.Inventory;
import net.minecraft.item.ItemStack;
import net.minecraft.recipe.RecipeSerializer;
import net.minecraft.recipe.RecipeType;
import net.minecraft.util.DefaultedList;
import net.minecraft.util.Identifier;
import net.minecraft.util.PacketByteBuf;
public class SpellRecipe extends AbstractSpecialRecipe {
private final String spellId;
public SpellRecipe(Identifier id, SpellIngredient spellitem, String spellName, DefaultedList<SpellIngredient> ingredients) {
super(id, spellitem, ingredients);
this.spellId = spellName;
}
@Override
public ItemStack getRecipeKindIcon() {
return new ItemStack(UItems.SPELLBOOK);
}
@Override
public ItemStack craft(CraftingInventory inv) {
SpellBookInventory inventory = (SpellBookInventory)inv;
Inventory craftResult = inventory.getCraftResultMatrix();
ItemStack stackToEnchant = craftResult.getInvStack(0);
return SpellRegistry.instance().enchantStack(stackToEnchant, spellId);
}
@Override
public ItemStack getOutput() {
return SpellRegistry.instance().enchantStack(super.getOutput(), spellId);
}
@Override
public RecipeSerializer<?> getSerializer() {
return URecipes.SPELL_SERIALIZER;
}
@Override
public RecipeType<?> getType() {
return URecipes.SPELL_BOOK;
}
public static class Serializer implements RecipeSerializer<SpellRecipe> {
@Override
public SpellRecipe read(Identifier id, JsonObject json) {
JsonObject resultJson = json.get("result").getAsJsonObject();
return new SpellRecipe(id,
SpellIngredient.single(resultJson),
resultJson.get("spell").getAsString(),
SpellIngredient.multiple(json)
);
}
@Override
public SpellRecipe read(Identifier id, PacketByteBuf buff) {
SpellIngredient spellItem = SpellIngredient.SERIALIZER.read(buff);
String spellName = buff.readString();
int size = buff.readInt();
DefaultedList<SpellIngredient> ingredients = DefaultedList.ofSize(0, SpellIngredient.EMPTY);
while (ingredients.size() < size) {
ingredients.add(SpellIngredient.SERIALIZER.read(buff));
}
return new SpellRecipe(id,
spellItem,
spellName,
ingredients);
}
@Override
public void write(PacketByteBuf buff, SpellRecipe recipe) {
recipe.getSpellItem().write(buff);
buff.writeString(recipe.spellId);
DefaultedList<SpellIngredient> ingredients = recipe.getSpellIngredients();
buff.writeInt(ingredients.size());
ingredients.forEach(i -> i.write(buff));
}
}
}

View file

@ -177,10 +177,6 @@ public interface UItems {
}
static void bootstrap() {
// FurnaceRecipes.instance().addSmeltingRecipe(new ItemStack(zap_apple), new ItemStack(cooked_zap_apple), 0.1F);
// FurnaceRecipes.instance().addSmeltingRecipe(new ItemStack(juice), new ItemStack(burned_juice), 0);
// FurnaceRecipes.instance().addSmeltingRecipe(new ItemStack(cuccoon), new ItemStack(chitin_shell), 0.3F);
Toxics.bootstrap();
}
}

View file

@ -0,0 +1,77 @@
package com.minelittlepony.unicopia.recipe;
import java.util.List;
import com.google.common.collect.Lists;
import net.minecraft.inventory.Inventory;
import net.minecraft.item.ItemStack;
import net.minecraft.recipe.Recipe;
import net.minecraft.util.DefaultedList;
import net.minecraft.util.Identifier;
import net.minecraft.world.World;
/**
* Basic crafting recipe that uses our custom ingredients.
*/
public abstract class AbstractShapelessPredicatedRecipe<C extends Inventory> implements Recipe<C> {
protected final Ingredient output;
protected final DefaultedList<Ingredient> ingredients;
private final Identifier id;
public AbstractShapelessPredicatedRecipe(Identifier id, Ingredient output, DefaultedList<Ingredient> ingredients) {
this.id = id;
this.output = output;
this.ingredients = ingredients;
}
protected abstract int getInputMultiplier(C inv, World worldIn);
@Override
public boolean matches(C inv, World worldIn) {
int materialMult = getInputMultiplier(inv, worldIn);
if (materialMult == 0) {
return false;
}
List<Ingredient> toMatch = Lists.newArrayList(ingredients);
for (int i = 0; i < inv.getInvSize(); i++) {
ItemStack stack = inv.getInvStack(i);
if (!stack.isEmpty()) {
if (toMatch.isEmpty() || !removeMatch(toMatch, stack, materialMult)) {
return false;
}
}
}
return toMatch.isEmpty();
}
private boolean removeMatch(List<Ingredient> toMatch, ItemStack stack, int materialMult) {
return toMatch.stream()
.filter(s -> s.matches(stack, materialMult))
.findFirst()
.filter(toMatch::remove)
.isPresent();
}
@Override
public Identifier getId() {
return id;
}
@Override
public ItemStack craft(C inv) {
return getOutput();
}
@Override
public boolean fits(int width, int height) {
return width * height < ingredients.size();
}
}

View file

@ -0,0 +1,43 @@
package com.minelittlepony.unicopia.recipe;
import java.util.List;
import java.util.Random;
import java.util.stream.Stream;
import com.google.gson.JsonArray;
import net.minecraft.item.ItemStack;
import net.minecraft.util.PacketByteBuf;
class ChoicePredicate implements Ingredient.Predicate {
static Ingredient.Predicate read(JsonArray arr) {
return new ChoicePredicate(Ingredient.many(arr));
}
private final List<Ingredient> options;
ChoicePredicate(List<Ingredient> options) {
this.options = options;
}
@Override
public ItemStack applyModifiers(ItemStack output, Random random) {
return options.get((int)(random.nextFloat() * options.size())).getStack(random);
}
@Override
public boolean matches(ItemStack stack, int materialMult) {
return options.stream().anyMatch(i -> i.matches(stack, materialMult));
}
@Override
public void write(PacketByteBuf buf) {
buf.writeInt(options.size());
options.forEach(i -> i.write(buf));
}
@Override
public Stream<ItemStack> getMatchingStacks() {
return options.stream().flatMap(Ingredient::getMatchingStacks).distinct();
}
}

View file

@ -0,0 +1,82 @@
package com.minelittlepony.unicopia.recipe;
import java.util.Random;
import java.util.stream.Stream;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParseException;
import net.minecraft.enchantment.Enchantment;
import net.minecraft.enchantment.EnchantmentHelper;
import net.minecraft.item.ItemStack;
import net.minecraft.util.Identifier;
import net.minecraft.util.PacketByteBuf;
import net.minecraft.util.registry.Registry;
/**
* A predicate that tests for a specific enchantment on an input item.
*/
class EnchantmentPredicate implements Ingredient.Predicate {
public static Ingredient.Predicate read(PacketByteBuf buf) {
int level = buf.readInt();
if (level == 0) {
return EMPTY;
}
return new EnchantmentPredicate(Registry.ENCHANTMENT.get(buf.readIdentifier()), level);
}
static Ingredient.Predicate read(JsonObject json) {
if (!json.has("enchantment")) {
return EMPTY;
}
JsonElement e = json.get("enchantment");
if (e.isJsonObject()) {
JsonObject o = e.getAsJsonObject();
Enchantment enchantment = Registry.ENCHANTMENT.get(new Identifier(o.get("id").getAsString()));
int level = o.has("level") ? o.get("level").getAsInt() : 1;
return new EnchantmentPredicate(enchantment, level);
}
Enchantment enchantment = Registry.ENCHANTMENT.get(new Identifier(e.getAsString()));
return new EnchantmentPredicate(enchantment, 1);
}
private final int level;
private final Enchantment enchantment;
EnchantmentPredicate(Enchantment enchantment, int level) {
this.enchantment = enchantment;
this.level = level;
if (enchantment == null) {
throw new JsonParseException("Invalid enchantment (null)");
}
}
@Override
public ItemStack applyModifiers(ItemStack output, Random random) {
output.addEnchantment(enchantment, level);
return output;
}
@Override
public boolean matches(ItemStack stack, int materialMult) {
return EnchantmentHelper.getLevel(enchantment, stack) >= level;
}
@Override
public void write(PacketByteBuf buf) {
buf.writeInt(level);
buf.writeIdentifier(Registry.ENCHANTMENT.getId(enchantment));
}
@Override
public Stream<ItemStack> getMatchingStacks() {
return Stream.empty();
}
}

View file

@ -0,0 +1,137 @@
package com.minelittlepony.unicopia.recipe;
import java.util.List;
import java.util.Random;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import javax.annotation.concurrent.Immutable;
import com.google.common.collect.Streams;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParseException;
import net.minecraft.item.ItemStack;
import net.minecraft.util.DefaultedList;
import net.minecraft.util.Lazy;
import net.minecraft.util.PacketByteBuf;
@Immutable
class Ingredient {
public static final Ingredient EMPTY = new Ingredient(Predicate.EMPTY, Predicate.EMPTY, Predicate.EMPTY, Predicate.EMPTY);
private final Predicate stack;
private final Predicate tag;
private final Predicate spell;
private final Predicate enchantment;
private final Lazy<List<ItemStack>> matchingStacks;
Ingredient(Predicate stack, Predicate tag, Predicate spell, Predicate enchantment) {
this.stack = stack;
this.tag = tag;
this.spell = spell;
this.enchantment = enchantment;
this.matchingStacks = new Lazy<>(() -> {
return Streams.concat(
stack.getMatchingStacks(),
tag.getMatchingStacks(),
spell.getMatchingStacks(),
enchantment.getMatchingStacks()
).filter(s -> matches(s, 1))
.collect(Collectors.toList());
});
}
public Stream<ItemStack> getMatchingStacks() {
return matchingStacks.get().stream();
}
public ItemStack getStack(Random random) {
ItemStack output = ItemStack.EMPTY.copy();
stack.applyModifiers(output, random);
tag.applyModifiers(output, random);
spell.applyModifiers(output, random);
enchantment.applyModifiers(output, random);
return output;
}
public boolean matches(ItemStack other, int materialMult) {
return stack.matches(other, materialMult)
&& tag.matches(other, materialMult)
&& spell.matches(other, materialMult)
&& enchantment.matches(other, materialMult);
}
public void write(PacketByteBuf buf) {
stack.write(buf);
tag.write(buf);
spell.write(buf);
enchantment.write(buf);
}
public static Ingredient read(PacketByteBuf buf) {
return new Ingredient(
StackPredicate.read(buf),
TagPredicate.read(buf),
SpellPredicate.read(buf),
EnchantmentPredicate.read(buf));
}
public static Ingredient one(JsonElement json) {
if (json.isJsonArray()) {
return new Ingredient(
ChoicePredicate.read(json.getAsJsonArray()),
Predicate.EMPTY,
Predicate.EMPTY,
Predicate.EMPTY);
}
JsonObject obj = json.getAsJsonObject();
return new Ingredient(
StackPredicate.read(obj),
TagPredicate.read(obj),
SpellPredicate.read(obj),
EnchantmentPredicate.read(obj));
}
public static DefaultedList<Ingredient> many(JsonArray arr) {
DefaultedList<Ingredient> ingredients = DefaultedList.copyOf(EMPTY);
arr.forEach(i -> ingredients.add(one(i)));
if (ingredients.isEmpty()) {
throw new JsonParseException("Recipe cannot have 0 ingredients");
}
return ingredients;
}
public interface Predicate {
Predicate EMPTY = new Predicate() {
@Override
public Stream<ItemStack> getMatchingStacks() {
return Stream.empty();
}
@Override
public boolean matches(ItemStack stack, int materialMult) {
return true;
}
};
Stream<ItemStack> getMatchingStacks();
boolean matches(ItemStack stack, int materialMult);
default ItemStack applyModifiers(ItemStack output, Random random) {
return output;
}
default void write(PacketByteBuf buf) {
buf.writeInt(0);
}
}
}

View file

@ -0,0 +1,99 @@
package com.minelittlepony.unicopia.recipe;
import java.util.Random;
import com.google.gson.JsonObject;
import com.minelittlepony.unicopia.container.SpellBookInventory;
import com.minelittlepony.unicopia.item.UItems;
import net.minecraft.inventory.CraftingInventory;
import net.minecraft.item.ItemStack;
import net.minecraft.recipe.RecipeSerializer;
import net.minecraft.recipe.RecipeType;
import net.minecraft.util.DefaultedList;
import net.minecraft.util.Identifier;
import net.minecraft.util.PacketByteBuf;
import net.minecraft.world.World;
/**
* Spellbook recipe accepting an item to enchant, a number of ingredients to use, an ingredient to compose the output.
*/
public class SpellBookRecipe extends AbstractShapelessPredicatedRecipe<CraftingInventory> {
private static final Random RANDOM = new Random();
protected final Ingredient input;
public SpellBookRecipe(Identifier id, Ingredient input, Ingredient output, DefaultedList<Ingredient> ingredients) {
super(id, output, ingredients);
this.input = input;
}
@Override
protected int getInputMultiplier(CraftingInventory inv, World worldIn) {
ItemStack enchantedStack = ((SpellBookInventory)inv).getCraftResultMatrix().getInvStack(0);
if (enchantedStack.isEmpty() || enchantedStack.getItem() == null) {
return 0;
}
if (!input.matches(enchantedStack, enchantedStack.getCount())) {
return 0;
}
return enchantedStack.getCount();
}
@Override
public ItemStack getOutput() {
return output.getStack(RANDOM);
}
@Override
public ItemStack getRecipeKindIcon() {
return new ItemStack(UItems.GEM);
}
@Override
public RecipeSerializer<?> getSerializer() {
return URecipes.ENCHANTING_SPELL_SERIALIZER;
}
@Override
public RecipeType<?> getType() {
return URecipes.SPELL_BOOK;
}
static class Serializer implements RecipeSerializer<SpellBookRecipe> {
@Override
public SpellBookRecipe read(Identifier id, JsonObject json) {
return new SpellBookRecipe(id,
Ingredient.one(json.get("input")),
Ingredient.one(json.get("result")),
Ingredient.many(json.get("ingredients").getAsJsonArray())
);
}
@Override
public SpellBookRecipe read(Identifier id, PacketByteBuf buf) {
Ingredient input = Ingredient.read(buf);
Ingredient output = Ingredient.read(buf);
int length = buf.readInt();
DefaultedList<Ingredient> ingredients = DefaultedList.copyOf(Ingredient.EMPTY);
while (ingredients.size() < length) {
ingredients.add(Ingredient.read(buf));
}
return new SpellBookRecipe(id, input, output, ingredients);
}
@Override
public void write(PacketByteBuf buf, SpellBookRecipe recipe) {
recipe.input.write(buf);
recipe.output.write(buf);
DefaultedList<Ingredient> ingredients = recipe.ingredients;
buf.writeInt(ingredients.size());
ingredients.forEach(i -> i.write(buf));
}
}
}

View file

@ -0,0 +1,55 @@
package com.minelittlepony.unicopia.recipe;
import java.util.Random;
import java.util.stream.Stream;
import com.google.gson.JsonObject;
import com.minelittlepony.unicopia.magic.spell.SpellRegistry;
import net.minecraft.item.ItemStack;
import net.minecraft.util.PacketByteBuf;
class SpellPredicate implements Ingredient.Predicate {
static Ingredient.Predicate read(PacketByteBuf buf) {
int level = buf.readInt();
if (level == 0) {
return EMPTY;
}
return new SpellPredicate(buf.readString());
}
static Ingredient.Predicate read(JsonObject json) {
if (!json.has("spell")) {
return EMPTY;
}
return new SpellPredicate(json.get("spell").getAsString());
}
private final String spell;
SpellPredicate(String spell) {
this.spell = spell;
}
@Override
public ItemStack applyModifiers(ItemStack output, Random random) {
return SpellRegistry.instance().enchantStack(output, spell);
}
@Override
public boolean matches(ItemStack stack, int materialMult) {
return SpellRegistry.getKeyFromStack(stack).equals(spell);
}
@Override
public void write(PacketByteBuf buf) {
buf.writeInt(1);
buf.writeString(spell);
}
@Override
public Stream<ItemStack> getMatchingStacks() {
return Stream.empty();
}
}

View file

@ -0,0 +1,106 @@
package com.minelittlepony.unicopia.recipe;
import java.util.Optional;
import java.util.Random;
import java.util.stream.Stream;
import com.google.common.collect.Streams;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonSyntaxException;
import net.minecraft.item.Item;
import net.minecraft.item.ItemGroup;
import net.minecraft.item.ItemStack;
import net.minecraft.item.Items;
import net.minecraft.util.DefaultedList;
import net.minecraft.util.Identifier;
import net.minecraft.util.PacketByteBuf;
import net.minecraft.util.registry.Registry;
class StackPredicate implements Ingredient.Predicate {
static Ingredient.Predicate read(PacketByteBuf buf) {
int count = buf.readInt();
if (count == 0) {
return EMPTY;
}
if (count > 0) {
return new StackPredicate(buf.readItemStack());
}
DefaultedList<Ingredient> items = DefaultedList.copyOf(Ingredient.EMPTY);
while (items.size() < count) {
items.add(Ingredient.read(buf));
}
return new ChoicePredicate(items);
}
static Ingredient.Predicate read(JsonObject json) {
if (!json.has("item")) {
return EMPTY;
}
JsonElement e = json.get("item");
if (e.isJsonArray()) {
return ChoicePredicate.read(e.getAsJsonArray());
}
if (e.isJsonObject()) {
JsonObject o = e.getAsJsonObject();
Item item = o.has("item") ? Registry.ITEM.get(new Identifier(o.get("item").getAsString())) : Items.AIR;
int size = o.has("count") ? Math.max(1, o.get("count").getAsInt()) : 1;
return new StackPredicate(new ItemStack(item, size));
}
return new StackPredicate(new ItemStack(Registry.ITEM.get(new Identifier(e.getAsString()))));
}
private final ItemStack stack;
StackPredicate(ItemStack stack) {
this.stack = stack;
if (stack.isEmpty()) {
throw new JsonSyntaxException("Unknown item tag");
}
}
@Override
public ItemStack applyModifiers(ItemStack output, Random random) {
return output.isEmpty() ? stack.copy() : output;
}
@Override
public Stream<ItemStack> getMatchingStacks() {
if (!stack.isEmpty()) {
DefaultedList<ItemStack> subItems = DefaultedList.of();
stack.getItem().appendStacks(ItemGroup.SEARCH, subItems);
return subItems.stream();
}
return Streams.stream(Optional.ofNullable(stack));
}
@Override
public boolean matches(ItemStack other, int materialMult) {
if (other.isEmpty() != stack.isEmpty()) {
return false;
}
if (other.isEmpty()) {
return true;
}
return ItemStack.areItemsEqual(stack, other)
&& other.getCount() >= (materialMult * stack.getCount());
}
@Override
public void write(PacketByteBuf buf) {
buf.writeInt(-1);
buf.writeItemStack(stack);
}
}

View file

@ -0,0 +1,79 @@
package com.minelittlepony.unicopia.recipe;
import java.util.Random;
import java.util.stream.Stream;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonSyntaxException;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.tag.ItemTags;
import net.minecraft.tag.Tag;
import net.minecraft.util.Identifier;
import net.minecraft.util.PacketByteBuf;
class TagPredicate implements Ingredient.Predicate {
static Ingredient.Predicate read(PacketByteBuf buf) {
int count = buf.readInt();
if (count == 0) {
return EMPTY;
}
return new TagPredicate(buf.readIdentifier(), count);
}
static Ingredient.Predicate read(JsonObject json) {
if (!json.has("tag")) {
return EMPTY;
}
JsonElement e = json.get("tag");
if (e.isJsonObject()) {
JsonObject o = e.getAsJsonObject();
Identifier id = new Identifier(o.get("id").getAsString());
int count = o.has("count") ? Math.max(1, o.get("count").getAsInt()) : 1;
if (count == 0) {
return EMPTY;
}
return new TagPredicate(id, count);
}
return new TagPredicate(new Identifier(json.getAsString()), 1);
}
private final Tag<Item> tag;
private final int count;
TagPredicate(Identifier res, int count) {
tag = ItemTags.getContainer().get(res);
this.count = count;
if (tag == null) {
throw new JsonSyntaxException("Unknown item tag '" + res + "'");
}
}
@Override
public ItemStack applyModifiers(ItemStack output, Random random) {
return output.isEmpty() ? new ItemStack(tag.getRandom(random)) : output;
}
@Override
public Stream<ItemStack> getMatchingStacks() {
return tag.values().stream().map(ItemStack::new);
}
@Override
public boolean matches(ItemStack other, int materialMult) {
return !other.isEmpty()
&& tag.contains(other.getItem())
&& other.getCount() > (count * materialMult);
}
@Override
public void write(PacketByteBuf buf) {
buf.writeInt(count);
buf.writeIdentifier(tag.getId());
}
}

View file

@ -1,4 +1,4 @@
package com.minelittlepony.unicopia.enchanting.recipe;
package com.minelittlepony.unicopia.recipe;
import net.minecraft.recipe.Recipe;
import net.minecraft.recipe.RecipeSerializer;
@ -7,11 +7,10 @@ import net.minecraft.util.Identifier;
import net.minecraft.util.registry.Registry;
public interface URecipes {
RecipeType<SpellBookRecipe> SPELL_BOOK = register("spell_book");
RecipeType<SpellRecipe> SPELL_BOOK = register("spell_book");
RecipeSerializer<SpecialRecipe> SPECIAL_SERIALIZER = register("special_spell", new SpecialRecipe.Serializer());
RecipeSerializer<SpellRecipe> SPELL_SERIALIZER = register("spell", new SpellRecipe.Serializer());
RecipeSerializer<SpellBookRecipe> ENCHANTING_SPELL_SERIALIZER = register("enchanting_spell", new SpellBookRecipe.Serializer());
RecipeSerializer<SpellBookRecipe> CRAFTING_SPELL_SERIALIZER = register("crafting_spell", new SpellBookRecipe.Serializer());
static <T extends Recipe<?>> RecipeType<T> register(final String id) {
return Registry.register(Registry.RECIPE_TYPE, new Identifier("unicopia", id), new RecipeType<T>() {

View file

@ -1,8 +0,0 @@
{
"items": [
{ "id": "unicopia:regular_apples" },
{ "item": "unicopia:apple_cider" },
{ "item": "unicopia:apple_seeds" },
{ "item": "minecraft:dye", "data": 1 }
]
}

View file

@ -1,11 +0,0 @@
{
"items": [
{ "item": "minecraft:red_glazed_terracotta" },
{ "item": "minecraft:dye", "data": 1 },
{ "item": "minecraft:redstone_block" },
{ "item": "minecraft:redstone" },
{ "item": "minecraft:emerald" },
{ "item": "minecraft:ghast_tear" },
{ "item": "minecraft:red_nether_brick" }
]
}

View file

@ -1,11 +0,0 @@
{
"items": [
{ "item": "minecraft:netherbrick" },
{ "item": "minecraft:brick" },
{ "item": "minecraft:red_nether_brick" },
{ "item": "minecraft:coal_block" },
{ "item": "minecraft:coal", "data": 0 },
{ "item": "unicopia:chitin_shell" },
{ "item": "unicopia:cuccoon" }
]
}

View file

@ -1,8 +0,0 @@
{
"items": [
{ "item": "unicopia:zap_apple" },
{ "item": "minecraft:redstone_torch" },
{ "item": "minecraft:redstone_block" },
{ "item": "minecraft:redstone" }
]
}

View file

@ -1,10 +0,0 @@
{
"items": [
{ "item": "minecraft:fire_charge" },
{ "item": "minecraft:magma_cream" },
{ "item": "minecraft:blaze_powder" },
{ "item": "minecraft:blaze_rod" },
{ "item": "minecraft:gold_nugget" },
{ "item": "minecraft:lava_bucket" }
]
}

View file

@ -1,7 +0,0 @@
{
"items": [
{ "item": "minecraft:ghast_tear" },
{ "item": "minecraft:water_bucket" },
{ "item": "minecraft:snowball" }
]
}

View file

@ -1,12 +0,0 @@
{
"items": [
{ "item": "minecraft:brown_mushroom" },
{ "item": "unicopia:rotten_apple" },
{ "item": "minecraft:golden_carrot" },
{ "item": "minecraft:wheat" },
{ "item": "minecraft:wheat_seeds" },
{ "item": "minecraft:grain" },
{ "item": "minecraft:alfalfa_leaves" },
{ "item": "unicopia:moss" }
]
}

View file

@ -1,6 +0,0 @@
{
"items": [
{ "item": "minecraft:glowstone" },
{ "item": "minecraft:glowstone_dust" }
]
}

View file

@ -1,8 +0,0 @@
{
"items": [
{ "item": "minecraft:apple" },
{ "item": "unicopia:apple_green" },
{ "item": "unicopia:apple_sweet" },
{ "item": "unicopia:apple_sour" }
]
}

View file

@ -1,11 +0,0 @@
{
"items": [
{ "item": "minecraft:rotten_flesh" },
{ "item": "unicopia:cloudsdale_tomato", "data": 1 },
{ "item": "unicopia:tomato", "data": 1 },
{ "item": "unicopia:rotten_apple" },
{ "item": "minecraft:red_mushroom" },
{ "item": "minecraft:brown_mushroom" },
{ "item": "unicopia:moss" }
]
}

View file

@ -1,8 +0,0 @@
{
"items": [
{ "item": "minecraft:chicken" },
{ "item": "minecraft:cooked_chicken" },
{ "item": "minecraft:feather" },
{ "item": "minecraft:string" }
]
}

View file

@ -1,7 +0,0 @@
{
"items": [
{ "item": "minecraft:egg" },
{ "item": "minecraft:coal" },
{ "item": "minecraft:flint" }
]
}

View file

@ -1,8 +0,0 @@
{
"items": [
{ "item": "minecraft:egg" },
{ "item": "minecraft:firework_charge" },
{ "item": "minecraft:ender_eye" },
{ "item": "minecraft:fire_charge" }
]
}

View file

@ -1,8 +0,0 @@
{
"items": [
{ "item": "minecraft:ender_eye" },
{ "item": "minecraft:spider_eye" },
{ "item": "minecraft:speckled_mellon" },
{ "item": "minecraft:ender_pearl" }
]
}

View file

@ -1,15 +0,0 @@
{
"items": [
{ "item": "minecraft:record_13" },
{ "item": "minecraft:record_cat" },
{ "item": "minecraft:record_blocks" },
{ "item": "minecraft:record_chirp" },
{ "item": "minecraft:record_far" },
{ "item": "minecraft:record_mall" },
{ "item": "minecraft:record_mellohi" },
{ "item": "minecraft:record_stal" },
{ "item": "minecraft:record_strad" },
{ "item": "minecraft:record_ward" },
{ "item": "minecraft:record_wait" }
]
}

View file

@ -1,7 +0,0 @@
{
"items": [
{ "item": "minecraft:noteblock" },
{ "item": "minecraft:jukebox" },
{ "item": "minecraft:diamond" }
]
}

View file

@ -1,9 +0,0 @@
{
"items": [
{ "item": "minecraft:red_flower" },
{ "item": "minecraft:yellow_flower" },
{ "item": "minecraft:tallgrass" },
{ "item": "minecraft:sapling" },
{ "item": "minecraft:stick" }
]
}

View file

@ -1,15 +0,0 @@
{
"type": "unicopia:crafting_spell",
"ingredients": [
{ "id": "unicopia:unaligned" },
{ "id": "unicopia:unaligned" },
{ "id": "unicopia:unaligned" }
],
"result": {
"item": [
{ "item": "unicopia:gem" },
{ "item": "unicopia:corrupted_gem" }
],
"spell": "awkward"
}
}

View file

@ -1,12 +0,0 @@
{
"type": "unicopia:crafting_spell",
"ingredients": [
{ "id": "unicopia:energy" },
{ "item": "unicopia:gem", "spell": "fire" },
{ "id": "unicopia:fire" }
],
"result": {
"item": { "item": "unicopia:gem" },
"spell": "charge"
}
}

View file

@ -1,12 +0,0 @@
{
"type": "unicopia:crafting_spell",
"ingredients": [
{ "item": "unicopia:gem", "spell": "flame" },
{ "id": "unicopia:fire" },
{ "id": "unicopia:fire" }
],
"result": {
"item": { "item": "unicopia:gem" },
"spell": "fire"
}
}

View file

@ -1,12 +0,0 @@
{
"type": "unicopia:crafting_spell",
"ingredients": [
{ "id": "unicopia:fire" },
{ "id": "unicopia:fire" },
{ "id": "unicopia:fire" }
],
"result": {
"item": { "item": "unicopia:gem" },
"spell": "fire"
}
}

View file

@ -1,12 +0,0 @@
{
"type": "unicopia:crafting_spell",
"ingredients": [
{ "id": "unicopia:ice" },
{ "id": "unicopia:ice" },
{ "id": "unicopia:ice" }
],
"result": {
"item": { "item": "unicopia:gem" },
"spell": "ice"
}
}

View file

@ -1,12 +0,0 @@
{
"type": "unicopia:crafting_spell",
"ingredients": [
{ "item": "unicopia:gem", "spell": "fire" },
{ "id": "unicopia:fire" },
{ "id": "unicopia:fire" }
],
"result": {
"item": { "item": "unicopia:corrupted_gem" },
"spell": "inferno"
}
}

View file

@ -1,12 +0,0 @@
{
"type": "unicopia:crafting_spell",
"ingredients": [
{ "id": "unicopia:blood" },
{ "id": "unicopia:energy" },
{ "id": "unicopia:rot" }
],
"result": {
"item": { "item": "unicopia:corrupted_gem" },
"spell": "necromancy"
}
}

View file

@ -1,14 +0,0 @@
{
"type": "unicopia:crafting_spell",
"ingredients": [
{ "id": "unicopia:energy" },
{ "id": "unicopia:life" },
{ "item": "unicopia:gem", "spell": "charge" }
],
"result": {
"item": [
{ "item": "unicopia:gem" }
],
"spell": "siphon"
}
}

View file

@ -1,13 +0,0 @@
{
"type": "unicopia:crafting_spell",
"ingredients": [
{ "id": "unicopia:sight" },
{ "item": "minecraft:ghast_tear" },
{ "id": "unicopia:energy" },
{ "item": "unicopia:gem", "spell": "fire" }
],
"result": {
"item": { "item": "unicopia:gem" },
"spell": "portal"
}
}

View file

@ -1,16 +0,0 @@
{
"type": "unicopia:crafting_special",
"ingredients": [
{ "id": "unicopia:apple_bloom" },
{ "id": "unicopia:scootaloo" },
{ "id": "unicopia:sweetie_belle" }
],
"input": {
"item": [
{ "id": "unicopia:sound"}
]
},
"output": {
"item": { "item": "unicopia:record_crusade" }
}
}

View file

@ -1,13 +0,0 @@
{
"type": "unicopia:crafting_spell",
"ingredients": [
{ "id": "unicopia:fire" },
{ "id": "unicopia:shell" },
{ "item": "unicopia:gem", "spell": "shield" },
{ "id": "unicopia:shell" }
],
"result": {
"item": { "item": "unicopia:corrupted_gem" },
"spell": "shield"
}
}

View file

@ -1,12 +0,0 @@
{
"type": "unicopia:crafting_spell",
"ingredients": [
{ "item": "minecraft:fire_charge" },
{ "id": "unicopia:blood" },
{ "item": "unicopia:gem", "spell": "fire" }
],
"result": {
"item": { "item": "unicopia:corrupted_gem" },
"spell": "vortex"
}
}

View file

@ -1,12 +0,0 @@
{
"type": "unicopia:crafting_spell",
"ingredients": [
{ "id": "unicopia:shell" },
{ "item": "unicopia:gem", "spell": "shield" },
{ "item": "unicopia:gem", "spell": "portal" }
],
"result": {
"item": { "item": "unicopia:gem" },
"spell": "vortex"
}
}

View file

@ -1,53 +0,0 @@
{
"type": "minecraft:crafting_shaped",
"pattern": [
"*D~",
"#$#",
" # "
],
"key": {
"#": [
{ "item": "unicopia:corrupted_gem" }
],
"D": [
{ "item": "minecraft:diamond" }
],
"*": [
{ "item": "unicopia:corrupted_gem", "nbt": { "spell": "inferno" } }
],
"$": [
{ "item": "unicopia:corrupted_gem", "nbt": { "spell": "darkness" } }
],
"~": [
{ "item": "unicopia:corrupted_gem", "nbt": { "spell": "necromancy" } }
]
},
"result": { "item": "unicopia:alicorn_amulet" }
}

View file

@ -19,5 +19,5 @@
{ "item": "minecraft:apple" }
]
},
"result": { "item": "unicopia:apple_cider", "data": 0, "count": 1 }
"result": { "item": "unicopia:apple_cider" }
}

View file

@ -16,5 +16,5 @@
{ "item": "minecraft:leather" }
]
},
"result": { "item": "unicopia:bag_of_holding", "data": 0, "count": 1 }
"result": { "item": "unicopia:bag_of_holding" }
}

View file

@ -10,7 +10,7 @@
{ "item": "unicopia:sugar_block" }
],
"*": [
{ "item": "minecraft:dye", "data": 9 }
{ "item": "minecraft:pink_dye" }
]
},
"result": { "item": "unicopia:bakery_door", "count": 3 }

View file

@ -0,0 +1,17 @@
{
"type": "minecraft:crafting_shaped",
"pattern": [
"###",
"#*#",
"###"
],
"key": {
"#": [
{ "item": "unicopia:sugar_block" }
],
"*": [
{ "item": "unicopia:crereal" }
]
},
"result": { "item": "unicopia:boop_o_roops" }
}

View file

@ -0,0 +1,9 @@
{
"type": "smelting",
"ingredient": {
"item": "unicopia:juice"
},
"result": "unicopia:burned_juice",
"experience": 0,
"cookingtime": 100
}

View file

@ -6,5 +6,5 @@
{ "item": "unicopia:alfalfa_leaves" },
{ "item": "minecraft:milk_bucket" }
],
"result": { "item": "unicopia:cereal", "data": 0, "count": 1 }
"result": { "item": "unicopia:cereal" }
}

View file

@ -10,5 +10,5 @@
{ "item": "unicopia:chitin_block" }
]
},
"result": { "item": "unicopia:chissled_chitin", "count": 4 }
"result": { "item": "unicopia:chiseled_chitin_shell_block", "count": 4 }
}

View file

@ -0,0 +1,9 @@
{
"type": "smelting",
"ingredient": {
"item": "unicopia:slime_drop"
},
"result": "unicopia:chitin_shell",
"experience": 0.3,
"cookingtime": 130
}

View file

@ -11,5 +11,5 @@
{ "item": "unicopia:chitin_shell" }
]
},
"result": { "item": "unicopia:chitin_block", "count": 1 }
"result": { "item": "unicopia:chitin_shell_block" }
}

View file

@ -0,0 +1,7 @@
{
"type": "minecraft:crafting_shapeless",
"ingredients": [
{ "item": "unicopia:chitin_shell_block" }
],
"result": { "item": "unicopia:chitin_shell", "count": 9 }
}

View file

@ -1,12 +0,0 @@
{
"type": "minecraft:crafting_shaped",
"pattern": [
"BBB"
],
"key": {
"B": [
{ "item": "unicopia:enchanted_cloud_block" }
]
},
"result": { "item": "unicopia:cloud_banister", "count": 3 }
}

View file

@ -1,9 +1,8 @@
{
"type": "minecraft:crafting_shaped",
"pattern": [
"###",
"###",
"###"
"##",
"##"
],
"key": {
"#": [

View file

@ -0,0 +1,7 @@
{
"type": "minecraft:crafting_shapeless",
"ingredients": [
{ "item": "unicopia:cloud_block" }
],
"result": { "item": "unicopia:cloud_matter", "count": 4 }
}

View file

@ -13,5 +13,5 @@
{ "item": "unicopia:cloud_matter" }
]
},
"result": { "item": "unicopia:construction_cloud_spawner", "count": 1 }
"result": { "item": "unicopia:construction_cloud_spawner" }
}

View file

@ -0,0 +1,9 @@
{
"type": "smelting",
"ingredient": {
"item": "unicopia:zap_apple"
},
"result": "unicopia:cooked_zap_apple",
"experience": 0.2,
"cookingtime": 430
}

View file

@ -9,5 +9,5 @@
{ "item": "unicopia:cloud_block" }
]
},
"result": { "item": "unicopia:packed_cloud_block", "count": 1 }
"result": { "item": "unicopia:dense_cloud_block", "count": 1 }
}

View file

@ -0,0 +1,12 @@
{
"type": "minecraft:crafting_shaped",
"pattern": [
"###"
],
"key": {
"#": [
{ "item": "unicopia:dense_cloud_block" }
]
},
"result": { "item": "unicopia:dense_cloud_slab", "count": 6 }
}

View file

@ -15,35 +15,7 @@
"*": [
{
"item": "minecraft:enchanted_book",
"nbt": {
"ench": [
{ "id": 2, "lvl": 1 }
]
}
},
{
"item": "minecraft:enchanted_book",
"nbt": {
"ench": [
{ "id": 2, "lvl": 2 }
]
}
},
{
"item": "minecraft:enchanted_book",
"nbt": {
"ench": [
{ "id": 2, "lvl": 3 }
]
}
},
{
"item": "minecraft:enchanted_book",
"nbt": {
"ench": [
{ "id": 2, "lvl": 4 }
]
}
"ench": "minecraft:feather_falling"
}
]
},

View file

@ -12,5 +12,5 @@
{ "item": "unicopia:gem", "nbt": { "spell": "light" } }
]
},
"result": { "item": "unicopia:enchanted_torch", "count": 1 }
"result": { "item": "unicopia:enchanted_torch" }
}

View file

@ -0,0 +1,9 @@
{
"type": "unicopia:shapeless_crafting_spell",
"ingredients": [
{ "item": "unicopia:gem", "spell": "inferno" },
{ "item": "unicopia:gem", "spell": "darkness" },
{ "item": "unicopia:gem", "spell": "necromancy" }
],
"result": { "item": "unicopia:alicorn_amulet" }
}

View file

@ -0,0 +1,16 @@
{
"type": "unicopia:enchanting_spell",
"input": { "item": "unicopia:gem" },
"ingredients": [
{ "tag": "#unicopia:unaligned" },
{ "tag": "#unicopia:unaligned" },
{ "tag": "#unicopia:unaligned" }
],
"result": {
"item": [
{ "item": "unicopia:gem" },
{ "item": "unicopia:corrupted_gem" }
],
"spell": "awkward"
}
}

View file

@ -0,0 +1,10 @@
{
"type": "unicopia:enchanting_spell",
"input": { "item": "unicopia:gem" },
"ingredients": [
{ "tag": "unicopia:magic_energetic" },
{ "item": "unicopia:gem", "spell": "fire" },
{ "tag": "unicopia:magic_firey" }
],
"result": { "item": "unicopia:gem", "spell": "charge" }
}

View file

@ -1,13 +1,11 @@
{
"type": "unicopia:crafting_spell",
"type": "unicopia:enchanting_spell",
"input": { "item": "unicopia:gem" },
"ingredients": [
{ "item": "unicopia:gem", "spell": "charge" },
{ "item": "unicopia:corrupted_gem" },
{ "id": "unicopia:life" },
{ "tag": "unicopia:life" },
{ "item": "minecraft:red_flower", "data": 0 }
],
"result": {
"item": { "item": "unicopia:gem" },
"spell": "drake"
}
"result": { "item": "unicopia:gem", "spell": "drake" }
}

View file

@ -0,0 +1,10 @@
{
"type": "unicopia:enchanting_spell",
"input": { "item": "unicopia:gem" },
"ingredients": [
{ "item": "unicopia:gem", "spell": "flame" },
{ "tag": "unicopia:fire" },
{ "tag": "unicopia:fire" }
],
"result": { "item": "unicopia:gem", "spell": "fire" }
}

View file

@ -0,0 +1,10 @@
{
"type": "unicopia:enchanting_spell",
"input": { "item": "unicopia:gem" },
"ingredients": [
{ "tag": "unicopia:fire" },
{ "tag": "unicopia:fire" },
{ "tag": "unicopia:fire" }
],
"result": { "item": "unicopia:gem", "spell": "fire" }
}

View file

@ -0,0 +1,10 @@
{
"type": "unicopia:enchanting_spell",
"input": { "item": "unicopia:gem" },
"ingredients": [
{ "tag": "unicopia:ice" },
{ "tag": "unicopia:ice" },
{ "tag": "unicopia:ice" }
],
"result": { "item": "unicopia:gem", "spell": "ice" }
}

View file

@ -0,0 +1,10 @@
{
"type": "unicopia:enchanting_spell",
"input": { "item": "unicopia:gem" },
"ingredients": [
{ "item": "unicopia:gem", "spell": "fire" },
{ "tag": "unicopia:fire" },
{ "tag": "unicopia:fire" }
],
"result": { "item": "unicopia:corrupted_gem", "spell": "inferno" }
}

View file

@ -1,7 +1,8 @@
{
"type": "unicopia:crafting_spell",
"type": "unicopia:enchanting_spell",
"input": { "item": "unicopia:gem" },
"ingredients": [
{ "id": "unicopia:light" },
{ "tag": "unicopia:light" },
{ "item": "unicopia:gem", "spell": "fire" },
[
{ "item": "minecraft:apple" },
@ -10,8 +11,5 @@
{ "item": "unicopia:apple_sour" }
]
],
"result": {
"item": { "item": "unicopia:gem" },
"spell": "light"
}
"result": { "item": "unicopia:gem", "spell": "light" }
}

View file

@ -0,0 +1,12 @@
{
"type": "unicopia:enchanting_spell",
"input": { "tag": "unicopia:sound"},
"ingredients": [
{ "tag": "unicopia:apple_bloom" },
{ "tag": "unicopia:scootaloo" },
{ "tag": "unicopia:sweetie_belle" }
],
"output": {
"item": "unicopia:music_disc_crusade"
}
}

View file

@ -0,0 +1,12 @@
{
"type": "unicopia:enchanting_spell",
"input": { "tag": "unicopia:sound"},
"ingredients": [
{ "item": "minecraft:diamond" },
{ "item": "minecraft:diamond" },
{ "item": "unicopia:boop_o_roops" }
],
"output": {
"item": "unicopia:music_disc_funk"
}
}

View file

@ -1,16 +1,12 @@
{
"type": "unicopia:crafting_special",
"type": "unicopia:enchanting_spell",
"input": { "tag": "unicopia:sound"},
"ingredients": [
{ "item": "unicopia:gem", "spell": "awkward" },
{ "item": "minecraft:feather" },
{ "item": "minecraft:carrot" }
],
"input": {
"item": [
{ "id": "unicopia:sound" }
]
},
"output": {
"item": { "item": "unicopia:record_pet" }
"item": "unicopia:music_disc_pet"
}
}

View file

@ -1,16 +1,12 @@
{
"type": "unicopia:crafting_special",
"type": "unicopia:enchanting_spell",
"input": { "tag": "unicopia:sound"},
"ingredients": [
{ "item": "minecraft:diamond" },
{ "item": "minecraft:diamond" },
{ "item": "minecraft:diamond" }
],
"input": {
"item": [
{ "id": "unicopia:sound"}
]
},
"output": {
"item": { "item": "unicopia:record_popular" }
"item": "unicopia:music_disc_popular"
}
}

View file

@ -1,16 +1,12 @@
{
"type": "unicopia:crafting_special",
"type": "unicopia:enchanting_spell",
"input": { "tag": "unicopia:sound"},
"ingredients": [
{ "item": "unicopia:gem", "spell": "awkward" },
{ "item": "unicopia:gem", "spell": "awkward" },
{ "item": "unicopia:gem", "spell": "awkward" }
],
"input": {
"item": [
{ "id": "unicopia:sound"}
]
},
"output": {
"item": { "id": "unicopia:sound" }
"tag": "unicopia:sound"
}
}

View file

@ -0,0 +1,13 @@
{
"type": "unicopia:enchanting_spell",
"input": { "item": "unicopia:gem" },
"ingredients": [
{ "tag": "unicopia:blood" },
{ "tag": "unicopia:energy" },
{ "tag": "unicopia:rot" }
],
"result": {
"item": "unicopia:corrupted_gem",
"spell": "necromancy"
}
}

View file

@ -0,0 +1,10 @@
{
"type": "unicopia:enchanting_spell",
"input": { "item": "unicopia:gem" },
"ingredients": [
{ "tag": "unicopia:energy" },
{ "tag": "unicopia:life" },
{ "item": "unicopia:gem", "spell": "charge" }
],
"result": { "item": "unicopia:gem", "spell": "siphon" }
}

View file

@ -0,0 +1,11 @@
{
"type": "unicopia:enchanting_spell",
"input": { "item": "unicopia:gem" },
"ingredients": [
{ "tag": "unicopia:sight" },
{ "item": "minecraft:ghast_tear" },
{ "tag": "unicopia:energy" },
{ "item": "unicopia:gem", "spell": "fire" }
],
"result": { "item": "unicopia:gem", "spell": "portal" }
}

View file

@ -0,0 +1,14 @@
{
"type": "unicopia:enchanting_spell",
"input": { "item": "unicopia:gem" },
"ingredients": [
{ "tag": "unicopia:fire" },
{ "tag": "unicopia:shell" },
{ "item": "unicopia:gem", "spell": "shield" },
{ "tag": "unicopia:shell" }
],
"result": {
"item": "unicopia:corrupted_gem",
"spell": "shield"
}
}

View file

@ -1,12 +1,10 @@
{
"type": "unicopia:crafting_spell",
"type": "unicopia:enchanting_spell",
"input": { "item": "unicopia:gem" },
"ingredients": [
{ "item": "unicopia:gem", "spell": "light" },
{ "item": "unicopia:gem", "spell": "charge" },
{ "item": "unicopia:gem", "spell": "light" }
],
"result": {
"item": { "item": "unicopia:gem" },
"spell": "reveal"
}
"result": { "item": "unicopia:gem", "spell": "reveal" }
}

View file

@ -1,12 +1,10 @@
{
"type": "unicopia:crafting_spell",
"type": "unicopia:enchanting_spell",
"input": { "item": "unicopia:gem" },
"ingredients": [
{ "id": "unicopia:shell" },
{ "id": "unicopia:shell" },
{ "id": "unicopia:shard" }
],
"result": {
"item": { "item": "unicopia:gem" },
"spell": "shield"
}
"result": { "item": "unicopia:gem", "spell": "shield" }
}

View file

@ -1,15 +1,11 @@
{
"type": "unicopia:crafting_spell",
"type": "unicopia:enchanting_spell",
"input": { "item": "unicopia:gem" },
"ingredients": [
{ "id": "unicopia:energy" },
{ "id": "unicopia:life" },
{ "id": "unicopia:dark" },
{ "item": "unicopia:gem", "spell": "siphon" }
],
"result": {
"item": [
{ "item": "unicopia:corrupted_gem" }
],
"spell": "siphon"
}
"result": { "item": "unicopia:corrupted_gem", "spell": "siphon" }
}

View file

@ -0,0 +1,10 @@
{
"type": "unicopia:enchanting_spell",
"input": { "item": "unicopia:gem" },
"ingredients": [
{ "item": "minecraft:fire_charge" },
{ "tag": "unicopia:blood" },
{ "item": "unicopia:gem", "spell": "fire" }
],
"result": { "item": "unicopia:corrupted_gem", "spell": "vortex" }
}

View file

@ -0,0 +1,10 @@
{
"type": "unicopia:enchanting_spell",
"input": { "item": "unicopia:gem" },
"ingredients": [
{ "tag": "unicopia:shell" },
{ "item": "unicopia:gem", "spell": "shield" },
{ "item": "unicopia:gem", "spell": "portal" }
],
"result": { "item": "unicopia:gem", "spell": "vortex" }
}

View file

@ -11,14 +11,14 @@
{ "item": "unicopia:mug" }
],
"J": [
{ "item": "unicopia:juice", "data": 0 }
{ "item": "unicopia:juice" }
],
"B": [
{ "item": "unicopia:burned_juice", "data": 0 }
{ "item": "unicopia:burned_juice" }
],
"A": [
{ "item": "minecraft:apple" }
]
},
"result": { "item": "unicopia:apple_cider", "data": 0, "count": 1 }
"result": { "item": "unicopia:apple_cider" }
}

View file

@ -1,14 +1,20 @@
{
"type": "minecraft:crafting_shaped",
"pattern": [
" # ",
"###",
" # "
"SCB",
"CSC",
"BCS"
],
"key": {
"#": [
{ "item": "unicopia:corrupted_gem" }
"S": [
{ "item": "minecraft:andesite" }
],
"C": [
{ "item": "#minecraft:stained_hardened_clay" }
],
"B": [
{ "item": "minecraft:black_dye" }
]
},
"result": { "item": "unicopia:gem", "count": 1 }
"result": { "item": "unicopia:gem", "count": 4 }
}

View file

@ -1,35 +0,0 @@
{
"type": "minecraft:crafting_shaped",
"pattern": [
"SCB",
"CSC",
"BCS"
],
"key": {
"S": [
{ "item": "minecraft:stone", "data": 3 }
],
"C": [
{ "item": "minecraft:stained_hardened_clay", "data": 0 },
{ "item": "minecraft:stained_hardened_clay", "data": 1 },
{ "item": "minecraft:stained_hardened_clay", "data": 2 },
{ "item": "minecraft:stained_hardened_clay", "data": 3 },
{ "item": "minecraft:stained_hardened_clay", "data": 4 },
{ "item": "minecraft:stained_hardened_clay", "data": 5 },
{ "item": "minecraft:stained_hardened_clay", "data": 6 },
{ "item": "minecraft:stained_hardened_clay", "data": 7 },
{ "item": "minecraft:stained_hardened_clay", "data": 8 },
{ "item": "minecraft:stained_hardened_clay", "data": 9 },
{ "item": "minecraft:stained_hardened_clay", "data": 10 },
{ "item": "minecraft:stained_hardened_clay", "data": 11 },
{ "item": "minecraft:stained_hardened_clay", "data": 12 },
{ "item": "minecraft:stained_hardened_clay", "data": 13 },
{ "item": "minecraft:stained_hardened_clay", "data": 14 },
{ "item": "minecraft:stained_hardened_clay", "data": 15 }
],
"B": [
{ "item": "minecraft:dye", "data": 15 }
]
},
"result": { "item": "unicopia:gem", "count": 4 }
}

Some files were not shown because too many files have changed in this diff Show more