Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@ repositories {
maven("https://maven.pvphub.me/tofaa") {
name = "EntityLib"
}
maven("https://repo.codemc.io/repository/maven-releases/") {
name = "CodeMC"
}
Comment on lines +33 to +35
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why was this added?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Entitylib was made from implementation to api in another PR, forgot to change it back

}

val rebarVersion = project.properties["rebar.version"] as String
Expand Down
8 changes: 2 additions & 6 deletions src/main/java/io/github/pylonmc/pylon/PylonBlocks.java
Original file line number Diff line number Diff line change
@@ -1,11 +1,7 @@
package io.github.pylonmc.pylon;

import io.github.pylonmc.pylon.content.assembling.AssemblyTable;
import io.github.pylonmc.pylon.content.building.Elevator;
import io.github.pylonmc.pylon.content.building.ExplosiveTarget;
import io.github.pylonmc.pylon.content.building.Immobilizer;
import io.github.pylonmc.pylon.content.building.Pedestal;
import io.github.pylonmc.pylon.content.building.WitherProofBlock;
import io.github.pylonmc.pylon.content.building.*;
import io.github.pylonmc.pylon.content.components.*;
import io.github.pylonmc.pylon.content.machines.cargo.*;
import io.github.pylonmc.pylon.content.machines.diesel.machines.DieselCoreDrill;
Expand Down Expand Up @@ -89,9 +85,9 @@ public static void initialize() {
RebarBlock.register(PylonKeys.SMELTERY_INPUT_HATCH, Material.LIGHT_BLUE_TERRACOTTA, SmelteryInputHatch.class);
RebarBlock.register(PylonKeys.SMELTERY_OUTPUT_HATCH, Material.ORANGE_TERRACOTTA, SmelteryOutputHatch.class);
RebarBlock.register(PylonKeys.SMELTERY_HOPPER, Material.HOPPER, SmelteryHopper.class);
RebarBlock.register(PylonKeys.SMELTERY_CASTER, Material.BRICKS, SmelteryCaster.class);
RebarBlock.register(PylonKeys.SMELTERY_BURNER, Material.FURNACE, SmelteryBurner.class);
RebarBlock.register(PylonKeys.DIESEL_SMELTERY_HEATER, Material.FURNACE, DieselSmelteryHeater.class);
RebarBlock.register(PylonKeys.CASTING_UNIT, Material.BRICKS, CastingUnit.class);
RebarBlock.register(PylonKeys.PIT_KILN, Material.DECORATED_POT, PitKiln.class);
RebarBlock.register(PylonKeys.FLUID_STRAINER, Material.COPPER_GRATE, FluidStrainer.class);
RebarBlock.register(PylonKeys.EXPLOSIVE_TARGET, Material.TARGET, ExplosiveTarget.class);
Expand Down
54 changes: 46 additions & 8 deletions src/main/java/io/github/pylonmc/pylon/PylonItems.java
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,10 @@
import org.bukkit.attribute.Attribute;
import org.bukkit.attribute.AttributeModifier;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.inventory.*;
import org.bukkit.inventory.EquipmentSlot;
import org.bukkit.inventory.EquipmentSlotGroup;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.ShapelessRecipe;
import org.bukkit.inventory.recipe.CraftingBookCategory;
import org.bukkit.potion.PotionType;

Expand Down Expand Up @@ -1957,13 +1960,6 @@ private PylonItems() {
PylonPages.SMELTING.addItem(SMELTERY_HOPPER);
}

public static final ItemStack SMELTERY_CASTER = ItemStackBuilder.rebar(Material.BRICKS, PylonKeys.SMELTERY_CASTER)
.build();
static {
RebarItem.register(RebarItem.class, SMELTERY_CASTER, PylonKeys.SMELTERY_CASTER);
PylonPages.SMELTING.addItem(SMELTERY_CASTER);
}

public static final ItemStack SMELTERY_BURNER = ItemStackBuilder.rebar(Material.FURNACE, PylonKeys.SMELTERY_BURNER)
.build();
static {
Expand All @@ -1978,6 +1974,48 @@ private PylonItems() {
PylonPages.SMELTING.addItem(DIESEL_SMELTERY_HEATER);
}

public static final ItemStack CASTING_UNIT = ItemStackBuilder.rebar(Material.BRICKS, PylonKeys.CASTING_UNIT)
.build();
static {
RebarItem.register(RebarItem.class, CASTING_UNIT, PylonKeys.CASTING_UNIT);
PylonPages.SMELTING.addItem(CASTING_UNIT);
}

public static final ItemStack NUGGET_CAST = ItemStackBuilder.rebar(Material.IRON_NUGGET, PylonKeys.NUGGET_CAST)
.build();
static {
RebarItem.register(RebarItem.class, NUGGET_CAST, PylonKeys.NUGGET_CAST);
PylonPages.SMELTING.addItem(NUGGET_CAST);
}

public static final ItemStack INGOT_CAST = ItemStackBuilder.rebar(Material.IRON_INGOT, PylonKeys.INGOT_CAST)
.build();
static {
RebarItem.register(RebarItem.class, INGOT_CAST, PylonKeys.INGOT_CAST);
PylonPages.SMELTING.addItem(INGOT_CAST);
}

public static final ItemStack BLOCK_CAST = ItemStackBuilder.rebar(Material.IRON_BLOCK, PylonKeys.BLOCK_CAST)
.build();
static {
RebarItem.register(RebarItem.class, BLOCK_CAST, PylonKeys.BLOCK_CAST);
PylonPages.SMELTING.addItem(BLOCK_CAST);
}

public static final ItemStack SHEET_CAST = ItemStackBuilder.rebar(Material.PAPER, PylonKeys.SHEET_CAST)
.build();
static {
RebarItem.register(RebarItem.class, SHEET_CAST, PylonKeys.SHEET_CAST);
PylonPages.SMELTING.addItem(SHEET_CAST);
}

public static final ItemStack PIPE_CAST = ItemStackBuilder.rebar(Material.BROWN_CONCRETE, PylonKeys.PIPE_CAST)
.build();
static {
RebarItem.register(RebarItem.class, PIPE_CAST, PylonKeys.PIPE_CAST);
PylonPages.SMELTING.addItem(PIPE_CAST);
}


//</editor-fold>

Expand Down
8 changes: 7 additions & 1 deletion src/main/java/io/github/pylonmc/pylon/PylonKeys.java
Original file line number Diff line number Diff line change
Expand Up @@ -237,8 +237,14 @@ public class PylonKeys {
public static final NamespacedKey SMELTERY_INPUT_HATCH = pylonKey("smeltery_input_hatch");
public static final NamespacedKey SMELTERY_OUTPUT_HATCH = pylonKey("smeltery_output_hatch");
public static final NamespacedKey SMELTERY_HOPPER = pylonKey("smeltery_hopper");
public static final NamespacedKey SMELTERY_CASTER = pylonKey("smeltery_caster");
public static final NamespacedKey SMELTERY_BURNER = pylonKey("smeltery_burner");
public static final NamespacedKey CASTING_UNIT = pylonKey("casting_unit");

public static final NamespacedKey NUGGET_CAST = pylonKey("cast_nugget");
public static final NamespacedKey INGOT_CAST = pylonKey("cast_ingot");
public static final NamespacedKey BLOCK_CAST = pylonKey("cast_block");
public static final NamespacedKey SHEET_CAST = pylonKey("cast_sheet");
public static final NamespacedKey PIPE_CAST = pylonKey("cast_pipe");

public static final NamespacedKey PIT_KILN = pylonKey("pit_kiln");

Expand Down
1 change: 1 addition & 0 deletions src/main/java/io/github/pylonmc/pylon/PylonRecipes.java
Original file line number Diff line number Diff line change
Expand Up @@ -28,5 +28,6 @@ public static void initialize() {
PitKilnRecipe.RECIPE_TYPE.register();
StrainingRecipe.RECIPE_TYPE.register();
TableSawRecipe.RECIPE_TYPE.register();
SmelteryMeltingPoint.RECIPE_TYPE.register();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ public void postInitialise() {

@Override
public void onBreak(@NotNull List<@NotNull ItemStack> drops, @NotNull BlockBreakContext context) {
drops.clear();
ItemStack stack = getItemDisplay().getItemStack();
if (!stack.isEmpty()) {
drops.add(stack);
Expand Down
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it perhaps be better behaviour here to make this a PylonFluidTank and just accept any (castable) fluid? I was very confused at first when nothing happened after I piped liquid copper into the casting unit, and it feels unintuitive from a UX perspective as it's inconsistent with what every other fluid block does

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I initially had it like that but the problem is I'd need a dynamic tank size

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you can do that with PylonFluidTank - the capacity can be set after creation. But I think also you could just set a static size of like 2,000 or something like that. or you could do something like the fluid hatch which would be cool, where you have to build a fluid tank casing on top which holds the fluid

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah but if I set it to static

  1. idk what's the biggest cast that's ever gonna be used
  2. It can take more fluid than I wanted, so now I have a whole caster of fluid I don't wanna cast

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

true. tbf someone could just add an 'advanced caster' or something if they need to do that, it's a fairly niche thing, and the fluid hatch approach would allow a lot of fluid to be stored since the later tanks have a lot of capacity. for the second thing - it does encourage the use of the accumulator or a redstone setup which is nice but idk if that's overcomplicating it. I'm conflicted, it would be really nice to be able to see fluid available but I see why maybe this is better, I'm fine with it as-is then I think. though I'd suggest maybe the barrier should change to something else in the GUI since it's always going to be a barrier, which to me indicates something is wrong

Original file line number Diff line number Diff line change
@@ -0,0 +1,232 @@
package io.github.pylonmc.pylon.content.machines.smelting;

import io.github.pylonmc.pylon.recipes.CastingRecipe;
import io.github.pylonmc.rebar.block.RebarBlock;
import io.github.pylonmc.rebar.block.base.RebarDirectionalBlock;
import io.github.pylonmc.rebar.block.base.RebarFluidBlock;
import io.github.pylonmc.rebar.block.base.RebarGuiBlock;
import io.github.pylonmc.rebar.block.base.RebarVirtualInventoryBlock;
import io.github.pylonmc.rebar.block.context.BlockBreakContext;
import io.github.pylonmc.rebar.block.context.BlockCreateContext;
import io.github.pylonmc.rebar.datatypes.RebarSerializers;
import io.github.pylonmc.rebar.fluid.FluidPointType;
import io.github.pylonmc.rebar.fluid.RebarFluid;
import io.github.pylonmc.rebar.i18n.RebarArgument;
import io.github.pylonmc.rebar.item.builder.ItemStackBuilder;
import io.github.pylonmc.rebar.util.MachineUpdateReason;
import io.github.pylonmc.rebar.util.RebarUtils;
import io.github.pylonmc.rebar.util.gui.GuiItems;
import io.github.pylonmc.rebar.util.gui.unit.UnitFormat;
import net.kyori.adventure.text.Component;
import org.bukkit.Material;
import org.bukkit.NamespacedKey;
import org.bukkit.block.Block;
import org.bukkit.block.BlockFace;
import org.bukkit.entity.Player;
import org.bukkit.event.inventory.ClickType;
import org.bukkit.inventory.ItemStack;
import org.bukkit.persistence.PersistentDataContainer;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jspecify.annotations.NonNull;
import xyz.xenondevs.invui.Click;
import xyz.xenondevs.invui.gui.Gui;
import xyz.xenondevs.invui.inventory.OperationCategory;
import xyz.xenondevs.invui.inventory.VirtualInventory;
import xyz.xenondevs.invui.item.AbstractItem;
import xyz.xenondevs.invui.item.ItemProvider;

import java.util.List;
import java.util.Map;

import static io.github.pylonmc.pylon.util.PylonUtils.pylonKey;

public final class CastingUnit extends RebarBlock implements
RebarFluidBlock,
RebarDirectionalBlock,
RebarGuiBlock,
RebarVirtualInventoryBlock {

private static final NamespacedKey QUEUED_CASTS_KEY = pylonKey("queued_casts");
private static final NamespacedKey AUTO_CAST_KEY = pylonKey("auto_cast");

private static final NamespacedKey FLUID_TYPE_KEY = pylonKey("fluid_type");
private static final NamespacedKey FLUID_AMOUNT_KEY = pylonKey("fluid_amount");

private int queuedCasts;
private boolean autoCast;

private @Nullable RebarFluid fluidType;
private double fluidAmount;

private final VirtualInventory castInv = new VirtualInventory(1);
private final VirtualInventory outputInv = new VirtualInventory(1);

@SuppressWarnings("unused")
public CastingUnit(@NotNull Block block, @NotNull BlockCreateContext context) {
super(block, context);
createFluidPoint(FluidPointType.INPUT, BlockFace.NORTH, context, false);
setFacing(context.getFacing());

queuedCasts = 0;
autoCast = false;
fluidType = null;
fluidAmount = 0;
}

@SuppressWarnings({"unused", "DataFlowIssue"})
public CastingUnit(@NotNull Block block, @NotNull PersistentDataContainer pdc) {
super(block, pdc);

queuedCasts = pdc.get(QUEUED_CASTS_KEY, RebarSerializers.INTEGER);
autoCast = pdc.get(AUTO_CAST_KEY, RebarSerializers.BOOLEAN);
fluidType = pdc.get(FLUID_TYPE_KEY, RebarSerializers.REBAR_FLUID);
fluidAmount = pdc.get(FLUID_AMOUNT_KEY, RebarSerializers.DOUBLE);
}

@Override
public void write(@NotNull PersistentDataContainer pdc) {
super.write(pdc);
pdc.set(QUEUED_CASTS_KEY, RebarSerializers.INTEGER, queuedCasts);
pdc.set(AUTO_CAST_KEY, RebarSerializers.BOOLEAN, autoCast);
RebarUtils.setNullable(pdc, FLUID_TYPE_KEY, RebarSerializers.REBAR_FLUID, fluidType);
pdc.set(FLUID_AMOUNT_KEY, RebarSerializers.DOUBLE, fluidAmount);
}

@Override
public void postInitialise() {
castInv.addPreUpdateHandler(event -> {
if (event.getNewItem() == null) return;
for (CastingRecipe recipe : CastingRecipe.RECIPE_TYPE) {
if (recipe.cast().isSimilar(event.getNewItem())) {
return;
}
}
event.setCancelled(true);
});
outputInv.addPreUpdateHandler(RebarUtils.DISALLOW_PLAYERS_FROM_ADDING_ITEMS_HANDLER);
castInv.setGuiPriority(OperationCategory.ADD, 1);
outputInv.setGuiPriority(OperationCategory.COLLECT, 1);
}

@Override
public void onBreak(@NotNull List<@NotNull ItemStack> drops, @NotNull BlockBreakContext context) {
RebarFluidBlock.super.onBreak(drops, context);
RebarVirtualInventoryBlock.super.onBreak(drops, context);
}

@Override
public @NotNull Map<@NotNull String, @NotNull VirtualInventory> getVirtualInventories() {
return Map.of(
"cast", castInv,
"output", outputInv
);
}

private class CastingControlItem extends AbstractItem {

@Override
public @NotNull ItemProvider getItemProvider(@NonNull Player viewer) {
return ItemStackBuilder.gui(queuedCasts > 0 || autoCast ? Material.STRUCTURE_VOID : Material.BARRIER, pylonKey("casting_control"))
.name(Component.translatable("pylon.gui.casting-control.name"))
.lore(Component.translatable(
"pylon.gui.casting-control.lore",
RebarArgument.of("casting", fluidType == null ?
Component.empty() :
Component.translatable(
"pylon.gui.casting-control.casting",
RebarArgument.of("fluid", fluidType.getName()),
RebarArgument.of("amount", UnitFormat.MILLIBUCKETS.format(fluidAmount).decimalPlaces(1))
)
),
RebarArgument.of("queued-casts", queuedCasts),
RebarArgument.of("auto-cast", Component.translatable(autoCast ? "pylon.gui.status.on" : "pylon.gui.status.off"))
));
}

@Override
public void handleClick(@NonNull ClickType clickType, @NonNull Player player, @NonNull Click click) {
if (clickType == ClickType.LEFT && !autoCast) {
queuedCasts++;
} else if (clickType == ClickType.RIGHT && !autoCast && queuedCasts > 0) {
queuedCasts--;
} else if (clickType == ClickType.SHIFT_LEFT) {
autoCast = !autoCast;
queuedCasts = 0;
} else if (clickType == ClickType.SHIFT_RIGHT) {
fluidType = null;
fluidAmount = 0;
}

notifyWindows();
}
}

private final CastingControlItem castingControlItem = new CastingControlItem();

private static final ItemStack CAST_BORDER = ItemStackBuilder.gui(Material.GREEN_STAINED_GLASS_PANE, pylonKey("cast"))
.name(Component.translatable("pylon.gui.cast-border"))
.build();

@Override
public @NotNull Gui createGui() {
return Gui.builder()
.setStructure(
"# # # # # c c c #",
"# # # i # c x c #",
"# # # # # c c c #",
"# # # o o o # # #",
"# # # o y o # # #",
"# # # o o o # # #"
)
.addIngredient('#', GuiItems.background())
.addIngredient('i', castingControlItem)
.addIngredient('c', CAST_BORDER)
.addIngredient('o', GuiItems.output())
.addIngredient('x', castInv)
.addIngredient('y', outputInv)
.build();
}

@Override
public double fluidAmountRequested(@NotNull RebarFluid fluid) {
if (queuedCasts == 0 && !autoCast) return 0;
if (fluidType != null && !fluidType.equals(fluid)) return 0;
ItemStack castItem = castInv.getItem(0);
if (castItem == null) return 0;

for (CastingRecipe recipe : CastingRecipe.RECIPE_TYPE) {
if (recipe.isInput(fluid) && castItem.isSimilar(recipe.cast())) {
if (outputInv.simulateSingleAdd(recipe.result()) > 0) return 0;
return recipe.input().amountMillibuckets() - fluidAmount;
}
}

return 0;
}

@Override
public void onFluidAdded(@NotNull RebarFluid fluid, double amount) {
if (queuedCasts == 0 && !autoCast) throw new AssertionError("Should not happen");
if (fluidType != null && !fluidType.equals(fluid)) throw new AssertionError("Should not happen");
ItemStack castItem = castInv.getItem(0);
if (castItem == null) throw new AssertionError("Should not happen");

for (CastingRecipe recipe : CastingRecipe.RECIPE_TYPE) {
if (recipe.isInput(fluid) && castItem.isSimilar(recipe.cast())) {
fluidType = fluid;
fluidAmount += amount;
if (Math.abs(fluidAmount - recipe.input().amountMillibuckets()) < 1e-6) {
fluidType = null;
fluidAmount = 0;
outputInv.addItem(new MachineUpdateReason(), recipe.result());
if (!autoCast) {
queuedCasts--;
}
}
castingControlItem.notifyWindows();
break;
}
}
}
}
Loading
Loading