Added a method to obtain/transmute various music disks

This commit is contained in:
Sollace 2019-03-09 13:17:26 +02:00
parent 79a5f215de
commit 762636f9bd
17 changed files with 344 additions and 116 deletions

View file

@ -28,6 +28,7 @@ import com.minelittlepony.unicopia.advancements.UAdvancements;
import com.minelittlepony.unicopia.command.Commands; import com.minelittlepony.unicopia.command.Commands;
import com.minelittlepony.unicopia.enchanting.AffineIngredients; import com.minelittlepony.unicopia.enchanting.AffineIngredients;
import com.minelittlepony.unicopia.enchanting.Pages; import com.minelittlepony.unicopia.enchanting.Pages;
import com.minelittlepony.unicopia.enchanting.SpecialRecipe;
import com.minelittlepony.unicopia.enchanting.SpellRecipe; import com.minelittlepony.unicopia.enchanting.SpellRecipe;
import com.minelittlepony.unicopia.forgebullshit.FBS; import com.minelittlepony.unicopia.forgebullshit.FBS;
import com.minelittlepony.unicopia.init.UEntities; import com.minelittlepony.unicopia.init.UEntities;
@ -63,6 +64,7 @@ public class Unicopia implements IGuiHandler {
super.registerRecipeTypes(types); super.registerRecipeTypes(types);
types.put("unicopia:crafting_spell", SpellRecipe::deserialize); types.put("unicopia:crafting_spell", SpellRecipe::deserialize);
types.put("unicopia:crafting_special", SpecialRecipe::deserialize);
AffineIngredients.instance().load(); AffineIngredients.instance().load();
} }

View file

@ -0,0 +1,125 @@
package com.minelittlepony.unicopia.enchanting;
import java.util.ArrayList;
import java.util.List;
import com.google.common.collect.Lists;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParseException;
import com.minelittlepony.unicopia.inventory.InventorySpellBook;
import net.minecraft.inventory.InventoryCrafting;
import net.minecraft.item.ItemStack;
import net.minecraft.item.crafting.IRecipe;
import net.minecraft.util.NonNullList;
import net.minecraft.world.World;
import net.minecraftforge.registries.IForgeRegistryEntry.Impl;
public abstract class AbstractSpecialRecipe extends Impl<IRecipe> implements IRecipe {
private final SpellIngredient spellitem;
private final NonNullList<SpellIngredient> ingredients;
static NonNullList<SpellIngredient> parseIngrediants(JsonObject json) {
NonNullList<SpellIngredient> ingredients = NonNullList.create();
for (JsonElement i : json.get("ingredients").getAsJsonArray()) {
SpellIngredient ingredient = SpellIngredient.parse(i);
if (ingredient != null) {
ingredients.add(ingredient);
}
}
if (ingredients.isEmpty()) {
throw new JsonParseException("Recipe cannot have 0 ingredients");
}
return ingredients;
}
static SpellIngredient parseSingleIngredient(JsonObject json) {
SpellIngredient result = SpellIngredient.parse(json.get("item"));
if (result == null) {
throw new JsonParseException("Recipe cannot have no enchantable input");
}
return result;
}
public AbstractSpecialRecipe(SpellIngredient spellitem, NonNullList<SpellIngredient> ingredients) {
this.spellitem = spellitem;
this.ingredients = ingredients;
}
@Override
public boolean matches(InventoryCrafting inv, World worldIn) {
ItemStack enchantedStack = ((InventorySpellBook)inv).getCraftResultMatrix().getStackInSlot(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.getSizeInventory(); i++) {
ItemStack stack = inv.getStackInSlot(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 ItemStack getCraftingResult(InventoryCrafting inv) {
return getRecipeOutput();
}
@Override
public boolean canFit(int width, int height) {
return width * height < ingredients.size();
}
@Override
public ItemStack getRecipeOutput() {
return spellitem.getStack();
}
@Override
public NonNullList<ItemStack> getRemainingItems(InventoryCrafting inv) {
NonNullList<ItemStack> remainers = NonNullList.<ItemStack>withSize(inv.getSizeInventory(), ItemStack.EMPTY);
for (int i = 0; i < remainers.size(); i++) {
ItemStack stack = inv.getStackInSlot(i);
if (stack != null && stack.getItem().hasContainerItem(stack)) {
remainers.set(i, new ItemStack(stack.getItem().getContainerItem()));
}
}
return remainers;
}
}

View file

@ -32,7 +32,14 @@ public class AffineIngredients {
} }
public SpellIngredient getIngredient(ResourceLocation res) { public SpellIngredient getIngredient(ResourceLocation res) {
return storedIngredients.get(res); SpellIngredient result = storedIngredients.get(res);
if (result == null) {
new RuntimeException("Ingredient `" + res + "` was not found.").printStackTrace();
return SpellIngredient.EMPTY;
}
return result;
} }
protected void handleJson(ResourceLocation id, JsonObject json) throws JsonParseException { protected void handleJson(ResourceLocation id, JsonObject json) throws JsonParseException {
@ -51,6 +58,11 @@ public class AffineIngredients {
this.res = res; this.res = res;
} }
@Override
public ItemStack getStack() {
return instance().getIngredient(res).getStack();
}
@Override @Override
public boolean matches(ItemStack other, int materialMult) { public boolean matches(ItemStack other, int materialMult) {
return instance().getIngredient(res).matches(other, materialMult); return instance().getIngredient(res).matches(other, materialMult);

View file

@ -0,0 +1,30 @@
package com.minelittlepony.unicopia.enchanting;
import com.google.gson.JsonObject;
import net.minecraft.item.ItemStack;
import net.minecraft.item.crafting.IRecipe;
import net.minecraft.util.NonNullList;
public class SpecialRecipe extends AbstractSpecialRecipe {
private final SpellIngredient output;
public static IRecipe deserialize(JsonObject json) {
return new SpecialRecipe(
parseSingleIngredient(json.get("input").getAsJsonObject()),
parseSingleIngredient(json.get("output").getAsJsonObject()),
parseIngrediants(json)
);
}
public SpecialRecipe(SpellIngredient input, SpellIngredient output, NonNullList<SpellIngredient> ingredients) {
super(input, ingredients);
this.output = output;
}
@Override
public ItemStack getRecipeOutput() {
return output.getStack();
}
}

View file

@ -16,6 +16,8 @@ import net.minecraft.item.ItemStack;
public interface SpellIngredient { public interface SpellIngredient {
static SpellIngredient EMPTY = new Single(ItemStack.EMPTY, false);
@Nullable @Nullable
static SpellIngredient parse(JsonElement json) { static SpellIngredient parse(JsonElement json) {
if (json.isJsonArray()) { if (json.isJsonArray()) {
@ -27,6 +29,8 @@ public interface SpellIngredient {
boolean matches(ItemStack other, int materialMult); boolean matches(ItemStack other, int materialMult);
ItemStack getStack();
class Compound implements SpellIngredient { class Compound implements SpellIngredient {
private final List<SpellIngredient> items; private final List<SpellIngredient> items;
@ -34,6 +38,11 @@ public interface SpellIngredient {
this.items = items; this.items = items;
} }
@Override
public ItemStack getStack() {
return items.get((int)(Math.random() * items.size())).getStack();
}
@Override @Override
public boolean matches(ItemStack other, int materialMult) { public boolean matches(ItemStack other, int materialMult) {
return items.stream().anyMatch(item -> item.matches(other, materialMult)); return items.stream().anyMatch(item -> item.matches(other, materialMult));
@ -71,6 +80,11 @@ public interface SpellIngredient {
ignoreMeta = meta; ignoreMeta = meta;
} }
@Override
public ItemStack getStack() {
return contained;
}
@Override @Override
public boolean matches(ItemStack other, int materialMult) { public boolean matches(ItemStack other, int materialMult) {
if (other.isEmpty() != contained.isEmpty()) { if (other.isEmpty() != contained.isEmpty()) {

View file

@ -1,132 +1,47 @@
package com.minelittlepony.unicopia.enchanting; package com.minelittlepony.unicopia.enchanting;
import java.util.ArrayList;
import java.util.List;
import com.google.common.collect.Lists;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject; import com.google.gson.JsonObject;
import com.google.gson.JsonParseException;
import com.minelittlepony.unicopia.init.UItems;
import com.minelittlepony.unicopia.inventory.InventorySpellBook; import com.minelittlepony.unicopia.inventory.InventorySpellBook;
import com.minelittlepony.unicopia.spell.SpellRegistry; import com.minelittlepony.unicopia.spell.SpellRegistry;
import net.minecraft.inventory.IInventory;
import net.minecraft.inventory.InventoryCrafting; import net.minecraft.inventory.InventoryCrafting;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
import net.minecraft.item.crafting.IRecipe; import net.minecraft.item.crafting.IRecipe;
import net.minecraft.util.NonNullList; import net.minecraft.util.NonNullList;
import net.minecraft.world.World;
import net.minecraftforge.registries.IForgeRegistryEntry.Impl; public class SpellRecipe extends AbstractSpecialRecipe {
public class SpellRecipe extends Impl<IRecipe> implements IRecipe {
private final SpellIngredient spellitem;
private final String spellId; private final String spellId;
private final NonNullList<SpellIngredient> ingredients;
public static IRecipe deserialize(JsonObject json) { public static IRecipe deserialize(JsonObject json) {
NonNullList<SpellIngredient> ingredients = NonNullList.create(); JsonObject resultJson = json.get("result").getAsJsonObject();
for (JsonElement i : json.get("ingredients").getAsJsonArray()) { return new SpellRecipe(
SpellIngredient ingredient = SpellIngredient.parse(i); parseSingleIngredient(resultJson),
resultJson.get("spell").getAsString(),
if (ingredient != null) { parseIngrediants(json)
ingredients.add(ingredient); );
}
}
if (ingredients.isEmpty()) {
throw new JsonParseException("Recipe cannot have 0 ingredients");
}
json = json.get("result").getAsJsonObject();
String spellId = json.get("spell").getAsString();
SpellIngredient result = SpellIngredient.parse(json.get("item"));
if (result == null) {
throw new JsonParseException("Recipe cannot have no enchantable input");
}
return new SpellRecipe(result, spellId, ingredients);
} }
public SpellRecipe(SpellIngredient spellitem, String spellName, NonNullList<SpellIngredient> ingredients) { public SpellRecipe(SpellIngredient spellitem, String spellName, NonNullList<SpellIngredient> ingredients) {
this.spellitem = spellitem; super(spellitem, ingredients);
this.spellId = spellName; this.spellId = spellName;
this.ingredients = ingredients;
}
@Override
public boolean matches(InventoryCrafting inv, World worldIn) {
ItemStack enchantedStack = ((InventorySpellBook)inv).getCraftResultMatrix().getStackInSlot(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.getSizeInventory(); i++) {
ItemStack stack = inv.getStackInSlot(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 @Override
public ItemStack getCraftingResult(InventoryCrafting inv) { public ItemStack getCraftingResult(InventoryCrafting inv) {
return getRecipeOutput(); InventorySpellBook inventory = (InventorySpellBook)inv;
}
@Override IInventory craftResult = inventory.getCraftResultMatrix();
public boolean canFit(int width, int height) { ItemStack stackToEnchant = craftResult.getStackInSlot(0);
return width * height < ingredients.size();
return SpellRegistry.instance().enchantStack(stackToEnchant, spellId);
} }
@Override @Override
public ItemStack getRecipeOutput() { public ItemStack getRecipeOutput() {
return SpellRegistry.instance().enchantStack(new ItemStack(UItems.spell, 1), spellId); return SpellRegistry.instance().enchantStack(super.getRecipeOutput(), spellId);
} }
@Override
public NonNullList<ItemStack> getRemainingItems(InventoryCrafting inv) {
NonNullList<ItemStack> remainers = NonNullList.<ItemStack>withSize(inv.getSizeInventory(), ItemStack.EMPTY);
for (int i = 0; i < remainers.size(); i++) {
ItemStack stack = inv.getStackInSlot(i);
if (stack != null && stack.getItem().hasContainerItem(stack)) {
remainers.set(i, new ItemStack(stack.getItem().getContainerItem()));
}
}
return remainers;
}
} }

View file

@ -8,9 +8,9 @@ import com.minelittlepony.unicopia.enchanting.IPageUnlockListener;
import com.minelittlepony.unicopia.inventory.InventorySpellBook; import com.minelittlepony.unicopia.inventory.InventorySpellBook;
import com.minelittlepony.unicopia.inventory.slot.SlotEnchanting; import com.minelittlepony.unicopia.inventory.slot.SlotEnchanting;
import com.minelittlepony.unicopia.inventory.slot.SlotEnchantingResult; import com.minelittlepony.unicopia.inventory.slot.SlotEnchantingResult;
import com.minelittlepony.unicopia.item.ItemSpell;
import com.minelittlepony.unicopia.player.PlayerSpeciesList; import com.minelittlepony.unicopia.player.PlayerSpeciesList;
import com.minelittlepony.unicopia.spell.SpellRegistry; import com.minelittlepony.unicopia.spell.SpellRegistry;
import com.minelittlepony.unicopia.world.UWorld;
import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.InventoryPlayer; import net.minecraft.entity.player.InventoryPlayer;
@ -20,6 +20,7 @@ import net.minecraft.inventory.IInventory;
import net.minecraft.inventory.InventoryBasic; import net.minecraft.inventory.InventoryBasic;
import net.minecraft.inventory.Slot; import net.minecraft.inventory.Slot;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
import net.minecraft.util.EnumParticleTypes;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World; import net.minecraft.world.World;
@ -76,9 +77,30 @@ public class ContainerSpellBook extends Container {
ItemStack crafted = Unicopia.getCraftingManager().findMatchingResult(craftMatrix, worldObj); ItemStack crafted = Unicopia.getCraftingManager().findMatchingResult(craftMatrix, worldObj);
if (!crafted.isEmpty()) { if (!crafted.isEmpty()) {
current = SpellRegistry.instance().enchantStack(current, crafted);
resultSlot.setCrafted(true); resultSlot.setCrafted(true);
if (crafted.getItem() != current.getItem()) {
craftResult.setInventorySlotContents(0, ItemStack.EMPTY);
resultSlot.onTake(player, crafted);
player.dropItem(crafted, true);
player.playSound(SoundEvents.BLOCK_NOTE_SNARE, 1, 1);
worldObj.newExplosion(null, player.posX, player.posY, player.posZ, 0, false, false);
worldObj.newExplosion(null, player.posX, player.posY, player.posZ, 0, false, false);
worldObj.spawnParticle(EnumParticleTypes.EXPLOSION_HUGE, player.posX, player.posY, player.posZ, 1, 0, 0);
UWorld.enqueueTask(w -> {
player.closeScreen();
});
return;
}
current = crafted;
player.playSound(SoundEvents.BLOCK_NOTE_CHIME, 1, 1); player.playSound(SoundEvents.BLOCK_NOTE_CHIME, 1, 1);
} else { } else {
current = SpellRegistry.instance().disenchantStack(current); current = SpellRegistry.instance().disenchantStack(current);
@ -102,7 +124,7 @@ public class ContainerSpellBook extends Container {
stack = slotStack.copy(); stack = slotStack.copy();
if (index > 5) { if (index > 5) {
if (stack.getItem() instanceof ItemSpell) { if (!resultSlot.getHasStack() && resultSlot.isItemValid(stack)) {
if (!mergeItemStack(slotStack, 5, 6, false)) { if (!mergeItemStack(slotStack, 5, 6, false)) {
return ItemStack.EMPTY; return ItemStack.EMPTY;
} }
@ -130,18 +152,14 @@ public class ContainerSpellBook extends Container {
@Override @Override
public void onContainerClosed(EntityPlayer player) { public void onContainerClosed(EntityPlayer player) {
super.onContainerClosed(player); clearContainer(player, worldObj, craftMatrix);
clearContainer(player, worldObj, craftResult);
for (int i = 0; i < craftMatrix.getSizeInventory(); i++) { ItemStack held = player.inventory.getItemStack();
if (craftMatrix.getStackInSlot(i) != null) {
player.dropItem(craftMatrix.getStackInSlot(i), false);
craftMatrix.setInventorySlotContents(i, ItemStack.EMPTY);
}
}
if (craftResult.getStackInSlot(0) != null) { if (!held.isEmpty()) {
player.dropItem(craftResult.getStackInSlot(0), false); player.inventory.setItemStack(ItemStack.EMPTY);
craftResult.setInventorySlotContents(0, ItemStack.EMPTY); player.inventory.placeItemBackInInventory(worldObj, held);
} }
} }

View file

@ -10,6 +10,7 @@ import com.minelittlepony.unicopia.spell.SpellRegistry;
import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.inventory.IInventory; import net.minecraft.inventory.IInventory;
import net.minecraft.item.ItemRecord;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
import net.minecraft.util.NonNullList; import net.minecraft.util.NonNullList;
@ -89,7 +90,8 @@ public class SlotEnchantingResult extends SlotEnchanting {
@Override @Override
public boolean isItemValid(ItemStack stack) { public boolean isItemValid(ItemStack stack) {
return stack.getItem() instanceof ItemSpell && !SpellRegistry.stackHasEnchantment(stack); return (stack.getItem() instanceof ItemSpell || stack.getItem() instanceof ItemRecord)
&& !SpellRegistry.stackHasEnchantment(stack);
} }
@Override @Override

View file

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

View file

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

View file

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

View file

@ -0,0 +1,15 @@
{
"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

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

View file

@ -0,0 +1,16 @@
{
"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

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

View file

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

View file

@ -0,0 +1,16 @@
{
"type": "unicopia:crafting_special",
"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" }
}
}