Skip to content

Bugfix/Cleanup/Polish Pass#1071

Open
JustAHuman-xD wants to merge 26 commits into
masterfrom
human/pylon-polish-pass
Open

Bugfix/Cleanup/Polish Pass#1071
JustAHuman-xD wants to merge 26 commits into
masterfrom
human/pylon-polish-pass

Conversation

@JustAHuman-xD

@JustAHuman-xD JustAHuman-xD commented Jun 29, 2026

Copy link
Copy Markdown
Contributor

requires: pylonmc/rebar#862

Went through a lot of pylon (though attempting to exclude a lot of what's being touched by electricity) and fixed various bugs, improved performance, and just cleaned up code

A few things were rewritten to address major bugs or issues

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Rewrote this as there were a lot of edge cases with the effect, its removal, cooldown, etc, that were not properly handled

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Rewrote this to fix #779

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

There were a lot of oddities with how Rune & the related interfaces worked, as well as just undocumented behavior for the implementing class, I rewrote it to be a lot more straightforward, cleaner, etc

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

This is the new version of the old RuneApplicable interface

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I rewrote and abstracted this into VeinminerTool so that we can do other tools which utilize the same logic while fixing a few bugs with the original implementation

ItemStack input = fuelInputHatch.inventory.getItem(0);
if (input != null && !RebarItem.isRebarItem(input)) {
ItemStack input = fuelInputHatch.inventory.getUnsafeItem(0);
if (input != null && !RebarItem.isRebarItemAndIsNot(input, VanillaFurnaceFuel.class)) {

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

fixed this not respecting VanillaFurnaceFuel

Comment on lines 184 to 198
public void tryConsumeFuel() {
ItemInputHatch inputHatch = getMultiblockComponentOrThrow(ItemInputHatch.class, ITEM_INPUT);
ItemStack stack = inputHatch.inventory.getItem(0);
if (stack == null || RebarItem.isRebarItem(stack) || stack.isEmpty()) {
ItemStack stack = inputHatch.inventory.getUnsafeItem(0);
if (stack == null || RebarItem.isRebarItemAndIsNot(stack, VanillaFurnaceFuel.class)) {
return;
}

ItemType itemType = stack.getType().asItemType();
if (itemType == null) {
if (itemType == null || !itemType.isFuel()) {
return;
}

inputHatch.inventory.setItem(new MachineUpdateReason(), 0, stack.subtract());
RebarUtils.unsafeSubtract(inputHatch.inventory, 0, 1);
startProcess(itemType.getBurnDuration() / 10);
}

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Fixed this consuming any item regardless of if it was fuel or not

Comment on lines +193 to +198
ItemType type = fuel.getType().asItemType();
if (type == null || !type.isFuel()|| RebarItem.isRebarItemAndIsNot(fuel, VanillaFurnaceFuel.class)) {
return;
}

RebarUtils.unsafeSubtract(fuelInventory, 0, 1);

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Fixed this not respecting if the item was actually fuel

Comment on lines -216 to +230
gypsum.remove();
BlockStorage.placeBlock(against, PylonKeys.BLOOMERY);
fire.setType(Material.AIR);
if (BlockStorage.placeBlock(against, PylonKeys.BLOOMERY) != null) {
Item gypsumDust = (Item) gypsumDusts.iterator().next();
ItemStack gypsumStack = gypsumDust.getItemStack();
gypsumStack.subtract();
gypsumDust.setItemStack(gypsumStack);
fire.setType(Material.AIR);
}

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

fixed this not respecting it the bloomery placement fails

Comment on lines +239 to +242
ItemType type = fuel.getType().asItemType();
if (type == null || !type.isFuel() || RebarItem.isRebarItemAndIsNot(fuel, VanillaFurnaceFuel.class)) {
return;
}

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Fixed it not respecting if it was a fuel item or not

@@ -57,24 +57,31 @@ public void removeEffect(@NotNull Player player) {
public static class FarmingTalismanListener implements Listener {
@EventHandler
public void onBlockBreak(BlockDropItemEvent event) {

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Fixed a bug where the trigger sound would play more than once

Comment on lines 124 to 129
/**
* This method is called when an item is inserted into the pedestal. It can be used to check if the item is
* allowed to be inserted.
*
* @return true if the item can be inserted into the pedestal, false otherwise
* @return true if the item can be placed on the pedestal, false otherwise
*/
public boolean isIllegalItem(Player player, ItemStack stack) {
return false;
public boolean canPlaceItem(Player player, ItemStack stack) {
return true;
}

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Fixed an issue where the javadoc was telling the opposite of what the method actually was

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Fixed a few bugs where the fireproof rune only considered an item to be fireproof if it was only fireproof (i.e. not immune to other different damage types) and where when making an item fireproof it would clear the existing damage immunities if they were there

if (curStack.getItemMeta().getPersistentDataContainer().has(SOULBOUND_KEY)) {
event.getItemsToKeep().add(curStack);
curItem.remove();
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Fixed a bug where this might operate when the player death event was cancelled

.set(DataComponentTypes.FIREWORK_EXPLOSION, FireworkEffect.builder()
.withColor(Color.PURPLE)
.build())
.editPdc(pdc -> pdc.set(SoulboundRune.SOULBOUND_KEY, RebarSerializers.BOOLEAN, true))

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Fixed a bug where the soulbound rune wasnt soulbound

Comment on lines +107 to +109
for (ItemStack drop : event.getDrops()) {
drainBlock.getWorld().dropItemNaturally(drainBlock.getLocation().toCenterLocation(), drop);
}

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

fixed a bug where this wouldn't respect any drops added by listeners of the event

Comment on lines +110 to +112
FluidLevelChangeEvent event = new FluidLevelChangeEvent(placeBlock, material.createBlockData());
if (event.callEvent()) {
placeBlock.setBlockData(event.getNewData());

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Fixed a bug where this wouldn't respect any modifications by listeners of the event

@JustAHuman-xD

Copy link
Copy Markdown
Contributor Author

This would supercede #1060 and #1069

Comment thread src/main/java/io/github/pylonmc/pylon/content/machines/smelting/Bloomery.java Outdated
Comment thread src/main/java/io/github/pylonmc/pylon/content/tools/base/Rune.java
Comment thread src/main/java/io/github/pylonmc/pylon/content/tools/LumberAxe.java
Comment thread src/main/java/io/github/pylonmc/pylon/content/tools/LumberAxe.java Outdated
Comment thread src/main/java/io/github/pylonmc/pylon/content/tools/LumberAxe.java
Comment thread src/main/java/io/github/pylonmc/pylon/content/tools/LumberAxe.java
Comment thread src/main/java/io/github/pylonmc/pylon/content/machines/fluid/FluidPlacer.java Outdated
@JustAHuman-xD JustAHuman-xD requested review from LordIdra and balugaq July 8, 2026 06:08
}

private boolean cannotVeinMine(Player player, Set<BlockPosition> vein) {
return vein.size() >= getMaxVeinSize() || getStack().isEmpty() || RebarUtils.hasOneDurabilityLeft(getStack()) || !getStack().equals(player.getInventory().getItemInMainHand());

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

It seems !getStack().equals(player.getInventory().getItemInMainHand()) always returns true
and RebarUtils.hasOneDurabilityLeft(getStack()) may not work for the tool may be enchanted with Unbreaking or in case that other plugins modify it.

QQ20260708-142726.mp4

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

the equals is not guaranteed to be true precisely because other plugins may interfere, I can remove the one durability clause and delay the breakage by a tick if you want instead, I just preferred it to all happen at the same time

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

just remove the one durability clause, getStack().isEmpty() will stop the veinmining action.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Can't do that because that causes the "one durability breaks 2 blocks bug"

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

It is because the origin event also breaks a block.
Just cancel the event pass into onBreakBlock, and we can take control of the whole break action. (also needs to make some changes at OFFSETS, put the nearest direction in the front)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I mean just search the blocks like how water spread.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I fail to see why or how I would do that. Also water spreads in a very weird and context specific way that does not really apply here

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

water spreads in a very weird and context specific way

What context you mean?

I fail to see why or how I would do that

see https://github.com/pylonmc/pylon/pull/1060/changes

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

That still does effectively the same recursion, is less flexible, and also just isn't how water spreads

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I don't think it causes recursion and it's less flexible., can you give some examples..?

Comment on lines +95 to +98
public abstract boolean canVeinmine(Block root);
public boolean isInVein(Block root, Block block) {
return root.getType() == block.getType();
}

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Needs some docs on these two methods, I was confused before I realized the difference of canVeinmine and isInVein

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I mean I can add them but the method name & signature are entirely different & imply completely different things so I don't really know how you'd get confused

@balugaq balugaq Jul 8, 2026

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

canVeinmine means for me: if the block can be veinmined.
I don't know what is root block means at first:

  1. it only means the first block I break
  2. or does the block near the first block is also considered as root block?

and when is it called:

  1. it only checks the first block I break
  2. or does this also used to check if the block can be veinmined when each time called tryVeinMine?

I would prefer to rename canVeinmine to canStartVeinmine

VEIN_MINING.remove(playerId);
}

public void tryVeinMine(Player player, Block root, Location rootLocation, Block block, Set<BlockPosition> vein) {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Hm that wasn't happening for me, are you sure you didn't change the setting for the vein limit or something?

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Does no change the setting. and it works well the first time I use it, I'm trying to reproduce it.

QQ_1783493527002

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

The set vein is used to record what block is broken. But a position may be visited many times, which causes player.breakBlock(block) returns false and remove the position
QQ_1783497307872

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

No because vein is a set and if it fails to add to it, it returns, also it it was already broken and air it wouldn't even reach player break block

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

QQ_1783498300342

Just find something weird, it logs continuously but suddenly vein.size turns to 2, unless it was cleared I can't find any other remove action in the code...

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Well, now I know why.

return;
}

BlockPosition position = new BlockPosition(block);

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

not sure if it needs a world border check

Comment thread src/main/java/io/github/pylonmc/pylon/content/tools/VeinminingTool.java Outdated
Co-authored-by: balugaq <129668183+balugaq@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

3 participants