-
Notifications
You must be signed in to change notification settings - Fork 95
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Includes: * ResourceLocation * Registry loadables for any vanilla registry we might reasonably use, plus helpers to create more * Tag key loadables for common tag types * TagCompound for raw NBT fields * ItemStack and FluidStack (with notably advantages over the recipe helper methods) * Ingredient and FluidIngredient (with the ability to allow or reject empty) * ItemOutput In addition, GenericLoaderRegistry and NamedComponentRegistry both implement loadable so they can be used in other builders
- Loading branch information
1 parent
82ad93b
commit d690781
Showing
13 changed files
with
755 additions
and
65 deletions.
There are no files selected for viewing
67 changes: 67 additions & 0 deletions
67
src/main/java/slimeknights/mantle/data/loadable/Loadables.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
package slimeknights.mantle.data.loadable; | ||
|
||
import net.minecraft.ResourceLocationException; | ||
import net.minecraft.core.Registry; | ||
import net.minecraft.core.particles.ParticleType; | ||
import net.minecraft.resources.ResourceKey; | ||
import net.minecraft.resources.ResourceLocation; | ||
import net.minecraft.sounds.SoundEvent; | ||
import net.minecraft.tags.TagKey; | ||
import net.minecraft.world.effect.MobEffect; | ||
import net.minecraft.world.entity.EntityType; | ||
import net.minecraft.world.entity.ai.attributes.Attribute; | ||
import net.minecraft.world.item.Item; | ||
import net.minecraft.world.item.alchemy.Potion; | ||
import net.minecraft.world.item.enchantment.Enchantment; | ||
import net.minecraft.world.level.block.Block; | ||
import net.minecraft.world.level.block.entity.BlockEntityType; | ||
import net.minecraft.world.level.material.Fluid; | ||
import slimeknights.mantle.data.loadable.common.RegistryLoadable; | ||
import slimeknights.mantle.data.loadable.primitive.StringLoadable; | ||
|
||
/** Various loadable instances provided by this mod */ | ||
@SuppressWarnings({"deprecation", "unused"}) | ||
public class Loadables { | ||
private Loadables() {} | ||
|
||
/** Loadable for a resource location */ | ||
public static final Loadable<ResourceLocation> RESOURCE_LOCATION = StringLoadable.DEFAULT.map((s, e) -> { | ||
try { | ||
return new ResourceLocation(s); | ||
} catch (ResourceLocationException ex) { | ||
throw e.create(ex); | ||
} | ||
}, (r, e) -> r.toString()); | ||
|
||
/* Registries */ | ||
public static final Loadable<SoundEvent> SOUND_EVENT = new RegistryLoadable<>(Registry.SOUND_EVENT); | ||
public static final Loadable<Fluid> FLUID = new RegistryLoadable<>(Registry.FLUID); | ||
public static final Loadable<MobEffect> MOB_EFFECT = new RegistryLoadable<>(Registry.MOB_EFFECT); | ||
public static final Loadable<Block> BLOCK = new RegistryLoadable<>(Registry.BLOCK); | ||
public static final Loadable<Enchantment> ENCHANTMENT = new RegistryLoadable<>(Registry.ENCHANTMENT); | ||
public static final Loadable<EntityType<?>> ENTITY_TYPE = new RegistryLoadable<>(Registry.ENTITY_TYPE); | ||
public static final Loadable<Item> ITEM = new RegistryLoadable<>(Registry.ITEM); | ||
public static final Loadable<Potion> POTION = new RegistryLoadable<>(Registry.POTION); | ||
public static final Loadable<ParticleType<?>> PARTICLE_TYPE = new RegistryLoadable<>(Registry.PARTICLE_TYPE); | ||
public static final Loadable<BlockEntityType<?>> BLOCK_ENTITY_TYPE = new RegistryLoadable<>(Registry.BLOCK_ENTITY_TYPE); | ||
public static final Loadable<Attribute> ATTRIBUTE = new RegistryLoadable<>(Registry.ATTRIBUTE); | ||
|
||
|
||
/* Tag keys */ | ||
public static final Loadable<TagKey<Fluid>> FLUID_TAG = tagKey(Registry.FLUID_REGISTRY); | ||
public static final Loadable<TagKey<MobEffect>> MOB_EFFECT_TAG = tagKey(Registry.MOB_EFFECT_REGISTRY); | ||
public static final Loadable<TagKey<Block>> BLOCK_TAG = tagKey(Registry.BLOCK_REGISTRY); | ||
public static final Loadable<TagKey<Enchantment>> ENCHANTMENT_TAG = tagKey(Registry.ENCHANTMENT_REGISTRY); | ||
public static final Loadable<TagKey<EntityType<?>>> ENTITY_TYPE_TAG = tagKey(Registry.ENTITY_TYPE_REGISTRY); | ||
public static final Loadable<TagKey<Item>> ITEM_TAG = tagKey(Registry.ITEM_REGISTRY); | ||
public static final Loadable<TagKey<Potion>> POTION_TAG = tagKey(Registry.POTION_REGISTRY); | ||
public static final Loadable<TagKey<BlockEntityType<?>>> BLOCK_ENTITY_TYPE_TAG = tagKey(Registry.BLOCK_ENTITY_TYPE_REGISTRY); | ||
|
||
|
||
/* Helpers */ | ||
|
||
/** Creates a tag key loadable */ | ||
public static <T> Loadable<TagKey<T>> tagKey(ResourceKey<? extends Registry<T>> registry) { | ||
return RESOURCE_LOCATION.flatMap(key -> TagKey.create(registry, key), TagKey::location); | ||
} | ||
} |
34 changes: 34 additions & 0 deletions
34
src/main/java/slimeknights/mantle/data/loadable/common/CodecLoadable.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
package slimeknights.mantle.data.loadable.common; | ||
|
||
import com.google.gson.JsonElement; | ||
import com.google.gson.JsonSyntaxException; | ||
import com.mojang.serialization.Codec; | ||
import com.mojang.serialization.JsonOps; | ||
import io.netty.handler.codec.DecoderException; | ||
import io.netty.handler.codec.EncoderException; | ||
import net.minecraft.network.FriendlyByteBuf; | ||
import slimeknights.mantle.data.loadable.ErrorFactory; | ||
import slimeknights.mantle.data.loadable.Loadable; | ||
|
||
/** Implementation of a loadable using a codec. Note this will be inefficient when reading from and writing to the network */ | ||
public record CodecLoadable<T>(Codec<T> codec) implements Loadable<T> { | ||
@Override | ||
public T convert(JsonElement element, String key) throws JsonSyntaxException { | ||
return codec.parse(JsonOps.INSTANCE, element).getOrThrow(false, ErrorFactory.JSON_SYNTAX_ERROR); | ||
} | ||
|
||
@Override | ||
public JsonElement serialize(T object) throws RuntimeException { | ||
return codec.encodeStart(JsonOps.INSTANCE, object).getOrThrow(false, ErrorFactory.RUNTIME); | ||
} | ||
|
||
@Override | ||
public T fromNetwork(FriendlyByteBuf buffer) throws DecoderException { | ||
return buffer.readWithCodec(codec); | ||
} | ||
|
||
@Override | ||
public void toNetwork(T object, FriendlyByteBuf buffer) throws EncoderException { | ||
buffer.writeWithCodec(codec, object); | ||
} | ||
} |
115 changes: 115 additions & 0 deletions
115
src/main/java/slimeknights/mantle/data/loadable/common/FluidStackLoadable.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,115 @@ | ||
package slimeknights.mantle.data.loadable.common; | ||
|
||
import com.google.gson.JsonElement; | ||
import com.google.gson.JsonNull; | ||
import com.google.gson.JsonObject; | ||
import com.google.gson.JsonSyntaxException; | ||
import io.netty.handler.codec.EncoderException; | ||
import lombok.RequiredArgsConstructor; | ||
import net.minecraft.nbt.CompoundTag; | ||
import net.minecraft.network.FriendlyByteBuf; | ||
import net.minecraft.util.GsonHelper; | ||
import net.minecraft.world.level.material.Fluid; | ||
import net.minecraft.world.level.material.Fluids; | ||
import net.minecraftforge.fluids.FluidStack; | ||
import slimeknights.mantle.data.loadable.Loadables; | ||
import slimeknights.mantle.data.loadable.record.RecordLoadable; | ||
|
||
/** Loadable for a fluid stack */ | ||
@RequiredArgsConstructor | ||
public enum FluidStackLoadable implements RecordLoadable<FluidStack> { | ||
/** Loads a non-empty fluid stack, ignoring NBT */ | ||
NON_EMPTY(false, true), | ||
/** Loads a non-empty fluid stack, including NBT */ | ||
NON_EMPTY_NBT(true, true), | ||
/** Loads a fluid stack that may be empty, ignoring NBT */ | ||
EMPTY(false, false), | ||
/** Loads a fluid stack that may be empty, including NBT */ | ||
EMPTY_NBT(true, false); | ||
|
||
/** If true, we read NBT */ | ||
private final boolean readNBT; | ||
/** If true, we disallow reading empty stacks */ | ||
private final boolean disallowEmpty; | ||
|
||
@Override | ||
public FluidStack convert(JsonElement element, String key) { | ||
if (!disallowEmpty && element.isJsonNull()) { | ||
return FluidStack.EMPTY; | ||
} | ||
return convert(element, key); | ||
} | ||
|
||
/** Deserializes this stack from an object */ | ||
@Override | ||
public FluidStack deserialize(JsonObject json) { | ||
Fluid fluid = Fluids.EMPTY; | ||
// if we disallow empty, force parsing the fluid so we get a missing field error | ||
// item field is optional if we allow empty | ||
if (json.has("fluid") || disallowEmpty) { | ||
fluid = Loadables.FLUID.getAndDeserialize(json, "fluid"); | ||
} | ||
// air may come from the default or the registry, either is disallowed if we disallow empty | ||
if (fluid == Fluids.EMPTY) { | ||
if (disallowEmpty) { | ||
throw new JsonSyntaxException("FluidStack may not be empty"); | ||
} | ||
return FluidStack.EMPTY; | ||
} | ||
// we handle empty via item, so amount is not even considered, thus amount of 0 is invalid | ||
int amount = GsonHelper.getAsInt(json, "amount"); | ||
if (amount <= 0) { | ||
throw new JsonSyntaxException("FluidStack amount must greater than 0"); | ||
} | ||
CompoundTag tag = null; | ||
if (readNBT && json.has("nbt")) { | ||
tag = NBTLoadable.ALLOW_STRING.convert(json.get("nbt"), "nbt"); | ||
} | ||
return new FluidStack(fluid, amount, tag); | ||
} | ||
|
||
@Override | ||
public FluidStack getAndDeserialize(JsonObject parent, String key) { | ||
if (!disallowEmpty && !parent.has(key)) { | ||
return FluidStack.EMPTY; | ||
} | ||
return RecordLoadable.super.getAndDeserialize(parent, key); | ||
} | ||
|
||
@Override | ||
public JsonElement serialize(FluidStack stack) { | ||
if (stack.isEmpty()) { | ||
if (disallowEmpty) { | ||
throw new IllegalArgumentException("FluidStack must not be empty"); | ||
} | ||
return JsonNull.INSTANCE; | ||
} | ||
return RecordLoadable.super.serialize(stack); | ||
} | ||
|
||
@Override | ||
public void serialize(FluidStack stack, JsonObject json) { | ||
if (stack.isEmpty()) { | ||
if (disallowEmpty) { | ||
throw new IllegalArgumentException("FluidStack must not be empty"); | ||
} | ||
return; | ||
} | ||
json.add("fluid", Loadables.FLUID.serialize(stack.getFluid())); | ||
json.addProperty("amount", stack.getAmount()); | ||
CompoundTag tag = readNBT ? stack.getTag() : null; | ||
if (tag != null) { | ||
json.add("nbt", NBTLoadable.ALLOW_STRING.serialize(tag)); | ||
} | ||
} | ||
|
||
@Override | ||
public FluidStack fromNetwork(FriendlyByteBuf buffer) { | ||
return FluidStack.readFromPacket(buffer); | ||
} | ||
|
||
@Override | ||
public void toNetwork(FluidStack stack, FriendlyByteBuf buffer) throws EncoderException { | ||
stack.writeToPacket(buffer); | ||
} | ||
} |
55 changes: 55 additions & 0 deletions
55
src/main/java/slimeknights/mantle/data/loadable/common/IngredientLoadable.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
package slimeknights.mantle.data.loadable.common; | ||
|
||
import com.google.gson.JsonElement; | ||
import com.google.gson.JsonNull; | ||
import com.google.gson.JsonObject; | ||
import com.google.gson.JsonSyntaxException; | ||
import io.netty.handler.codec.DecoderException; | ||
import io.netty.handler.codec.EncoderException; | ||
import net.minecraft.network.FriendlyByteBuf; | ||
import net.minecraft.world.item.crafting.Ingredient; | ||
import slimeknights.mantle.data.loadable.Loadable; | ||
|
||
/** Loadable for ingredients, handling Forge ingredients */ | ||
public enum IngredientLoadable implements Loadable<Ingredient> { | ||
ALLOW_EMPTY, | ||
DISALLOW_EMPTY; | ||
|
||
@Override | ||
public Ingredient getAndDeserialize(JsonObject parent, String key) { | ||
if (this == ALLOW_EMPTY && !parent.has(key)) { | ||
return Ingredient.EMPTY; | ||
} | ||
return Loadable.super.getAndDeserialize(parent, key); | ||
} | ||
|
||
@Override | ||
public Ingredient convert(JsonElement element, String key) throws JsonSyntaxException { | ||
Ingredient ingredient = Ingredient.fromJson(element); | ||
if (ingredient == Ingredient.EMPTY && this == DISALLOW_EMPTY) { | ||
throw new JsonSyntaxException("Ingredient cannot be empty"); | ||
} | ||
return ingredient; | ||
} | ||
|
||
@Override | ||
public JsonElement serialize(Ingredient object) throws RuntimeException { | ||
if (object == Ingredient.EMPTY) { | ||
if (this == ALLOW_EMPTY) { | ||
return JsonNull.INSTANCE; | ||
} | ||
throw new IllegalArgumentException("Ingredient cannot be empty"); | ||
} | ||
return object.toJson(); | ||
} | ||
|
||
@Override | ||
public Ingredient fromNetwork(FriendlyByteBuf buffer) throws DecoderException { | ||
return Ingredient.fromNetwork(buffer); | ||
} | ||
|
||
@Override | ||
public void toNetwork(Ingredient object, FriendlyByteBuf buffer) throws EncoderException { | ||
object.toNetwork(buffer); | ||
} | ||
} |
Oops, something went wrong.