Skip to content

Commit

Permalink
Fix redstone still breaking when placed on exchanged blocks after Vaz…
Browse files Browse the repository at this point in the history
…kiiMods#4316 (VazkiiMods#4330)

This reverts back to the original implementation I had for preventing
blocks attached to replaced blocks from breaking.

After further testing I found that the current solution only works for
simple things like torches, but not more complex things like redstone
dust.
  • Loading branch information
jpenilla authored Apr 18, 2023
1 parent 9c94927 commit f6d01ae
Show file tree
Hide file tree
Showing 6 changed files with 99 additions and 14 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package vazkii.botania.common;

public interface CollectingNeighborUpdaterAccess {
void botania$pauseUpdates();

void botania$resumeUpdates();
}
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
import net.minecraft.world.level.block.IronBarsBlock;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.redstone.NeighborUpdater;
import net.minecraft.world.phys.BlockHitResult;
import net.minecraft.world.phys.HitResult;
import net.minecraft.world.phys.Vec3;
Expand All @@ -51,10 +52,12 @@
import vazkii.botania.api.item.WireframeCoordinateListProvider;
import vazkii.botania.api.mana.ManaItemHandler;
import vazkii.botania.client.gui.ItemsRemainingRenderHandler;
import vazkii.botania.common.CollectingNeighborUpdaterAccess;
import vazkii.botania.common.block.PlatformBlock;
import vazkii.botania.common.helper.ItemNBTHelper;
import vazkii.botania.common.helper.PlayerHelper;
import vazkii.botania.common.item.StoneOfTemperanceItem;
import vazkii.botania.mixin.LevelAccessor;
import vazkii.botania.xplat.XplatAbstractions;

import java.util.ArrayList;
Expand Down Expand Up @@ -254,19 +257,29 @@ public int exchange(Level world, Player player, BlockPos pos, ItemStack rod, Ite
&& stateAt.getBlock().asItem() != replacement) {
float hardness = stateAt.getDestroySpeed(world, pos);
if (!world.isClientSide) {
world.destroyBlock(pos, !player.getAbilities().instabuild, player, 0);
BlockHitResult hit = new BlockHitResult(getHitPos(rod, pos), getSwapTemplateDirection(rod), pos, false);
InteractionResult result = PlayerHelper.substituteUse(new UseOnContext(player, InteractionHand.MAIN_HAND, hit), placeStack);
// TODO: provide an use context that overrides player facing direction/yaw?
// currently it pulls from the player directly

if (!player.getAbilities().instabuild) {
if (result.consumesAction()) {
removeFromInventory(player, rod, replacement, true);
displayRemainderCounter(player, rod);
} else {
((ServerLevel) world).sendParticles(ParticleTypes.LARGE_SMOKE, pos.getX() + 0.5D, pos.getY() + 0.5D, pos.getZ() + 0.5D,
2, 0.1, 0.1, 0.1, 0);
final NeighborUpdater neighborUpdater = ((LevelAccessor) world).getNeighborUpdater();
try {
if (neighborUpdater instanceof CollectingNeighborUpdaterAccess access) {
access.botania$pauseUpdates();
}
world.destroyBlock(pos, !player.getAbilities().instabuild, player);
BlockHitResult hit = new BlockHitResult(getHitPos(rod, pos), getSwapTemplateDirection(rod), pos, false);
InteractionResult result = PlayerHelper.substituteUse(new UseOnContext(player, InteractionHand.MAIN_HAND, hit), placeStack);
// TODO: provide an use context that overrides player facing direction/yaw?
// currently it pulls from the player directly

if (!player.getAbilities().instabuild) {
if (result.consumesAction()) {
removeFromInventory(player, rod, replacement, true);
displayRemainderCounter(player, rod);
} else {
((ServerLevel) world).sendParticles(ParticleTypes.LARGE_SMOKE, pos.getX() + 0.5D, pos.getY() + 0.5D, pos.getZ() + 0.5D,
2, 0.1, 0.1, 0.1, 0);
}
}
} finally {
if (neighborUpdater instanceof CollectingNeighborUpdaterAccess access) {
access.botania$resumeUpdates();
}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package vazkii.botania.mixin;

import net.minecraft.world.level.redstone.CollectingNeighborUpdater;

import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;

import vazkii.botania.common.CollectingNeighborUpdaterAccess;

@Mixin(CollectingNeighborUpdater.class)
abstract class CollectingNeighborUpdaterMixin implements CollectingNeighborUpdaterAccess {
@Shadow
private int count;
@Shadow
@Final
private int maxChainedNeighborUpdates;

@Shadow
protected abstract void runUpdates();

@Unique
private boolean delayUpdates = false;

@Inject(method = "runUpdates", at = @At("HEAD"), cancellable = true)
void skipUpdatesWhenDelayed(final CallbackInfo ci) {
if (this.delayUpdates
// It's possible to just temporarily change the max chained updates, but I don't think
// we will normally get to that amount anyway as we pause/resume updates for each single block
// we exchange, and the limit is 1000000 by default
&& this.count < this.maxChainedNeighborUpdates) {
ci.cancel();
}
}

@Override
public void botania$pauseUpdates() {
this.delayUpdates = true;
}

@Override
public void botania$resumeUpdates() {
this.delayUpdates = false;
this.runUpdates();
}
}
13 changes: 13 additions & 0 deletions Xplat/src/main/java/vazkii/botania/mixin/LevelAccessor.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package vazkii.botania.mixin;

import net.minecraft.world.level.Level;
import net.minecraft.world.level.redstone.NeighborUpdater;

import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.gen.Accessor;

@Mixin(Level.class)
public interface LevelAccessor {
@Accessor("neighborUpdater")
NeighborUpdater getNeighborUpdater();
}
2 changes: 2 additions & 0 deletions Xplat/src/main/resources/botania_xplat.mixins.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
"BiomeAccessor",
"BlockModelGeneratorsAccessor",
"BushBlockMixin",
"CollectingNeighborUpdaterMixin",
"CreeperAccessor",
"CreeperMixin",
"CriteriaTriggersAccessor",
Expand All @@ -29,6 +30,7 @@
"ItemEntityAccessor",
"ItemEntityMixin",
"ItemMixin",
"LevelAccessor",
"LivingEntityAccessor",
"LoomMenuMixin",
"LoomMenuPatternSlotMixin",
Expand Down
2 changes: 1 addition & 1 deletion web/changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ and start a new "Upcoming" section.
* Change: Instead of always cooling down for 5 minutes, thermalilies now have a random cooldown between 20 seconds and 5 minutes. For automation, you can read how long the cooldown is with a comparator
* Change: Entropinnyum's "unethical TNT" detection was changed, it's now more accurate and shouldn't cause any false positives
* Change: Flower pouches now render missing flowers transparently, and render a "1" next to stacks with one item
* Change: Rod of the Shifting Crust now only processes neighbor updates for the replaced block and not the removed block, meaning torches or other blocks attached to exchanged blocks will no longer break as long as the new block can still support it
* Change: Rod of the Shifting Crust now delays processing neighbor updates until the block is replaced, meaning torches or other blocks attached to exchanged blocks will no longer break as long as the new block can still support it
* Fix: Mana spreaders now update their mana levels in real time, like pools do
* Fix: Red stringed containers now always report and accessible inventory, so that corporea sparks will not pop off them
* Fix: The fallback vanilla item transfer implementation in corporea now correctly updates inventories after taking items (this bug was not directly accessible, since neither fabric nor forge use this fallback implementation)
Expand Down

0 comments on commit f6d01ae

Please sign in to comment.