Add structure previews to the emi recipes for earth ponies, add the spectral clock recipe to emi, and ensure items aren't burned when throwing them into the altar's flame

This commit is contained in:
Sollace 2024-02-05 12:21:10 +00:00
parent e48b7bd244
commit 3d5292c7f3
No known key found for this signature in database
GPG key ID: E52FACE7B5C773DB
12 changed files with 336 additions and 27 deletions

View file

@ -0,0 +1,22 @@
package com.minelittlepony.unicopia.block;
import net.minecraft.block.BlockState;
import net.minecraft.block.SoulFireBlock;
import net.minecraft.entity.Entity;
import net.minecraft.entity.ItemEntity;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
public class SpectralFireBlock extends SoulFireBlock {
public SpectralFireBlock(Settings settings) {
super(settings);
}
@Override
public void onEntityCollision(BlockState state, World world, BlockPos pos, Entity entity) {
if (!(entity instanceof ItemEntity)) {
super.onEntityCollision(state, world, pos, entity);
}
}
}

View file

@ -225,6 +225,8 @@ public interface UBlocks {
Block CRYSTAL_DOOR = register("crystal_door", new CrystalDoorBlock(Settings.copy(Blocks.IRON_DOOR), UWoodTypes.CRYSTAL), ItemGroups.FUNCTIONAL);
Block CLOUD_DOOR = register("cloud_door", new CloudDoorBlock(Settings.copy(CLOUD), CLOUD.getDefaultState(), UWoodTypes.CLOUD), ItemGroups.FUNCTIONAL);
Block SPECTRAL_FIRE = register("spectral_fire", new SpectralFireBlock(Settings.copy(Blocks.SOUL_FIRE)));
EdibleBlock HAY_BLOCK = register("hay_block", new EdibleBlock(new Identifier("hay_block"), new Identifier("wheat"), true));
private static <T extends Block> T register(String name, T item) {
@ -266,7 +268,7 @@ public interface UBlocks {
StrippableBlockRegistry.register(PALM_LOG, STRIPPED_PALM_LOG);
StrippableBlockRegistry.register(ZAP_WOOD, STRIPPED_ZAP_WOOD);
StrippableBlockRegistry.register(PALM_WOOD, STRIPPED_PALM_WOOD);
Collections.addAll(TRANSLUCENT_BLOCKS, WEATHER_VANE, CHITIN_SPIKES, PLUNDER_VINE, PLUNDER_VINE_BUD, CLAM_SHELL, SCALLOP_SHELL, TURRET_SHELL, CURING_JOKE);
Collections.addAll(TRANSLUCENT_BLOCKS, WEATHER_VANE, CHITIN_SPIKES, PLUNDER_VINE, PLUNDER_VINE_BUD, CLAM_SHELL, SCALLOP_SHELL, TURRET_SHELL, CURING_JOKE, SPECTRAL_FIRE);
TintedBlock.REGISTRY.add(PALM_LEAVES);
FlammableBlockRegistry.getDefaultInstance().add(GREEN_APPLE_LEAVES, 30, 60);

View file

@ -9,6 +9,19 @@ import net.minecraft.block.Blocks;
import net.minecraft.network.PacketByteBuf;
public record Schematic(int dx, int dy, int dz, Entry[] states) {
public static final Schematic ALTAR = new Schematic.Builder()
.fill(0, 0, 0, 8, 0, 8, Blocks.SOUL_SAND.getDefaultState())
.fill(3, 1, 3, 5, 1, 5, Blocks.OBSIDIAN.getDefaultState())
.set(4, 1, 4, Blocks.SOUL_SAND.getDefaultState())
.set(4, 2, 4, Blocks.SOUL_FIRE.getDefaultState())
.set(4, 1, 6, Blocks.LODESTONE.getDefaultState())
.fill(0, 1, 2, 0, 4, 2, Blocks.OBSIDIAN.getDefaultState()).fill(0, 1, 6, 0, 4, 6, Blocks.OBSIDIAN.getDefaultState())
.fill(2, 1, 0, 2, 4, 0, Blocks.OBSIDIAN.getDefaultState()).fill(6, 1, 0, 6, 4, 0, Blocks.OBSIDIAN.getDefaultState())
.fill(8, 1, 2, 8, 4, 2, Blocks.OBSIDIAN.getDefaultState()).fill(8, 1, 6, 8, 4, 6, Blocks.OBSIDIAN.getDefaultState())
.fill(2, 1, 8, 2, 4, 8, Blocks.OBSIDIAN.getDefaultState()).fill(6, 1, 8, 6, 4, 8, Blocks.OBSIDIAN.getDefaultState())
.build();
public static Schematic fromPacket(PacketByteBuf buffer) {
Builder builder = new Builder();
buffer.readCollection(ArrayList::new, buf -> {

View file

@ -81,7 +81,7 @@ public class SpellbookEntityRenderer extends LivingEntityRenderer<SpellbookEntit
Altar altar = entity.getAltar().get();
Vec3d center = altar.origin().toCenterPos();
Vec3d center = altar.origin().toCenterPos().add(0, -1, 0);
float x = (float)MathHelper.lerp(tickDelta, entity.prevX, entity.getX());
float y = (float)MathHelper.lerp(tickDelta, entity.prevY, entity.getY());

View file

@ -1,6 +1,7 @@
package com.minelittlepony.unicopia.compat.emi;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Stream;
import org.jetbrains.annotations.Nullable;
@ -12,6 +13,7 @@ import com.minelittlepony.unicopia.ability.magic.spell.crafting.SpellShapedCraft
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.block.state.Schematic;
import com.minelittlepony.unicopia.item.EnchantableItem;
import com.minelittlepony.unicopia.item.TransformCropsRecipe;
import com.minelittlepony.unicopia.item.UItems;
@ -21,12 +23,14 @@ 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;
import dev.emi.emi.recipe.EmiStonecuttingRecipe;
import net.minecraft.block.Block;
import net.minecraft.block.Blocks;
import net.minecraft.item.ItemStack;
import net.minecraft.item.Items;
import net.minecraft.recipe.RecipeType;
import net.minecraft.registry.DynamicRegistryManager;
import net.minecraft.registry.Registries;
@ -35,10 +39,12 @@ 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 EmiStack GROWING_STATION = EmiStack.of(Blocks.FARMLAND);
static final EmiStack ALTAR_STATION = EmiStack.of(Blocks.CRYING_OBSIDIAN);
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 EmiRecipeCategory ALTAR_CATEGORY = new EmiRecipeCategory(Unicopia.id("altar"), ALTAR_STATION, ALTAR_STATION);
static final Identifier WIDGETS = Unicopia.id("textures/gui/widgets.png");
static final EmiTexture EMPTY_ARROW = new EmiTexture(WIDGETS, 44, 0, 24, 17);
@ -111,16 +117,35 @@ 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;
}
});
registry.addRecipe(new StructureInteractionEmiRecipe(
GROWING_CATEGORY,
recipe.getId(),
new Schematic.Builder()
.fill(0, 0, 0, 6, 0, 6, Block.getBlockFromItem(recipe.getCatalyst().getItem()).getDefaultState())
.set(3, 0, 3, Blocks.FARMLAND.getDefaultState())
.set(3, 1, 3, Block.getBlockFromItem(recipe.getTargetAsItem().getItem()).getDefaultState())
.build(),
List.of(EmiStack.of(recipe.getTargetAsItem()), EmiStack.of(recipe.getCatalyst(), TransformCropsRecipe.AREA)),
EmiStack.of(recipe.getOutput()),
Unicopia.id("textures/gui/ability/grow.png")
));
});
registry.addCategory(ALTAR_CATEGORY);
registry.addWorkstation(ALTAR_CATEGORY, ALTAR_STATION);
registry.addRecipe(new StructureInteractionEmiRecipe(
ALTAR_CATEGORY,
Unicopia.id("altar/spectral_clock"),
Schematic.ALTAR,
List.of(
EmiStack.of(Items.CLOCK),
EmiStack.of(UItems.SPELLBOOK),
EmiStack.of(Blocks.SOUL_SAND),
EmiStack.of(Blocks.LODESTONE),
EmiStack.of(Blocks.OBSIDIAN, 8 * 4 + 8)
),
EmiStack.of(UItems.SPECTRAL_CLOCK),
Unicopia.id("textures/gui/race/alicorn.png")
));
}
}

View file

@ -57,36 +57,38 @@ class SpellbookEmiRecipe implements EmiRecipe, SpellbookRecipe.CraftingTreeBuild
@Override
public int getDisplayWidth() {
return 220;
return 150;
}
@Override
public int getDisplayHeight() {
return 145;
return 75;
}
@Override
public void addWidgets(WidgetHolder widgets) {
widgets.addTexture(SpellbookScreen.TEXTURE, 0, 0, getDisplayWidth(), getDisplayHeight(), 50, 50, 128, 128, 512, 256);
widgets.addTexture(Main.EMPTY_ARROW, 160, 65);
widgets.addTexture(Main.EMPTY_ARROW, 85, 30);
List<HexagonalCraftingGrid.Slot> grid = new ArrayList<>();
List<HexagonalCraftingGrid.Slot> gem = new ArrayList<>();
HexagonalCraftingGrid.create(4, 35, 3, grid, gem);
HexagonalCraftingGrid.create(-34, -5, 3, grid, gem);
int currentInput = 1;
for (int i = 0; i < grid.size(); i++) {
widgets.add(new SlotTexture(grid.get(i)));
var slot = grid.get(i);
if (currentInput < inputs.size() && grid.get(i).weight() == 1) {
widgets.addSlot(inputs.get(currentInput++), grid.get(i).left(), grid.get(i).top()).drawBack(false);
} else {
widgets.addSlot(grid.get(i).left(), grid.get(i).top()).drawBack(false);
if (currentInput < inputs.size() && slot.weight() == 1) {
widgets.add(new SlotTexture(slot));
widgets.addSlot(inputs.get(currentInput++), slot.left(), slot.top()).drawBack(false);
} else if (slot.weight() == 1) {
widgets.add(new SlotTexture(slot));
widgets.addSlot(slot.left(), slot.top()).drawBack(false);
}
}
widgets.addSlot(inputs.get(0), gem.get(0).left(), gem.get(0).top()).drawBack(false);
widgets.addSlot(getOutput(), 190, 60).large(true).recipeContext(this);
widgets.addSlot(getOutput(), 120, 25).large(true).recipeContext(this);
}
protected EmiIngredient getOutput() {

View file

@ -0,0 +1,144 @@
package com.minelittlepony.unicopia.compat.emi;
import java.util.List;
import com.minelittlepony.unicopia.block.state.Schematic;
import dev.emi.emi.api.recipe.EmiRecipe;
import dev.emi.emi.api.recipe.EmiRecipeCategory;
import dev.emi.emi.api.render.EmiTexture;
import dev.emi.emi.api.stack.EmiIngredient;
import dev.emi.emi.api.stack.EmiStack;
import dev.emi.emi.api.widget.WidgetHolder;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.gui.DrawContext;
import net.minecraft.client.render.DiffuseLighting;
import net.minecraft.client.render.LightmapTextureManager;
import net.minecraft.client.render.OverlayTexture;
import net.minecraft.client.render.VertexConsumerProvider.Immediate;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.text.Text;
import net.minecraft.util.Identifier;
import net.minecraft.util.Util;
import net.minecraft.util.math.RotationAxis;
public class StructureInteractionEmiRecipe implements EmiRecipe {
private final EmiRecipeCategory category;
private final Identifier id;
private final Schematic schematic;
private final List<EmiIngredient> inputs;
private final List<EmiStack> output;
private final Identifier processIcon;
private int age;
public StructureInteractionEmiRecipe(EmiRecipeCategory category, Identifier id, Schematic schematic, List<EmiIngredient> inputs, EmiStack output, Identifier processIcon) {
this.category = category;
this.id = id;
this.schematic = schematic;
this.inputs = inputs;
this.output = List.of(output);
this.processIcon = processIcon;
}
@Override
public EmiRecipeCategory getCategory() {
return category;
}
@Override
public Identifier getId() {
return id;
}
@Override
public List<EmiIngredient> getInputs() {
return inputs;
}
@Override
public List<EmiStack> getOutputs() {
return output;
}
@Override
public int getDisplayWidth() {
return 130;
}
@Override
public int getDisplayHeight() {
return schematic.dy() * 8 + 80 + 20 * (inputs.size() - 2);
}
@Override
public void addWidgets(WidgetHolder widgets) {
int y = schematic.dy() * 8;
int row = 0;
age = 0;
widgets.addDrawable(10, y / 2, 100, 100, this::renderSchematic);
int x = 10;
for (int i = 0; i < inputs.size(); i++) {
if (i > 1) {
x -= 40;
row += 20;
}
if (i > 0) {
widgets.addTexture(EmiTexture.PLUS, x + 3, y + 53 + row);
x += 20;
}
widgets.addSlot(inputs.get(i), x, y + 50 + row).catalyst(i > 0);
x += 20;
}
widgets.addTexture(EmiTexture.EMPTY_ARROW, 73, y + 52);
widgets.addSlot(output.get(0), 100, y + 47).large(true).recipeContext(this);
widgets.addTexture(processIcon, 73, y + 45, 13, 13, 0, 0, 16, 16, 16, 16).tooltipText(List.of(Text.translatable(
Util.createTranslationKey("recipe", category.getId()) + "." + "instruction"
)));
}
private void renderSchematic(DrawContext context, int mouseX, int mouseY, float delta) {
if (schematic.volume() == 0) {
return;
}
MatrixStack matrices = context.getMatrices();
Immediate immediate = context.getVertexConsumers();
MinecraftClient client = MinecraftClient.getInstance();
matrices.push();
float minSize = (Math.max(schematic.dz(), Math.max(schematic.dx(), schematic.dy())) + 1) * 16;
float scale = 60 / minSize;
matrices.scale(scale, scale, 1);
matrices.translate(95, 40, 100);
matrices.scale(16, -16, 16);
matrices.peek().getNormalMatrix().scale(1, -1, 1);
matrices.multiply(RotationAxis.POSITIVE_X.rotationDegrees(20));
matrices.peek().getPositionMatrix().rotate(RotationAxis.POSITIVE_Y.rotationDegrees(40));
matrices.translate(
(-schematic.dx() - 1) / 2F,
(-schematic.dy() - 1) / 2F,
(-schematic.dz() - 1) / 2F
);
DiffuseLighting.disableGuiDepthLighting();
age++;
for (var entry : schematic.states()) {
int x = entry.x() - schematic.dx() / 2;
int z = entry.z() - schematic.dz() / 2;
int distance = x * x + z * z;
if (age >= distance * 2) {
matrices.push();
matrices.translate(entry.x(), entry.y(), entry.z());
client.getBlockRenderManager().renderBlockAsEntity(entry.state(), matrices, immediate, LightmapTextureManager.MAX_LIGHT_COORDINATE, OverlayTexture.DEFAULT_UV);
matrices.pop();
}
}
matrices.pop();
}
}

View file

@ -262,7 +262,7 @@ public class SpellbookEntity extends MobEntity implements MagicImmune {
return;
}
//setBeamTicks(0);
setBeamTicks(0);
if (activeRecipe == null) {
return;

View file

@ -7,6 +7,7 @@ import java.util.function.Consumer;
import java.util.function.Predicate;
import org.jetbrains.annotations.Nullable;
import com.minelittlepony.unicopia.block.UBlocks;
import com.minelittlepony.unicopia.entity.mob.FloatingArtefactEntity;
import com.minelittlepony.unicopia.entity.mob.SpellbookEntity;
import com.minelittlepony.unicopia.entity.mob.UEntities;
@ -133,7 +134,7 @@ public record Altar(BlockPos origin, Set<BlockPos> pillars) {
}
public void generateDecorations(World world) {
world.setBlockState(origin, Blocks.SOUL_FIRE.getDefaultState(), Block.FORCE_STATE | Block.NOTIFY_ALL);
world.setBlockState(origin, UBlocks.SPECTRAL_FIRE.getDefaultState(), Block.FORCE_STATE | Block.NOTIFY_ALL);
pillars.forEach(pillar -> {
FloatingArtefactEntity artefact = UEntities.FLOATING_ARTEFACT.create(world);
artefact.setStack(UItems.ALICORN_BADGE.getDefaultStack());
@ -160,7 +161,7 @@ public record Altar(BlockPos origin, Set<BlockPos> pillars) {
}
public boolean isValid(World world) {
return checkState(world, origin, Blocks.SOUL_FIRE)
return checkState(world, origin, UBlocks.SPECTRAL_FIRE)
&& checkState(world, origin.down(), Blocks.SOUL_SAND)
&& checkSlab(world, origin.down())
&& pillars.stream().allMatch(pillar ->

View file

@ -0,0 +1,90 @@
{
"multipart": [
{
"apply": [
{
"model": "minecraft:block/soul_fire_floor0"
},
{
"model": "minecraft:block/soul_fire_floor1"
}
]
},
{
"apply": [
{
"model": "minecraft:block/soul_fire_side0"
},
{
"model": "minecraft:block/soul_fire_side1"
},
{
"model": "minecraft:block/soul_fire_side_alt0"
},
{
"model": "minecraft:block/soul_fire_side_alt1"
}
]
},
{
"apply": [
{
"model": "minecraft:block/soul_fire_side0",
"y": 90
},
{
"model": "minecraft:block/soul_fire_side1",
"y": 90
},
{
"model": "minecraft:block/soul_fire_side_alt0",
"y": 90
},
{
"model": "minecraft:block/soul_fire_side_alt1",
"y": 90
}
]
},
{
"apply": [
{
"model": "minecraft:block/soul_fire_side0",
"y": 180
},
{
"model": "minecraft:block/soul_fire_side1",
"y": 180
},
{
"model": "minecraft:block/soul_fire_side_alt0",
"y": 180
},
{
"model": "minecraft:block/soul_fire_side_alt1",
"y": 180
}
]
},
{
"apply": [
{
"model": "minecraft:block/soul_fire_side0",
"y": 270
},
{
"model": "minecraft:block/soul_fire_side1",
"y": 270
},
{
"model": "minecraft:block/soul_fire_side_alt0",
"y": 270
},
{
"model": "minecraft:block/soul_fire_side_alt1",
"y": 270
}
]
}
]
}

View file

@ -49,6 +49,9 @@
"emi.category.unicopia.spellbook": "Spellbook",
"emi.category.unicopia.cloud_shaping": "Shaping",
"emi.category.unicopia.growing": "Growing",
"emi.category.unicopia.altar": "Dark Ritual",
"recipe.unicopia.altar.instruction": "Cast item into flames",
"recipe.unicopia.growing.instruction": "Focus Earth Pony Magic",
"item.unicopia.alicorn_badge": "Alicorn Emblem",
"item.unicopia.unicorn_badge": "Unicorn Emblem",
@ -222,6 +225,7 @@
"block.unicopia.rocks": "Rocks",
"block.unicopia.plunder_vine": "Plunder Vine",
"block.unicopia.plunder_vine_bud": "Plunder Vine Bud",
"block.unicopia.spectral_fire": "Spectral Fire",
"block.unicopia.bananas": "Bananas",
"block.unicopia.zapling": "Zapling",
"block.unicopia.zap_log": "Zap Apple Log",

View file

@ -0,0 +1,6 @@
{
"replace": false,
"values": [
"unicopia:spectral_fire"
]
}