Package me.hackware.api
Class BlockPlacementManager
java.lang.Object
me.hackware.api.BlockPlacementManager
Centralized block-placement manager.
Handles placement rate-limiting, per-block cooldowns, air-place, rotation,
offhand swap tricks, and placement sounds.
Configuration is read through AntiCheatBridge.PlacementPolicy.
Ported from Meteor's BlockPlacementManager, adapted to Hackware APIs and Mojang mappings.
-
Nested Class Summary
Nested Classes -
Method Summary
Modifier and TypeMethodDescriptionbooleanbeginPlacement(List<net.minecraft.core.BlockPos> positions, net.minecraft.world.item.Item item) Begins a placement transaction with a list of positions.booleanbeginPlacement(net.minecraft.core.BlockPos position, net.minecraft.world.level.block.state.BlockState state, net.minecraft.world.item.Item item) Begins a placement transaction.static booleancanPlaceOver(net.minecraft.core.BlockPos pos) Returns true if a block can be placed at this position (either the block is replaceable, or it's an insta-breakable block that BPM will clear with a break packet before placing).booleancheckPlacement(net.minecraft.world.item.Item item, net.minecraft.core.BlockPos blockPos) booleancheckPlacement(net.minecraft.world.item.Item item, net.minecraft.core.BlockPos blockPos, net.minecraft.world.level.block.state.BlockState state) booleancheckPlacement(net.minecraft.world.item.Item item, net.minecraft.core.BlockPos blockPos, net.minecraft.world.level.block.state.BlockState state, net.minecraft.world.level.block.state.BlockState desiredState) voidvoidforceResetPlaceCooldown(net.minecraft.core.BlockPos blockPos) static BlockPlacementManagerget()intReturns packets sent in the current rate-limit window (0 when idle/reset).static net.minecraft.core.DirectiongetPlaceOnDirection(net.minecraft.core.BlockPos pos) intReturns how many placement packets can still be sent in the current rate-limit window.longReturns the timestamp the current rate-limit window started, or -1 if idle.voidinit()Register event handlers.static booleanisInstaBreakAndShouldClear(net.minecraft.world.level.block.state.BlockState state, net.minecraft.core.BlockPos blockPos) Returns true if the given non-replaceable block can be insta-broken (zero hardness) and therefore should be cleared with a break packet immediately before placement.booleanisOnPlaceCooldown(net.minecraft.core.BlockPos blockPos) Returns true if the position is still on per-block retry cooldown.booleanplaceBlock(net.minecraft.world.item.Item item, net.minecraft.core.BlockPos blockPos) Places a single block.booleanplaceBlock(net.minecraft.world.item.Item item, net.minecraft.core.BlockPos blockPos, boolean ignorePerBlockCooldown) Placement variant that can bypass the per-position retry cooldown (AntiCheatBridge.PlacementPolicy.perBlockCooldownMs()).booleanplaceBlock(net.minecraft.world.item.Item item, net.minecraft.core.BlockPos blockPos, net.minecraft.world.level.block.state.BlockState state) booleanplaceBlock(net.minecraft.world.item.Item item, net.minecraft.core.BlockPos blockPos, net.minecraft.world.level.block.state.BlockState state, boolean ignorePerBlockCooldown) List<net.minecraft.core.BlockPos> placeBlocksBatch(List<net.minecraft.core.BlockPos> blocks, net.minecraft.world.item.Item item) Batch placement — keeps the swap open and sends multiple placement packets.List<net.minecraft.core.BlockPos> placeBlocksBatch(List<net.minecraft.core.BlockPos> blocks, net.minecraft.world.item.Item item, boolean asymmetric) Batch placement variant.List<net.minecraft.core.BlockPos> placeBlocksBatchWithState(List<BlockPlacementManager.PlacementRequest> blocks, net.minecraft.world.item.Item item) Batch placement with desired block states (for oriented slabs, stairs, etc.).List<net.minecraft.core.BlockPos> placeBlocksBatchWithState(List<BlockPlacementManager.PlacementRequest> blocks, net.minecraft.world.item.Item item, boolean asymmetric) Batch placement with desired block states (for oriented slabs, stairs, etc.).voidremovePendingSound(net.minecraft.core.BlockPos pos) Remove a pending sound entry so the client-side sound is not played when the server confirms the block update (avoids double sounds).
-
Method Details
-
get
-
init
public void init()Register event handlers. Call once during mod init. -
beginPlacement
public boolean beginPlacement(net.minecraft.core.BlockPos position, net.minecraft.world.level.block.state.BlockState state, net.minecraft.world.item.Item item) Begins a placement transaction. Swaps the item into the main hand. Must be followed byplaceBlock(net.minecraft.world.item.Item, net.minecraft.core.BlockPos)calls and thenendPlacement(). -
beginPlacement
public boolean beginPlacement(List<net.minecraft.core.BlockPos> positions, net.minecraft.world.item.Item item) Begins a placement transaction with a list of positions. Succeeds if at least one position is valid for placement. -
placeBlock
public boolean placeBlock(net.minecraft.world.item.Item item, net.minecraft.core.BlockPos blockPos) Places a single block. Must be called betweenbeginPlacement(net.minecraft.core.BlockPos, net.minecraft.world.level.block.state.BlockState, net.minecraft.world.item.Item)andendPlacement(), or standalone (will use SwapManager internally). -
placeBlock
public boolean placeBlock(net.minecraft.world.item.Item item, net.minecraft.core.BlockPos blockPos, boolean ignorePerBlockCooldown) Placement variant that can bypass the per-position retry cooldown (AntiCheatBridge.PlacementPolicy.perBlockCooldownMs()). Used by Surround so it isn't throttled re-placing the same slot; all other modules keep the retry delay. -
placeBlock
public boolean placeBlock(net.minecraft.world.item.Item item, net.minecraft.core.BlockPos blockPos, net.minecraft.world.level.block.state.BlockState state) -
placeBlock
public boolean placeBlock(net.minecraft.world.item.Item item, net.minecraft.core.BlockPos blockPos, net.minecraft.world.level.block.state.BlockState state, boolean ignorePerBlockCooldown) -
placeBlocksBatch
public List<net.minecraft.core.BlockPos> placeBlocksBatch(List<net.minecraft.core.BlockPos> blocks, net.minecraft.world.item.Item item) Batch placement — keeps the swap open and sends multiple placement packets. Returns the positions that were actually placed. -
placeBlocksBatch
public List<net.minecraft.core.BlockPos> placeBlocksBatch(List<net.minecraft.core.BlockPos> blocks, net.minecraft.world.item.Item item, boolean asymmetric) Batch placement variant.- Parameters:
asymmetric- when true, a block item that has to be silent-swapped up from the deep inventory is left in the hotbar afterward instead of being swapped back (seeSwapManager.beginSwap(Item, boolean, boolean)). Continuous builders (Scaffold, HighwayCleaner) set this so they promote the block into the hotbar once and reuse it, instead of paying a swap-back every tick.
-
placeBlocksBatchWithState
public List<net.minecraft.core.BlockPos> placeBlocksBatchWithState(List<BlockPlacementManager.PlacementRequest> blocks, net.minecraft.world.item.Item item) Batch placement with desired block states (for oriented slabs, stairs, etc.). -
placeBlocksBatchWithState
public List<net.minecraft.core.BlockPos> placeBlocksBatchWithState(List<BlockPlacementManager.PlacementRequest> blocks, net.minecraft.world.item.Item item, boolean asymmetric) Batch placement with desired block states (for oriented slabs, stairs, etc.).- Parameters:
asymmetric- when true, an item that has to be silent-swapped up from the deep inventory is left in the hotbar afterward instead of being swapped back (seeSwapManager.beginSwap(Item, boolean, boolean)).
-
endPlacement
public void endPlacement() -
forceResetPlaceCooldown
public void forceResetPlaceCooldown(net.minecraft.core.BlockPos blockPos) -
isOnPlaceCooldown
public boolean isOnPlaceCooldown(net.minecraft.core.BlockPos blockPos) Returns true if the position is still on per-block retry cooldown. -
getRemainingBudget
public int getRemainingBudget()Returns how many placement packets can still be sent in the current rate-limit window. -
getPacketsSent
public int getPacketsSent()Returns packets sent in the current rate-limit window (0 when idle/reset). -
getWindowStartTimestamp
public long getWindowStartTimestamp()Returns the timestamp the current rate-limit window started, or -1 if idle. -
checkPlacement
public boolean checkPlacement(net.minecraft.world.item.Item item, net.minecraft.core.BlockPos blockPos) -
checkPlacement
public boolean checkPlacement(net.minecraft.world.item.Item item, net.minecraft.core.BlockPos blockPos, net.minecraft.world.level.block.state.BlockState state) -
isInstaBreakAndShouldClear
public static boolean isInstaBreakAndShouldClear(net.minecraft.world.level.block.state.BlockState state, net.minecraft.core.BlockPos blockPos) Returns true if the given non-replaceable block can be insta-broken (zero hardness) and therefore should be cleared with a break packet immediately before placement. Used to allow placing onto things like tnt, scaffolding, torches, redstone, etc. without performing an extra inventory swap. -
canPlaceOver
public static boolean canPlaceOver(net.minecraft.core.BlockPos pos) Returns true if a block can be placed at this position (either the block is replaceable, or it's an insta-breakable block that BPM will clear with a break packet before placing). Use this from modules (Surround, AutoTrap, etc.) instead of a rawcanBeReplaced()check so insta-breakable blocks like tnt/scaffolding/torches are not skipped. -
checkPlacement
public boolean checkPlacement(net.minecraft.world.item.Item item, net.minecraft.core.BlockPos blockPos, net.minecraft.world.level.block.state.BlockState state, net.minecraft.world.level.block.state.BlockState desiredState) -
getPlaceOnDirection
public static net.minecraft.core.Direction getPlaceOnDirection(net.minecraft.core.BlockPos pos) -
removePendingSound
public void removePendingSound(net.minecraft.core.BlockPos pos) Remove a pending sound entry so the client-side sound is not played when the server confirms the block update (avoids double sounds).
-