mirror of
https://github.com/Sollace/Unicopia.git
synced 2024-11-27 15:17:59 +01:00
Move earth ponies' transmutations to recipes
This commit is contained in:
parent
78dbc800ae
commit
d4e698fa56
13 changed files with 296 additions and 77 deletions
|
@ -1,9 +1,6 @@
|
|||
package com.minelittlepony.unicopia.ability;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.function.DoubleSupplier;
|
||||
import java.util.function.Supplier;
|
||||
import com.minelittlepony.unicopia.Race;
|
||||
|
@ -12,12 +9,12 @@ import com.minelittlepony.unicopia.UTags;
|
|||
import com.minelittlepony.unicopia.ability.data.Hit;
|
||||
import com.minelittlepony.unicopia.ability.data.Pos;
|
||||
import com.minelittlepony.unicopia.block.UBlocks;
|
||||
import com.minelittlepony.unicopia.block.state.StateUtil;
|
||||
import com.minelittlepony.unicopia.entity.player.Pony;
|
||||
import com.minelittlepony.unicopia.item.TransformCropsRecipe;
|
||||
import com.minelittlepony.unicopia.item.URecipes;
|
||||
import com.minelittlepony.unicopia.particle.MagicParticleEffect;
|
||||
import com.minelittlepony.unicopia.particle.ParticleUtils;
|
||||
import com.minelittlepony.unicopia.server.world.BlockDestructionManager;
|
||||
import com.minelittlepony.unicopia.server.world.UTreeGen;
|
||||
import com.minelittlepony.unicopia.util.TraceHelper;
|
||||
import com.minelittlepony.unicopia.util.VecHelper;
|
||||
|
||||
|
@ -33,7 +30,6 @@ import net.minecraft.particle.ParticleTypes;
|
|||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.Direction;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
import net.minecraft.util.math.random.Random;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraft.world.WorldEvents;
|
||||
|
||||
|
@ -139,10 +135,11 @@ public class EarthPonyGrowAbility implements Ability<Pos> {
|
|||
}
|
||||
|
||||
private boolean applyDirectly(Pony player, BlockPos pos) {
|
||||
return TransmutationRecipe.RECIPES.stream()
|
||||
.filter(recipe -> recipe.matches(player.asWorld(), pos))
|
||||
return player.asWorld().getRecipeManager()
|
||||
.getAllMatches(URecipes.GROWING, new TransformCropsRecipe.PlacementArea(player, pos), player.asWorld())
|
||||
.stream()
|
||||
.map(recipe -> recipe.checkPattern(player.asWorld(), pos))
|
||||
.filter(result -> result.matchedLocations().size() + 1 >= TransmutationRecipe.MINIMUM_INPUT)
|
||||
.filter(result -> result.matchedLocations().size() + 1 >= TransformCropsRecipe.MINIMUM_INPUT)
|
||||
.filter(result -> {
|
||||
boolean transform = result.shoudTransform(player.asWorld().random);
|
||||
|
||||
|
@ -201,48 +198,6 @@ public class EarthPonyGrowAbility implements Ability<Pos> {
|
|||
|
||||
}
|
||||
|
||||
private static record TransmutationRecipe(Block input, BlockState output, BlockState material) {
|
||||
static final List<TransmutationRecipe> RECIPES = List.of(
|
||||
new TransmutationRecipe(Blocks.OAK_SAPLING, UTreeGen.GOLDEN_APPLE_TREE.sapling().get().getDefaultState(), Blocks.RAW_GOLD_BLOCK.getDefaultState()),
|
||||
new TransmutationRecipe(Blocks.CARROTS, UBlocks.GOLD_ROOT.getDefaultState(), Blocks.RAW_GOLD_BLOCK.getDefaultState()),
|
||||
new TransmutationRecipe(Blocks.CORNFLOWER, UBlocks.CURING_JOKE.getDefaultState(), Blocks.LAPIS_BLOCK.getDefaultState()),
|
||||
new TransmutationRecipe(Blocks.WITHER_ROSE, UBlocks.PLUNDER_VINE_BUD.getDefaultState(), Blocks.NETHERRACK.getDefaultState())
|
||||
);
|
||||
static final int RADIUS = 3;
|
||||
static final int SIDE_LENGTH = (2 * RADIUS) + 1;
|
||||
static final int AREA = (SIDE_LENGTH * SIDE_LENGTH) - 1;
|
||||
static final int MINIMUM_INPUT = 9;
|
||||
|
||||
public boolean matches(World world, BlockPos pos) {
|
||||
return world.getBlockState(pos).isOf(input);
|
||||
}
|
||||
|
||||
public Result checkPattern(World world, BlockPos pos) {
|
||||
BlockPos center = pos.down();
|
||||
Set<BlockPos> matches = new HashSet<>();
|
||||
for (BlockPos cell : BlockPos.iterateInSquare(center, RADIUS, Direction.EAST, Direction.NORTH)) {
|
||||
if (cell.equals(center)) {
|
||||
continue;
|
||||
}
|
||||
if (!world.getBlockState(cell).equals(material)) {
|
||||
break;
|
||||
}
|
||||
matches.add(cell.toImmutable());
|
||||
}
|
||||
return new Result(this, matches);
|
||||
}
|
||||
|
||||
public BlockState getResult(World world, BlockPos pos) {
|
||||
return StateUtil.copyState(world.getBlockState(pos), output);
|
||||
}
|
||||
|
||||
record Result (TransmutationRecipe recipe, Set<BlockPos> matchedLocations) {
|
||||
public boolean shoudTransform(Random random) {
|
||||
return random.nextInt(TransmutationRecipe.AREA) < matchedLocations().size();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public interface Growable {
|
||||
boolean grow(World world, BlockState state, BlockPos pos);
|
||||
}
|
||||
|
|
|
@ -13,6 +13,7 @@ import com.minelittlepony.unicopia.ability.magic.spell.trait.SpellTraits;
|
|||
import com.minelittlepony.unicopia.ability.magic.spell.trait.Trait;
|
||||
import com.minelittlepony.unicopia.block.UBlocks;
|
||||
import com.minelittlepony.unicopia.item.EnchantableItem;
|
||||
import com.minelittlepony.unicopia.item.TransformCropsRecipe;
|
||||
import com.minelittlepony.unicopia.item.UItems;
|
||||
import com.minelittlepony.unicopia.item.URecipes;
|
||||
import com.minelittlepony.unicopia.item.group.MultiItem;
|
||||
|
@ -20,6 +21,7 @@ import com.minelittlepony.unicopia.item.group.MultiItem;
|
|||
import dev.emi.emi.api.EmiPlugin;
|
||||
import dev.emi.emi.api.EmiRegistry;
|
||||
import dev.emi.emi.api.recipe.EmiRecipeCategory;
|
||||
import dev.emi.emi.api.recipe.EmiWorldInteractionRecipe;
|
||||
import dev.emi.emi.api.render.EmiTexture;
|
||||
import dev.emi.emi.api.stack.Comparison;
|
||||
import dev.emi.emi.api.stack.EmiStack;
|
||||
|
@ -33,8 +35,10 @@ import net.minecraft.util.Identifier;
|
|||
public class Main implements EmiPlugin {
|
||||
static final EmiStack SPELL_BOOK_STATION = EmiStack.of(UItems.SPELLBOOK);
|
||||
static final EmiStack CLOUD_SHAPING_STATION = EmiStack.of(UBlocks.SHAPING_BENCH);
|
||||
static final EmiStack GROWING_STATION = EmiStack.of(UItems.EARTH_BADGE);
|
||||
static final EmiRecipeCategory SPELL_BOOK_CATEGORY = new EmiRecipeCategory(Unicopia.id("spellbook"), SPELL_BOOK_STATION, SPELL_BOOK_STATION);
|
||||
static final EmiRecipeCategory CLOUD_SHAPING_CATEGORY = new EmiRecipeCategory(Unicopia.id("cloud_shaping"), CLOUD_SHAPING_STATION, CLOUD_SHAPING_STATION);
|
||||
static final EmiRecipeCategory GROWING_CATEGORY = new EmiRecipeCategory(Unicopia.id("growing"), GROWING_STATION, GROWING_STATION);
|
||||
|
||||
static final Identifier WIDGETS = Unicopia.id("textures/gui/widgets.png");
|
||||
static final EmiTexture EMPTY_ARROW = new EmiTexture(WIDGETS, 44, 0, 24, 17);
|
||||
|
@ -103,5 +107,20 @@ public class Main implements EmiPlugin {
|
|||
});
|
||||
}
|
||||
});
|
||||
|
||||
registry.addCategory(GROWING_CATEGORY);
|
||||
registry.addWorkstation(GROWING_CATEGORY, GROWING_STATION);
|
||||
registry.getRecipeManager().listAllOfType(URecipes.GROWING).forEach(recipe -> {
|
||||
registry.addRecipe(new EmiWorldInteractionRecipe(EmiWorldInteractionRecipe.builder()
|
||||
.id(recipe.getId())
|
||||
.leftInput(EmiStack.of(recipe.getTargetAsItem()))
|
||||
.rightInput(EmiStack.of(recipe.getCatalyst(), TransformCropsRecipe.MINIMUM_INPUT), true)
|
||||
.output(EmiStack.of(recipe.getOutput()))) {
|
||||
@Override
|
||||
public EmiRecipeCategory getCategory() {
|
||||
return GROWING_CATEGORY;
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,176 @@
|
|||
package com.minelittlepony.unicopia.item;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
import com.minelittlepony.unicopia.block.state.StateUtil;
|
||||
import com.minelittlepony.unicopia.entity.player.Pony;
|
||||
import com.mojang.datafixers.util.Pair;
|
||||
import com.mojang.serialization.Codec;
|
||||
import com.mojang.serialization.JsonOps;
|
||||
import com.mojang.serialization.codecs.RecordCodecBuilder;
|
||||
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.inventory.SingleStackInventory;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.network.PacketByteBuf;
|
||||
import net.minecraft.recipe.Recipe;
|
||||
import net.minecraft.recipe.RecipeSerializer;
|
||||
import net.minecraft.recipe.RecipeType;
|
||||
import net.minecraft.registry.DynamicRegistryManager;
|
||||
import net.minecraft.registry.Registries;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.Direction;
|
||||
import net.minecraft.util.math.random.Random;
|
||||
import net.minecraft.world.EmptyBlockView;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
public class TransformCropsRecipe implements Recipe<TransformCropsRecipe.PlacementArea> {
|
||||
public static final int RADIUS = 3;
|
||||
public static final int SIDE_LENGTH = (2 * RADIUS) + 1;
|
||||
public static final int AREA = (SIDE_LENGTH * SIDE_LENGTH) - 1;
|
||||
public static final int MINIMUM_INPUT = 9;
|
||||
|
||||
private final Identifier id;
|
||||
|
||||
private final Block target;
|
||||
private final BlockState catalyst;
|
||||
private final BlockState output;
|
||||
|
||||
public TransformCropsRecipe(Identifier id, Block target, BlockState catalyst, BlockState output) {
|
||||
this.id = id;
|
||||
this.output = output;
|
||||
this.target = target;
|
||||
this.catalyst = catalyst;
|
||||
}
|
||||
|
||||
public ItemStack getTargetAsItem() {
|
||||
return target.asItem().getDefaultStack();
|
||||
}
|
||||
|
||||
public ItemStack getCatalyst() {
|
||||
return catalyst.getBlock().getPickStack(EmptyBlockView.INSTANCE, BlockPos.ORIGIN, catalyst);
|
||||
}
|
||||
|
||||
public ItemStack getOutput() {
|
||||
return output.getBlock().getPickStack(EmptyBlockView.INSTANCE, BlockPos.ORIGIN, output);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Identifier getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RecipeSerializer<?> getSerializer() {
|
||||
return URecipes.TRANSFORM_CROP_SERIALIZER;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RecipeType<?> getType() {
|
||||
return URecipes.GROWING;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matches(PlacementArea inventory, World world) {
|
||||
return world.getBlockState(inventory.position()).isOf(target);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack craft(PlacementArea inventory, DynamicRegistryManager manager) {
|
||||
return getOutput(manager);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack getOutput(DynamicRegistryManager manager) {
|
||||
return output.getBlock().asItem().getDefaultStack();
|
||||
}
|
||||
|
||||
public Result checkPattern(World world, BlockPos pos) {
|
||||
BlockPos center = pos.down();
|
||||
Set<BlockPos> matches = new HashSet<>();
|
||||
for (BlockPos cell : BlockPos.iterateInSquare(center, RADIUS, Direction.EAST, Direction.NORTH)) {
|
||||
if (cell.equals(center)) {
|
||||
continue;
|
||||
}
|
||||
if (!world.getBlockState(cell).equals(catalyst)) {
|
||||
break;
|
||||
}
|
||||
matches.add(cell.toImmutable());
|
||||
}
|
||||
return new Result(this, matches);
|
||||
}
|
||||
|
||||
public BlockState getResult(World world, BlockPos pos) {
|
||||
return StateUtil.copyState(world.getBlockState(pos), output);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean fits(int width, int height) {
|
||||
return width >= SIDE_LENGTH && height >= SIDE_LENGTH;
|
||||
}
|
||||
|
||||
public static class Serializer implements RecipeSerializer<TransformCropsRecipe> {
|
||||
record Intermediate(Block target, BlockState fuel, BlockState output) {}
|
||||
private static final Codec<Intermediate> CODEC = RecordCodecBuilder.create(instance -> instance.group(
|
||||
Registries.BLOCK.getCodec().fieldOf("target").forGetter(Intermediate::target),
|
||||
BlockState.CODEC.fieldOf("consume").forGetter(Intermediate::fuel),
|
||||
BlockState.CODEC.fieldOf("output").forGetter(Intermediate::output)
|
||||
).apply(instance, Intermediate::new));
|
||||
|
||||
@Override
|
||||
public TransformCropsRecipe read(Identifier id, JsonObject json) {
|
||||
Intermediate content = CODEC.decode(JsonOps.INSTANCE, json).result().map(Pair::getFirst).get();
|
||||
return new TransformCropsRecipe(id, content.target(), content.fuel(), content.output());
|
||||
}
|
||||
|
||||
@Override
|
||||
public TransformCropsRecipe read(Identifier id, PacketByteBuf buffer) {
|
||||
return new TransformCropsRecipe(id,
|
||||
buffer.readRegistryValue(Registries.BLOCK),
|
||||
Block.getStateFromRawId(buffer.readInt()),
|
||||
Block.getStateFromRawId(buffer.readInt())
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(PacketByteBuf buffer, TransformCropsRecipe recipe) {
|
||||
buffer.writeRegistryValue(Registries.BLOCK, recipe.target);
|
||||
buffer.writeInt(Block.getRawIdFromState(recipe.catalyst));
|
||||
buffer.writeInt(Block.getRawIdFromState(recipe.output));
|
||||
}
|
||||
}
|
||||
|
||||
public static record PlacementArea (Pony pony, BlockPos position) implements SingleStackInventory {
|
||||
@Override
|
||||
public ItemStack getStack(int var1) {
|
||||
return ItemStack.EMPTY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack removeStack(int slot, int count) {
|
||||
return ItemStack.EMPTY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setStack(int slot, ItemStack stack) { }
|
||||
|
||||
@Override
|
||||
public void markDirty() { }
|
||||
|
||||
@Override
|
||||
public boolean canPlayerUse(PlayerEntity player) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public record Result (TransformCropsRecipe recipe, Set<BlockPos> matchedLocations) {
|
||||
public boolean shoudTransform(Random random) {
|
||||
return random.nextInt(AREA) < matchedLocations().size();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -48,6 +48,7 @@ public interface UItems {
|
|||
|
||||
FriendshipBraceletItem FRIENDSHIP_BRACELET = register("friendship_bracelet", new FriendshipBraceletItem(new FabricItemSettings().rarity(Rarity.UNCOMMON)), ItemGroups.TOOLS);
|
||||
|
||||
Item PLUNDER_VINE = register("plunder_vine", new BlockItem(UBlocks.PLUNDER_VINE_BUD, new Item.Settings()));
|
||||
Item EMPTY_JAR = register("empty_jar", new JarItem(new Item.Settings().maxCount(16).fireproof(), false, false, false), ItemGroups.FUNCTIONAL);
|
||||
FilledJarItem FILLED_JAR = register("filled_jar", new FilledJarItem(new Item.Settings().maxCount(1).recipeRemainder(EMPTY_JAR)));
|
||||
Item RAIN_CLOUD_JAR = register("rain_cloud_jar", new JarItem(new Item.Settings().maxCount(1).fireproof().recipeRemainder(EMPTY_JAR), true, false, false), ItemGroups.FUNCTIONAL);
|
||||
|
|
|
@ -23,6 +23,7 @@ import net.minecraft.util.collection.DefaultedList;
|
|||
public interface URecipes {
|
||||
RecipeType<SpellbookRecipe> SPELLBOOK = RecipeType.register("unicopia:spellbook");
|
||||
RecipeType<StonecuttingRecipe> CLOUD_SHAPING = RecipeType.register("unicopia:cloud_shaping");
|
||||
RecipeType<TransformCropsRecipe> GROWING = RecipeType.register("unicopia:growing");
|
||||
|
||||
RecipeSerializer<ShapelessRecipe> ZAP_APPLE_SERIALIZER = RecipeSerializer.register("unicopia:crafting_zap_apple", new ZapAppleRecipe.Serializer());
|
||||
RecipeSerializer<GlowingRecipe> GLOWING_SERIALIZER = RecipeSerializer.register("unicopia:crafting_glowing", new SpecialRecipeSerializer<>(GlowingRecipe::new));
|
||||
|
@ -33,6 +34,7 @@ public interface URecipes {
|
|||
RecipeSerializer<SpellEnhancingRecipe> TRAIT_COMBINING = RecipeSerializer.register("unicopia:spellbook/combining", new SpellEnhancingRecipe.Serializer());
|
||||
RecipeSerializer<SpellDuplicatingRecipe> SPELL_DUPLICATING = RecipeSerializer.register("unicopia:spellbook/duplicating", new SpellDuplicatingRecipe.Serializer());
|
||||
RecipeSerializer<CloudShapingRecipe> CLOUD_SHAPING_SERIALIZER = RecipeSerializer.register("unicopia:cloud_shaping", new CuttingRecipe.Serializer<>(CloudShapingRecipe::new) {});
|
||||
RecipeSerializer<TransformCropsRecipe> TRANSFORM_CROP_SERIALIZER = RecipeSerializer.register("unicopia:transform_crop", new TransformCropsRecipe.Serializer());
|
||||
|
||||
static DefaultedList<Ingredient> getIngredients(JsonArray json) {
|
||||
DefaultedList<Ingredient> defaultedList = DefaultedList.of();
|
||||
|
|
|
@ -46,6 +46,7 @@
|
|||
"item.unicopia.spellbook": "Spellbook",
|
||||
"emi.category.unicopia.spellbook": "Spellbook",
|
||||
"emi.category.unicopia.cloud_shaping": "Shaping",
|
||||
"emi.category.unicopia.growing": "Growing",
|
||||
|
||||
"item.unicopia.alicorn_badge": "Alicorn Emblem",
|
||||
"item.unicopia.unicorn_badge": "Unicorn Emblem",
|
||||
|
@ -73,6 +74,7 @@
|
|||
"item.unicopia.love_bucket": "Love Bucket",
|
||||
"item.unicopia.love_mug": "Mug o' Love",
|
||||
|
||||
"item.unicopia.plunder_vine": "Plunder Vine",
|
||||
"item.unicopia.empty_jar": "Glass Jar",
|
||||
"item.unicopia.filled_jar": "%s in a Jar",
|
||||
"item.unicopia.rain_cloud_jar": "Rain in a Jar",
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
{
|
||||
"parent": "unicopia:block/plunder_vine_bud"
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
{
|
||||
"type": "unicopia:transform_crop",
|
||||
"target": "minecraft:cornflower",
|
||||
"consume": {
|
||||
"Name": "minecraft:lapis_block",
|
||||
"Properties": {}
|
||||
},
|
||||
"output": {
|
||||
"Name": "unicopia:curing_joke",
|
||||
"Properties": {}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
{
|
||||
"type": "unicopia:transform_crop",
|
||||
"target": "minecraft:carrots",
|
||||
"consume": {
|
||||
"Name": "minecraft:raw_gold_block",
|
||||
"Properties": {}
|
||||
},
|
||||
"output": {
|
||||
"Name": "unicopia:gold_root",
|
||||
"Properties": {}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
{
|
||||
"type": "unicopia:transform_crop",
|
||||
"target": "minecraft:oak_sapling",
|
||||
"consume": {
|
||||
"Name": "minecraft:raw_gold_block",
|
||||
"Properties": {}
|
||||
},
|
||||
"output": {
|
||||
"Name": "unicopia:golden_oak_sapling",
|
||||
"Properties": {}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
{
|
||||
"type": "unicopia:transform_crop",
|
||||
"target": "minecraft:wither_rose",
|
||||
"consume": {
|
||||
"Name": "minecraft:netherrack",
|
||||
"Properties": {}
|
||||
},
|
||||
"output": {
|
||||
"Name": "unicopia:plunder_vine_bud",
|
||||
"Properties": {}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
{
|
||||
"type": "unicopia:transform_crop",
|
||||
"target": "minecraft:dark_oak_sapling",
|
||||
"consume": {
|
||||
"Name": "unicopia:chitin",
|
||||
"Properties": {}
|
||||
},
|
||||
"output": {
|
||||
"Name": "unicopia:zapling",
|
||||
"Properties": {}
|
||||
}
|
||||
}
|
|
@ -15,6 +15,7 @@
|
|||
"minecraft:end_portal_frame",
|
||||
"minecraft:debug_stick",
|
||||
"minecraft:command_block_minecart",
|
||||
"unicopia:plunder_vine",
|
||||
"#unicopia:badges"
|
||||
]
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue