Skip to content

Commit

Permalink
Fixes hoppers being read while unlocked
Browse files Browse the repository at this point in the history
  • Loading branch information
samolego committed Apr 4, 2023
1 parent 39fd5a2 commit 145ddb3
Show file tree
Hide file tree
Showing 2 changed files with 103 additions and 81 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -72,86 +72,10 @@ public static InteractionResult onUseBlock(Player player, Level world, Interacti
BlockState blockState = world.getBlockState(craftingPos);

if (blockState.getBlock() == Blocks.CRAFTING_TABLE) {
((ICSPlayer) player).cs_setLastInteractedContainer(null);

final boolean singleplayer = Minecraft.getInstance().isLocalServer();
lastCraftingHit = hitResult;

ContainerDiscovery.resetInventoryCache();

if (config.enableBlocks) {
Set<LevelChunk> chunks2check = ContainerDiscovery.getChunksAround(player.blockPosition(), world);
chunks2check.forEach(levelChunk -> {
// Check for blockentity containers
levelChunk.getBlockEntities().forEach((position, blockEntity) -> {
// Check if within reach
if (blockEntity instanceof InteractableContainer && player.getEyePosition().distanceTo(Vec3.atCenterOf(position)) < config.maxDist) {
// Check if container can be opened
// (avoid sending packets to those that client knows they can't be opened)
boolean canOpen = ContainerUtil.canOpenContainer(blockEntity, player);
InteractableContainer container = ContainerUtil.getContainer(blockEntity);

if (canOpen) {
if (singleplayer && container.isEmpty()) {
ContainerDiscovery.copyServerContent(container);
}

if (!singleplayer && (container.isEmpty() || !config.enableCaching)) {
INTERACTION_Q.add(container);
StorageCache.FREE_SPACE_CONTAINERS.put(container, container.getContainerSize());
} else if (!container.isEmpty()) {
for (int i = 0; i < container.getContainerSize(); ++i) {
ItemStack stack = container.getItem(i);
if (!stack.isEmpty()) {
ContainerDiscovery.addRemoteItem(container, i, stack);
} else {
StorageCache.FREE_SPACE_CONTAINERS.compute(container, (key, value) -> value == null ? 1 : value + 1);
}
}
StorageCache.CACHED_INVENTORIES.add(container);
} else {
StorageCache.FREE_SPACE_CONTAINERS.put(container, container.getContainerSize());
}
}
}
});
});
if (!ContainerDiscovery.canCraftingOpen(player, world)) {
return InteractionResult.FAIL;
}

// Check for other containers (e.g. chest minecarts, etc.)
if (config.enableEntities) {
final var boundingBox = player.getBoundingBox().inflate(config.maxDist);
world.getEntities((Entity) null, boundingBox, InteractableContainer.CONTAINER_ENTITY_SELECTOR).forEach(entity -> {
final var container = (InteractableContainer) entity;
if (singleplayer && container.isEmpty()) {
ContainerDiscovery.copyServerContent(container);
}

if (!singleplayer && (container.isEmpty() || !config.enableCaching)) {
INTERACTION_Q.add(container);
StorageCache.FREE_SPACE_CONTAINERS.put(container, container.getContainerSize());
} else if (!container.isEmpty()) {
for (int i = 0; i < container.getContainerSize(); ++i) {
ItemStack stack = container.getItem(i);
if (!stack.isEmpty()) {
ContainerDiscovery.addRemoteItem(container, i, stack);
} else {
StorageCache.FREE_SPACE_CONTAINERS.compute(container, (key, value) -> value == null ? 1 : value + 1);
}
}
StorageCache.CACHED_INVENTORIES.add(container);
} else {
StorageCache.FREE_SPACE_CONTAINERS.put(container, container.getContainerSize());
}
});
}

if (!INTERACTION_Q.isEmpty()) {
CompletableFuture.runAsync(ContainerDiscovery::sendPackets);
return InteractionResult.FAIL; // We'll open the crafting table later
}

RemoteInventory.getInstance().sort();
} else {
ESPRender.removeBlockPos(craftingPos);

Expand All @@ -167,6 +91,96 @@ public static InteractionResult onUseBlock(Player player, Level world, Interacti
return InteractionResult.PASS;
}

/**
* Tries to search the containers
* or opens the crafting table.
* @param player
* @param world
* @return true if crafting table can be opened, false otherwise.
*/
private static boolean canCraftingOpen(Player player, Level world) {
((ICSPlayer) player).cs_setLastInteractedContainer(null);

final boolean singleplayer = Minecraft.getInstance().isLocalServer();

ContainerDiscovery.resetInventoryCache();

if (config.enableBlocks) {
Set<LevelChunk> chunks2check = ContainerDiscovery.getChunksAround(player.blockPosition(), world);
chunks2check.forEach(levelChunk -> {
// Check for blockentity containers
levelChunk.getBlockEntities().forEach((position, blockEntity) -> {
// Check if within reach
if (blockEntity instanceof InteractableContainer && player.getEyePosition().distanceTo(Vec3.atCenterOf(position)) < config.maxDist) {
// Check if container can be opened
// (avoid sending packets to those that client knows they can't be opened)
boolean canOpen = ContainerUtil.shouldIncludeContainer(blockEntity, player);
InteractableContainer container = ContainerUtil.getContainer(blockEntity);

if (canOpen) {
if (singleplayer && container.isEmpty()) {
ContainerDiscovery.copyServerContent(container);
}

if (!singleplayer && (container.isEmpty() || !config.enableCaching)) {
INTERACTION_Q.add(container);
StorageCache.FREE_SPACE_CONTAINERS.put(container, container.getContainerSize());
} else if (!container.isEmpty()) {
for (int i = 0; i < container.getContainerSize(); ++i) {
ItemStack stack = container.getItem(i);
if (!stack.isEmpty()) {
ContainerDiscovery.addRemoteItem(container, i, stack);
} else {
StorageCache.FREE_SPACE_CONTAINERS.compute(container, (key, value) -> value == null ? 1 : value + 1);
}
}
StorageCache.CACHED_INVENTORIES.add(container);
} else {
StorageCache.FREE_SPACE_CONTAINERS.put(container, container.getContainerSize());
}
}
}
});
});
}

// Check for other containers (e.g. chest minecarts, etc.)
if (config.enableEntities) {
final var boundingBox = player.getBoundingBox().inflate(config.maxDist);
world.getEntities((Entity) null, boundingBox, InteractableContainer.CONTAINER_ENTITY_SELECTOR).forEach(entity -> {
final var container = (InteractableContainer) entity;
if (singleplayer && container.isEmpty()) {
ContainerDiscovery.copyServerContent(container);
}

if (!singleplayer && (container.isEmpty() || !config.enableCaching)) {
INTERACTION_Q.add(container);
StorageCache.FREE_SPACE_CONTAINERS.put(container, container.getContainerSize());
} else if (!container.isEmpty()) {
for (int i = 0; i < container.getContainerSize(); ++i) {
ItemStack stack = container.getItem(i);
if (!stack.isEmpty()) {
ContainerDiscovery.addRemoteItem(container, i, stack);
} else {
StorageCache.FREE_SPACE_CONTAINERS.compute(container, (key, value) -> value == null ? 1 : value + 1);
}
}
StorageCache.CACHED_INVENTORIES.add(container);
} else {
StorageCache.FREE_SPACE_CONTAINERS.put(container, container.getContainerSize());
}
});
}

if (!INTERACTION_Q.isEmpty()) {
CompletableFuture.runAsync(ContainerDiscovery::sendPackets);
return false; // We'll open the crafting table later
}

RemoteInventory.getInstance().sort();
return true;
}

/**
* Copies the content of the server container to the client block entity container
*
Expand All @@ -187,7 +201,6 @@ private static void copyServerContent(InteractableContainer container) {
.getLevel(Minecraft.getInstance().level.dimension());

// Get server block entity

final BlockPos pos = BlockPos.containing(container.cs_position());
InteractableContainer serverContainer = (InteractableContainer) level.getChunkAt(pos).getBlockEntity(pos);
if (serverContainer == null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.ChestBlock;
import net.minecraft.world.level.block.DoubleBlockCombiner;
import net.minecraft.world.level.block.HopperBlock;
import net.minecraft.world.level.block.ShulkerBoxBlock;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.entity.ChestBlockEntity;
Expand Down Expand Up @@ -58,13 +59,16 @@ public static synchronized InteractableContainer getContainer(Level level, Block
}

/**
* Checks whether player can open the container from clientside pov.
* Checks whether this container should be included in the list.
* Default is yes, but if container is a chest, it must be checked
* whether it's blocked by a block above it. Similar applies to shulkers.
* Hoppers are also excluded if they're unlocked.
*
* @param containerBE container block entity
* @param player player
* @return true if player can open the container, false otherwise
*/
public static boolean canOpenContainer(BlockEntity containerBE, Player player) {
public static boolean shouldIncludeContainer(BlockEntity containerBE, Player player) {
final BlockState containerState = containerBE.getBlockState();
final var blockPos = containerBE.getBlockPos();

Expand Down Expand Up @@ -106,6 +110,11 @@ public static boolean canOpenContainer(BlockEntity containerBE, Player player) {
}
}

// Check for unlocked hopper
if (containerBE instanceof HopperBlockEntity) {
return !containerState.getValue(HopperBlock.ENABLED);
}

return true;
}
}

0 comments on commit 145ddb3

Please sign in to comment.