
Added the original 'wayoftime' folder back, so see if that fixed the multiple folder issue.
385 lines
No EOL
10 KiB
Java
385 lines
No EOL
10 KiB
Java
package wayoftime.bloodmagic.api.event.recipes;
|
|
|
|
import java.util.ArrayList;
|
|
import java.util.Arrays;
|
|
import java.util.Collections;
|
|
import java.util.List;
|
|
import java.util.Objects;
|
|
|
|
import javax.annotation.Nonnull;
|
|
import javax.annotation.Nullable;
|
|
|
|
import com.google.gson.JsonArray;
|
|
import com.google.gson.JsonElement;
|
|
import com.google.gson.JsonObject;
|
|
import com.google.gson.JsonParseException;
|
|
import com.google.gson.JsonSyntaxException;
|
|
|
|
import net.minecraft.fluid.Fluid;
|
|
import net.minecraft.network.PacketBuffer;
|
|
import net.minecraft.tags.FluidTags;
|
|
import net.minecraft.tags.ITag;
|
|
import net.minecraft.tags.TagCollectionManager;
|
|
import net.minecraft.util.JSONUtils;
|
|
import net.minecraft.util.ResourceLocation;
|
|
import net.minecraftforge.fluids.FluidStack;
|
|
import wayoftime.bloodmagic.api.SerializerHelper;
|
|
import wayoftime.bloodmagic.util.Constants;
|
|
|
|
/**
|
|
* Created by Thiakil on 12/07/2019.
|
|
*/
|
|
public abstract class FluidStackIngredient implements InputIngredient<FluidStack>
|
|
{
|
|
|
|
public static FluidStackIngredient from(@Nonnull Fluid instance, int amount)
|
|
{
|
|
return from(new FluidStack(instance, amount));
|
|
}
|
|
|
|
public static FluidStackIngredient from(@Nonnull FluidStack instance)
|
|
{
|
|
return new Single(instance);
|
|
}
|
|
|
|
public static FluidStackIngredient from(@Nonnull ITag<Fluid> fluidTag, int minAmount)
|
|
{
|
|
return new Tagged(fluidTag, minAmount);
|
|
}
|
|
|
|
public static FluidStackIngredient read(PacketBuffer buffer)
|
|
{
|
|
// TODO: Allow supporting serialization of different types than just the ones we
|
|
// implement?
|
|
IngredientType type = buffer.readEnumValue(IngredientType.class);
|
|
if (type == IngredientType.SINGLE)
|
|
{
|
|
return Single.read(buffer);
|
|
} else if (type == IngredientType.TAGGED)
|
|
{
|
|
return Tagged.read(buffer);
|
|
}
|
|
return Multi.read(buffer);
|
|
}
|
|
|
|
public static FluidStackIngredient deserialize(@Nullable JsonElement json)
|
|
{
|
|
if (json == null || json.isJsonNull())
|
|
{
|
|
throw new JsonSyntaxException("Ingredient cannot be null");
|
|
}
|
|
if (json.isJsonArray())
|
|
{
|
|
JsonArray jsonArray = json.getAsJsonArray();
|
|
int size = jsonArray.size();
|
|
if (size == 0)
|
|
{
|
|
throw new JsonSyntaxException("Ingredient array cannot be empty, at least one ingredient must be defined");
|
|
} else if (size > 1)
|
|
{
|
|
FluidStackIngredient[] ingredients = new FluidStackIngredient[size];
|
|
for (int i = 0; i < size; i++)
|
|
{
|
|
// Read all the ingredients
|
|
ingredients[i] = deserialize(jsonArray.get(i));
|
|
}
|
|
return createMulti(ingredients);
|
|
}
|
|
// If we only have a single element, just set our json as that so that we don't
|
|
// have to use Multi for efficiency reasons
|
|
json = jsonArray.get(0);
|
|
}
|
|
if (!json.isJsonObject())
|
|
{
|
|
throw new JsonSyntaxException("Expected fluid to be object or array of objects");
|
|
}
|
|
JsonObject jsonObject = json.getAsJsonObject();
|
|
if (jsonObject.has(Constants.JSON.FLUID) && jsonObject.has(Constants.JSON.TAG))
|
|
{
|
|
throw new JsonParseException("An ingredient entry is either a tag or an fluid, not both");
|
|
} else if (jsonObject.has(Constants.JSON.FLUID))
|
|
{
|
|
return from(SerializerHelper.deserializeFluid(jsonObject));
|
|
} else if (jsonObject.has(Constants.JSON.TAG))
|
|
{
|
|
if (!jsonObject.has(Constants.JSON.AMOUNT))
|
|
{
|
|
throw new JsonSyntaxException("Expected to receive a amount that is greater than zero");
|
|
}
|
|
JsonElement count = jsonObject.get(Constants.JSON.AMOUNT);
|
|
if (!JSONUtils.isNumber(count))
|
|
{
|
|
throw new JsonSyntaxException("Expected amount to be a number greater than zero.");
|
|
}
|
|
int amount = count.getAsJsonPrimitive().getAsInt();
|
|
if (amount < 1)
|
|
{
|
|
throw new JsonSyntaxException("Expected amount to be greater than zero.");
|
|
}
|
|
ResourceLocation resourceLocation = new ResourceLocation(JSONUtils.getString(jsonObject, Constants.JSON.TAG));
|
|
ITag<Fluid> tag = TagCollectionManager.getManager().getFluidTags().get(resourceLocation);
|
|
if (tag == null)
|
|
{
|
|
throw new JsonSyntaxException("Unknown fluid tag '" + resourceLocation + "'");
|
|
}
|
|
return from(tag, amount);
|
|
}
|
|
throw new JsonSyntaxException("Expected to receive a resource location representing either a tag or a fluid.");
|
|
}
|
|
|
|
public static FluidStackIngredient createMulti(FluidStackIngredient... ingredients)
|
|
{
|
|
if (ingredients.length == 0)
|
|
{
|
|
// TODO: Throw error
|
|
} else if (ingredients.length == 1)
|
|
{
|
|
return ingredients[0];
|
|
}
|
|
List<FluidStackIngredient> cleanedIngredients = new ArrayList<>();
|
|
for (FluidStackIngredient ingredient : ingredients)
|
|
{
|
|
if (ingredient instanceof Multi)
|
|
{
|
|
// Don't worry about if our inner ingredients are multi as well, as if this is
|
|
// the only external method for
|
|
// creating a multi ingredient, then we are certified they won't be of a higher
|
|
// depth
|
|
cleanedIngredients.addAll(Arrays.asList(((Multi) ingredient).ingredients));
|
|
} else
|
|
{
|
|
cleanedIngredients.add(ingredient);
|
|
}
|
|
}
|
|
// There should be more than a single fluid or we would have split out earlier
|
|
return new Multi(cleanedIngredients.toArray(new FluidStackIngredient[0]));
|
|
}
|
|
|
|
public static class Single extends FluidStackIngredient
|
|
{
|
|
|
|
@Nonnull
|
|
private final FluidStack fluidInstance;
|
|
|
|
public Single(@Nonnull FluidStack fluidInstance)
|
|
{
|
|
this.fluidInstance = Objects.requireNonNull(fluidInstance);
|
|
}
|
|
|
|
@Override
|
|
public boolean test(@Nonnull FluidStack fluidStack)
|
|
{
|
|
return testType(fluidStack) && fluidStack.getAmount() >= fluidInstance.getAmount();
|
|
}
|
|
|
|
@Override
|
|
public boolean testType(@Nonnull FluidStack fluidStack)
|
|
{
|
|
return Objects.requireNonNull(fluidStack).isFluidEqual(fluidInstance);
|
|
}
|
|
|
|
@Nonnull
|
|
@Override
|
|
public FluidStack getMatchingInstance(@Nonnull FluidStack fluidStack)
|
|
{
|
|
return test(fluidStack) ? fluidInstance : FluidStack.EMPTY;
|
|
}
|
|
|
|
@Nonnull
|
|
@Override
|
|
public List<FluidStack> getRepresentations()
|
|
{
|
|
return Collections.singletonList(fluidInstance);
|
|
}
|
|
|
|
@Override
|
|
public void write(PacketBuffer buffer)
|
|
{
|
|
buffer.writeEnumValue(IngredientType.SINGLE);
|
|
fluidInstance.writeToPacket(buffer);
|
|
}
|
|
|
|
@Nonnull
|
|
@Override
|
|
public JsonElement serialize()
|
|
{
|
|
JsonObject json = new JsonObject();
|
|
json.addProperty(Constants.JSON.AMOUNT, fluidInstance.getAmount());
|
|
json.addProperty(Constants.JSON.FLUID, fluidInstance.getFluid().getRegistryName().toString());
|
|
if (fluidInstance.hasTag())
|
|
{
|
|
json.addProperty(Constants.JSON.NBT, fluidInstance.getTag().toString());
|
|
}
|
|
return json;
|
|
}
|
|
|
|
public static Single read(PacketBuffer buffer)
|
|
{
|
|
return new Single(FluidStack.readFromPacket(buffer));
|
|
}
|
|
}
|
|
|
|
public static class Tagged extends FluidStackIngredient
|
|
{
|
|
|
|
@Nonnull
|
|
private final ITag<Fluid> tag;
|
|
private final int amount;
|
|
|
|
public Tagged(@Nonnull ITag<Fluid> tag, int amount)
|
|
{
|
|
this.tag = tag;
|
|
this.amount = amount;
|
|
}
|
|
|
|
@Override
|
|
public boolean test(@Nonnull FluidStack fluidStack)
|
|
{
|
|
return testType(fluidStack) && fluidStack.getAmount() >= amount;
|
|
}
|
|
|
|
@Override
|
|
public boolean testType(@Nonnull FluidStack fluidStack)
|
|
{
|
|
return Objects.requireNonNull(fluidStack).getFluid().isIn(tag);
|
|
}
|
|
|
|
@Nonnull
|
|
@Override
|
|
public FluidStack getMatchingInstance(@Nonnull FluidStack fluidStack)
|
|
{
|
|
if (test(fluidStack))
|
|
{
|
|
// Our fluid is in the tag so we make a new stack with the given amount
|
|
return new FluidStack(fluidStack, amount);
|
|
}
|
|
return FluidStack.EMPTY;
|
|
}
|
|
|
|
@Nonnull
|
|
@Override
|
|
public List<FluidStack> getRepresentations()
|
|
{
|
|
// TODO: Can this be cached some how
|
|
List<FluidStack> representations = new ArrayList<>();
|
|
for (Fluid fluid : TagResolverHelper.getRepresentations(tag))
|
|
{
|
|
representations.add(new FluidStack(fluid, amount));
|
|
}
|
|
return representations;
|
|
}
|
|
|
|
@Override
|
|
public void write(PacketBuffer buffer)
|
|
{
|
|
buffer.writeEnumValue(IngredientType.TAGGED);
|
|
buffer.writeResourceLocation(TagCollectionManager.getManager().getFluidTags().getValidatedIdFromTag(tag));
|
|
buffer.writeVarInt(amount);
|
|
}
|
|
|
|
@Nonnull
|
|
@Override
|
|
public JsonElement serialize()
|
|
{
|
|
JsonObject json = new JsonObject();
|
|
json.addProperty(Constants.JSON.AMOUNT, amount);
|
|
json.addProperty(Constants.JSON.TAG, TagCollectionManager.getManager().getFluidTags().getValidatedIdFromTag(tag).toString());
|
|
return json;
|
|
}
|
|
|
|
public static Tagged read(PacketBuffer buffer)
|
|
{
|
|
return new Tagged(FluidTags.makeWrapperTag(buffer.readResourceLocation().toString()), buffer.readVarInt());
|
|
}
|
|
}
|
|
|
|
public static class Multi extends FluidStackIngredient
|
|
{
|
|
|
|
private final FluidStackIngredient[] ingredients;
|
|
|
|
protected Multi(@Nonnull FluidStackIngredient... ingredients)
|
|
{
|
|
this.ingredients = ingredients;
|
|
}
|
|
|
|
@Override
|
|
public boolean test(@Nonnull FluidStack stack)
|
|
{
|
|
return Arrays.stream(ingredients).anyMatch(ingredient -> ingredient.test(stack));
|
|
}
|
|
|
|
@Override
|
|
public boolean testType(@Nonnull FluidStack stack)
|
|
{
|
|
return Arrays.stream(ingredients).anyMatch(ingredient -> ingredient.testType(stack));
|
|
}
|
|
|
|
@Nonnull
|
|
@Override
|
|
public FluidStack getMatchingInstance(@Nonnull FluidStack stack)
|
|
{
|
|
for (FluidStackIngredient ingredient : ingredients)
|
|
{
|
|
FluidStack matchingInstance = ingredient.getMatchingInstance(stack);
|
|
if (!matchingInstance.isEmpty())
|
|
{
|
|
return matchingInstance;
|
|
}
|
|
}
|
|
return FluidStack.EMPTY;
|
|
}
|
|
|
|
@Nonnull
|
|
@Override
|
|
public List<FluidStack> getRepresentations()
|
|
{
|
|
List<FluidStack> representations = new ArrayList<>();
|
|
for (FluidStackIngredient ingredient : ingredients)
|
|
{
|
|
representations.addAll(ingredient.getRepresentations());
|
|
}
|
|
return representations;
|
|
}
|
|
|
|
@Override
|
|
public void write(PacketBuffer buffer)
|
|
{
|
|
buffer.writeEnumValue(IngredientType.MULTI);
|
|
buffer.writeVarInt(ingredients.length);
|
|
for (FluidStackIngredient ingredient : ingredients)
|
|
{
|
|
ingredient.write(buffer);
|
|
}
|
|
}
|
|
|
|
@Nonnull
|
|
@Override
|
|
public JsonElement serialize()
|
|
{
|
|
JsonArray json = new JsonArray();
|
|
for (FluidStackIngredient ingredient : ingredients)
|
|
{
|
|
json.add(ingredient.serialize());
|
|
}
|
|
return json;
|
|
}
|
|
|
|
public static FluidStackIngredient read(PacketBuffer buffer)
|
|
{
|
|
FluidStackIngredient[] ingredients = new FluidStackIngredient[buffer.readVarInt()];
|
|
for (int i = 0; i < ingredients.length; i++)
|
|
{
|
|
ingredients[i] = FluidStackIngredient.read(buffer);
|
|
}
|
|
return createMulti(ingredients);
|
|
}
|
|
}
|
|
|
|
private enum IngredientType
|
|
{
|
|
SINGLE,
|
|
TAGGED,
|
|
MULTI
|
|
}
|
|
} |