Skip to content

Conversation

@Intybyte
Copy link
Member

Fixes #299

@Seggan
Copy link
Member

Seggan commented Nov 14, 2025

The linked issue should be accomplished by allowing melting rocks into a smeltery imo

@Seggan
Copy link
Member

Seggan commented Nov 14, 2025

Instead of adding a whole new machine

@Intybyte
Copy link
Member Author

The linked issue should be accomplished by allowing melting rocks into a smeltery imo

That feels like shooting ducks with a cannon tho

@Seggan
Copy link
Member

Seggan commented Nov 15, 2025

That feels like shooting ducks with a cannon tho

Ain't no one gonna stop me

Copy link
Contributor

@LordIdra LordIdra left a comment

Choose a reason for hiding this comment

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

This is almost identical to the mixing pot as it stands.

I would suggest instead to do what 'modded' crucibles do, where items that get thrown in are consumed (one by one) and then slowly melted. So you throw cobblestone in, and over 25 seconds, 4 mb of lava are added per second. Then, it's ready to consume the next cobblestone you throw in. (And also produces smoke gradually as it goes).

This makes balancing much easier and differentiates this enough to make it worth having alongside the mixing pot

@Intybyte Intybyte marked this pull request as draft November 19, 2025 19:55
@Intybyte Intybyte marked this pull request as ready for review November 20, 2025 16:40
@Intybyte
Copy link
Member Author

This is almost identical to the mixing pot as it stands.

I would suggest instead to do what 'modded' crucibles do, where items that get thrown in are consumed (one by one) and then slowly melted. So you throw cobblestone in, and over 25 seconds, 4 mb of lava are added per second. Then, it's ready to consume the next cobblestone you throw in. (And also produces smoke gradually as it goes).

This makes balancing much easier and differentiates this enough to make it worth having alongside the mixing pot

Ok did something very similar to modded, instead of having it tick every second and add it gradually (which with many crucibles it might be unnecessarily performance intensive), I made it melt a block every X ticks, just like modded crucibles depending on the heat source below, it will change the melting speed

@LordIdra
Copy link
Contributor

Not building with latest core (do I need to use a specific branch?)
image

@Intybyte
Copy link
Member Author

Not building with latest core (do I need to use a specific branch?) image

Didn't push to core, mb

@Intybyte
Copy link
Member Author

Intybyte commented Nov 26, 2025

Requires pylonmc/pylon-core#512

@Intybyte Intybyte marked this pull request as draft November 27, 2025 17:30
@Seggan Seggan changed the title Crucible [ref:vaan/feature/crucible] Crucible Dec 5, 2025
@Seggan
Copy link
Member

Seggan commented Dec 5, 2025

(changed name so itll compile)

@Intybyte
Copy link
Member Author

Intybyte commented Dec 5, 2025

I think it is done?

@Intybyte Intybyte marked this pull request as ready for review December 5, 2025 20:24
Copy link
Contributor

@LordIdra LordIdra left a comment

Choose a reason for hiding this comment

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

Sorry, have realised I forgot to review this in my last PR crusade

Nice work on this, it looks better now. A couple of general things

  • The fluid being displayed as water when you're melting lava is really awkward. I don't know if this PR is the place to address it given it is also a mixing pot issue as well but thought I'd mention it in case. (Open an issue if you don't want to address it here)
  • Fire / soul fire does not display correctly in the guide (again not sure if this is an issue for this PR, open an issue if not)
  • The particles are afaict the exact same as the mixing pot. I don't think they really suit the crucible and it feels a bit unpolished.
  • I would probably avoid showing the items that can be used to heat the crucible. We can add a separate page for this when the disambiguation system is in.
  • It would be great to have some way to see what is inside the crucible waiting to be melted. There's no way to know ATM. Maybe WAILA?
  • Fluid output does not appear to work. Not sure why:
image

@LordIdra
Copy link
Contributor

Another thing rq - I think it makes more sense for the smelt time to be an attribute of the recipe than the crucible

@Intybyte
Copy link
Member Author

* The fluid being displayed as water when you're melting lava is really awkward. I don't know if this PR is the place to address it given it is also a mixing pot issue as well but thought I'd mention it in case. (Open an issue if you don't want to address it here)

This is also for the mixing pot, maybe we can make it similar to how tank behave for both of them, but maybe in another issue

* Fire / soul fire does not display correctly in the guide (again not sure if this is an issue for this PR, open an issue if not)

It is intended, we use barrier as fallback, there is no item to display fire anymore

* The particles are afaict the exact same as the mixing pot. I don't think they really suit the crucible and it feels a bit unpolished.

Yeah, what should i use? maybe lava particles? will experiment this once the PR is done and working

* I would probably avoid showing the items that can be used to heat the crucible. We can add a separate page for this when the disambiguation system is in.

So in the future?

* It would be great to have some way to see what is inside the crucible waiting to be melted. There's no way to know ATM. Maybe WAILA?

I can display {ITEMNAME} x{AMOUNT}, I hope the WAILA won't get too messy

* Fluid output does not appear to work. Not sure why:

Not sure what you are doing with that, but I am using fluid tanks and it works

Also noticed that the getTickInterval doesn't work anymore as expected, maybe there was a change idk, how it is saved as a constant instead in the code that handles tickers, might want to undo it back to allow more flexible behaviours such as this, otherwise i will need to have it unnecessarly tick a lot of often just to run sleeps inside

@LordIdra
Copy link
Contributor

It is intended, we use barrier as fallback, there is no item to display fire anymore

I use flint and steel here for the mixing pot iirc. Might be good to fall back to that instead for [soul] fire? This looks like an error from the user's perspective

Yeah, what should i use? maybe lava particles? will experiment this once the PR is done and working

not sure. I don't think lava particles would work because it's not only lava in the pot. Maybe like ash / smoke particles, or do lava particles or water particles depending on what's in the pot?

So in the future?

Yeah I just wouldn't add this rn because we'll remove it soon anyway

I can display {ITEMNAME} x{AMOUNT}, I hope the WAILA won't get too messy

👍

Not sure what you are doing with that, but I am using fluid tanks and it works

oh I'm just a buffoon, I was trying to get lava out with the wrong pipes mb

Also noticed that the getTickInterval doesn't work anymore as expected, maybe there was a change idk, how it is saved as a constant instead in the code that handles tickers, might want to undo it back to allow more flexible behaviours such as this, otherwise i will need to have it unnecessarly tick a lot of often just to run sleeps inside

Really confused, what do you mean?

@Intybyte
Copy link
Member Author

I use flint and steel here for the mixing pot iirc. Might be good to fall back to that instead for [soul] fire? This looks like an error from the user's perspective

I can make a small fallback map and add some exceptions like fire, but that isn't something I want to really think about maintain every time a similar situation happens

Really confused, what do you mean?

The idea was to have a variable tickInterval in order to not tick when unnecessary, however now, TickManager#startTicker obtains the tickInterval once and always uses that one, I am pretty sure it wasn't like that before and it worked, now it does not, it would be an easy fix on core, otherwise i would have to resort to the other thing I said

@LordIdra
Copy link
Contributor

I can make a small fallback map and add some exceptions like fire, but that isn't something I want to really think about maintain every time a similar situation happens

It's just adding items to a map when we find them, it's not really a high maintenance thing. That doesn't seem like a thing to worry about tbh

The idea was to have a variable tickInterval in order to not tick when unnecessary, however now, TickManager#startTicker obtains the tickInterval once and always uses that one, I am pretty sure it wasn't like that before and it worked, now it does not, it would be an easy fix on core, otherwise i would have to resort to the other thing I said

I don't understand what you're saying. What does 'variable tickInterval in order to not tick when unnecessary' or 'obtains the tickInterval once and always uses that one' mean?? can you give an example maybe?

@Intybyte
Copy link
Member Author

the method getTickInterval is called, and returns after how much time next tick is, normally it is saved on a constant variable inside the TickManager.

in this case, possibly in others, the getTickInterval output isn't constant, in this case it depends on the block below the crucible.

however the tickInterval used in the coroutine is set in stone, it can't be changed, even if it is supposed to be changed in order to tick faster, as maybe the player instead of using a torch below the crucible puts a lava bucket.

Proposal: every time after the tick is processed, instead of using a saved constant value, call getTickInterval every time

@LordIdra
Copy link
Contributor

the method getTickInterval is called, and returns after how much time next tick is, normally it is saved on a constant variable inside the TickManager.

in this case, possibly in others, the getTickInterval output isn't constant, in this case it depends on the block below the crucible.

however the tickInterval used in the coroutine is set in stone, it can't be changed, even if it is supposed to be changed in order to tick faster, as maybe the player instead of using a torch below the crucible puts a lava bucket.

Proposal: every time after the tick is processed, instead of using a saved constant value, call getTickInterval every time

Oh I see. So you're just saying that setTickInterval has no effect if called after being set for the first time?

@Intybyte
Copy link
Member Author

the method getTickInterval is called, and returns after how much time next tick is, normally it is saved on a constant variable inside the TickManager.
in this case, possibly in others, the getTickInterval output isn't constant, in this case it depends on the block below the crucible.
however the tickInterval used in the coroutine is set in stone, it can't be changed, even if it is supposed to be changed in order to tick faster, as maybe the player instead of using a torch below the crucible puts a lava bucket.
Proposal: every time after the tick is processed, instead of using a saved constant value, call getTickInterval every time

Oh I see. So you're just saying that setTickInterval has no effect if called after being set for the first time?

No, but yes, that is also a consequence, i am not using setTickInterval at all in this example, i am directly overriding getTickInterval in this case

@LordIdra
Copy link
Contributor

Have you tried calling setTickInterval to set the new tick rate when needed?

@LordIdra
Copy link
Contributor

Ah wait I see. So in PylonTickingBlock 'val tickDelay = pylonBlock.tickInterval' is called before the loop. Yeah you can just change that to call getTickInterval each time and then it should work

@Intybyte
Copy link
Member Author

Requires pylonmc/pylon-core#521

Copy link
Contributor

@LordIdra LordIdra left a comment

Choose a reason for hiding this comment

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

Just a couple more small things I noticed.

Another thing, the ticking rate seems to have gone up a LOT, like it chomps up cobblestone like crazy now. Assuming this isn't intended?

@Intybyte
Copy link
Member Author

Just a couple more small things I noticed.

Another thing, the ticking rate seems to have gone up a LOT, like it chomps up cobblestone like crazy now. Assuming this isn't intended?

yes, it depends on the block below, if you use lava it is supposed to be a LOT faster, if you use a torch, it should have same behaviour as before (minimum speed)

Copy link
Member

@Seggan Seggan left a comment

Choose a reason for hiding this comment

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

Played around with it ingame, ngl I would prefer you throwing in items instead of right clicking the crucible. Barring that, at least a way to get the items out pls?

}

@NoArgsConstructor(access = AccessLevel.PRIVATE)
public static final class HeatManager {
Copy link
Member

Choose a reason for hiding this comment

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

Why is this class needed?

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 wanted to extract the whole Heat handling tbh, but I am not sure where

Copy link
Contributor

Choose a reason for hiding this comment

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

I don't think this should be in the recipe type, as it's to do with the crucible, not the recipe type. I don't think this needs to be a whole separate class either, you can just have static fields / methods in Crucible - this is what we do with other blocks when we have some kind of registry associated with them

animate(display, 0, duration, matrix);
}

public static @NotNull ItemStack makeItem(@NotNull NamespacedKey key) {
Copy link
Member

Choose a reason for hiding this comment

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

What do these functions do?

Copy link
Member Author

Choose a reason for hiding this comment

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

... make items?

Copy link
Contributor

Choose a reason for hiding this comment

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

Could we call this itemFromKey? it's not really obvious what 'make item' means at first glance

@@ -0,0 +1,29 @@
pylonbase:cobblestone_to_lava:
input-item:
minecraft:cobblestone: 1
Copy link
Member

Choose a reason for hiding this comment

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

use #pyloncore:rocks instead

Copy link
Member Author

Choose a reason for hiding this comment

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

deja vu? XD

immagine

Copy link
Contributor

@LordIdra LordIdra left a comment

Choose a reason for hiding this comment

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

You should be able to put in items when it's not heated. Right now you can't. I think making this not a multiblock will fix that.

import static io.github.pylonmc.pylon.base.util.BaseUtils.baseKey;

public final class Crucible extends PylonBlock implements PylonMultiblock, PylonInteractBlock, PylonFluidTank, PylonCauldron, PylonBreakHandler, PylonTickingBlock {
public final int CAPACITY = getSettings().getOrThrow("capacity", ConfigAdapter.INT);
Copy link
Contributor

Choose a reason for hiding this comment

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

Nit but should be capacity (same for smelt_time)

Comment on lines +154 to +167
public void clearInventory() {
this.processingType = null;
this.amount = 0;
}

public boolean isValid(ItemStack item) {
for(var entry : CrucibleRecipe.RECIPE_TYPE.getRecipes()) {
if (entry.matches(item)) {
return true;
}
}

return false;
}
Copy link
Contributor

Choose a reason for hiding this comment

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

These two don't really seem like they should be helper methods as they're so simple. If you really want isValid, it should probably be a method on the recipe type instead

Copy link
Member Author

Choose a reason for hiding this comment

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

clearInventory is meant in case someone wants to clear the inventory from code, i can move is valid

Comment on lines +173 to +176
if (recipe.matches(processingType)) {
if (!new PrePylonCraftEvent<>(CrucibleRecipe.RECIPE_TYPE, recipe, this, null).callEvent()) {
continue;
}
Copy link
Contributor

Choose a reason for hiding this comment

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

These two ifs can be collapsed into one if

Copy link
Member Author

Choose a reason for hiding this comment

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

keeping it like that for clarity and because everywhere else in the code has always been like this, so for consistency,also not really imporant as you wanted to remove those events no?

Comment on lines +216 to +229
@Override
public @NotNull Set<@NotNull ChunkPosition> getChunksOccupied() {
return Set.of(new ChunkPosition(getBlock()));
}

@Override
public boolean checkFormed() {
return getHeatFactor() != null;
}

@Override
public boolean isPartOfMultiblock(@NotNull Block otherBlock) {
return otherBlock.equals(getBelow());
}
Copy link
Contributor

Choose a reason for hiding this comment

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

I don't think this needs to be a multiblock. It'll be simpler that way and the performance impact is negligible. I know that other blocks like the mixing pot do this, but I have removed this in an open PR

Comment on lines +315 to +317
public @NotNull Block getBelow() {
return getBlock().getRelative(BlockFace.DOWN);
}
Copy link
Contributor

Choose a reason for hiding this comment

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

This doesn't really seem like it needs to be a helper method, there isn't really any benefit to not just inlining this afaict


if (material.isItem()) {
return new ItemStack(material);
} else {
Copy link
Contributor

Choose a reason for hiding this comment

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

nit redundant else

animate(display, 0, duration, matrix);
}

public static @NotNull ItemStack makeItem(@NotNull NamespacedKey key) {
Copy link
Contributor

Choose a reason for hiding this comment

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

I feel like I might have mentioned this already, but this seems like a common enough thing that it should be a core util. In fact, don't we already do something similar when deserializing recipe inputs? Presumably the logic from there could just be extracted

crucible:
name: "Crucible"
lore: |-
<arrow> Place items in the crucible and <insn>right click</insn> to melt them
Copy link
Contributor

Choose a reason for hiding this comment

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

The lore is incorrect. You need to right click to put items inside the crucible and then it melts them

Comment on lines +339 to +348
pylonbase:crucible:
pattern:
- "C C"
- "C C"
- "CCC"
key:
C: minecraft:brick
result: pylonbase:crucible
category: building

Copy link
Contributor

Choose a reason for hiding this comment

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

Might it be worth making this refractory brick? It would make sense, add another use case for refractory brick, and also gate a potentially very powerful item (practically infinite lava) a bit further along

Copy link
Member Author

Choose a reason for hiding this comment

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

wasn't the curcible mean for early game though

Copy link
Contributor

Choose a reason for hiding this comment

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

Not specifically. I was thinking it might be for skyblock, but I think there are a number of recipes you might need to modify anyway for that and you can easily do that now that recipes are data driven

Comment on lines +198 to +208
new ParticleBuilder(Particle.SPLASH)
.count(20)
.location(getBlock().getLocation().toCenterLocation().add(0, 0.5, 0))
.offset(0.3, 0, 0.3)
.spawn();

new ParticleBuilder(Particle.CAMPFIRE_COSY_SMOKE)
.count(30)
.location(getBlock().getLocation().toCenterLocation())
.extra(0.05)
.spawn();
Copy link
Contributor

Choose a reason for hiding this comment

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

I think in terms of the particles you could just continually spawn ash + smoke particles every 10 ticks or so and that would look pretty good

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add a way to obtain lava more sustainably

4 participants