Skip to content

Commit

Permalink
Stop interactions with out of line of sight containers
Browse files Browse the repository at this point in the history
  • Loading branch information
Axionize committed Aug 23, 2024
1 parent 104d1ec commit 0d70608
Show file tree
Hide file tree
Showing 2 changed files with 142 additions and 0 deletions.
141 changes: 141 additions & 0 deletions src/main/java/ac/grim/grimac/checks/impl/badpackets/ContainerLOS.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
package ac.grim.grimac.checks.impl.badpackets;

import ac.grim.grimac.checks.Check;
import ac.grim.grimac.checks.CheckData;
import ac.grim.grimac.checks.type.PacketCheck;
import ac.grim.grimac.player.GrimPlayer;
import com.github.retrooper.packetevents.event.PacketReceiveEvent;
import com.github.retrooper.packetevents.protocol.attribute.Attributes;
import com.github.retrooper.packetevents.protocol.packettype.PacketType;
import com.github.retrooper.packetevents.protocol.player.ClientVersion;
import com.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientPlayerBlockPlacement;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.util.Vector;

@CheckData(name = "BadPacketsZ", experimental = true)
public class ContainerLOS extends Check implements PacketCheck {
public ContainerLOS(final GrimPlayer player) {
super(player);
}

// 64 is the max vanilla lets you set the block_interaction_range attribute to
double rayTraceDistanceCap = 64;

// Planned config options
// rayTraceDistanceCap
// - By default the check gets the block_interaction_range attribute for the maxDistance
// - This config option puts a cap on maxDistance, forcing it t
// - For example, if block_interaction_range is 10 blocks but rayTraceDistanceCap is 8 blocks
// - We will raytrace up to 8 blocks
// - However, if block_interaction_range is 6 blocks and rayTraceDistanceCap is 8 blocks
// - We will only raytrace up to 6 blocks
// interactBlocksList
// - List of blocks the player is trying to interact with to run the raytrace check against
// - Set to empty to make this check run for every block.

// TODO: figure out how to put this in the simulation code, fully compensate for lagllllll and run async in threads
@Override
public void onPacketReceive(PacketReceiveEvent event) {
if (event.getPacketType() == PacketType.Play.Client.PLAYER_BLOCK_PLACEMENT) {
WrapperPlayClientPlayerBlockPlacement packet = new WrapperPlayClientPlayerBlockPlacement(event);
Location location = new Location(this.player.bukkitPlayer.getWorld(), packet.getBlockPosition().getX(), packet.getBlockPosition().getY(), packet.getBlockPosition().getZ());
Block interactBlock = location.getBlock();

// For my specific use case, only run checks if the player is trying to interact with the following blocks
// So we don't have to ray trace and run this calculation for every block placement
if (!isInteractableBlock(interactBlock.getType())) {
return;
}
double maxDistance =
player.getClientVersion().isNewerThanOrEquals(ClientVersion.V_1_20_5) ?
// Does this code work on <= 1.20.5 ? Will the attribute return 4.5 in survival
// And 6.0 in creative or give an error?
Math.min(rayTraceDistanceCap, player.compensatedEntities.getSelf().getAttributeValue(Attributes.PLAYER_BLOCK_INTERACTION_RANGE)) :
Math.min(rayTraceDistanceCap, 6.0);


Block targetBlock = getTargetBlock(player, maxDistance);
if (targetBlock == null) {
System.out.println("Impossible for no ray trace block to exist.");
event.setCancelled(true);
return;
}

if (targetBlock.equals(interactBlock)) {
System.out.println("Nothing to see here, nothing wrong");
} else {
System.out.println("Player interacted with block at: " + interactBlock.getX() + " " + interactBlock.getY() + " " + interactBlock.getZ());
System.out.println("Raytrace check hit " + targetBlock.getType() + " block at: " + targetBlock.getX() + " " + targetBlock.getY() + " " + targetBlock.getZ());
event.setCancelled(true);
}
}
}

private Block getTargetBlock(GrimPlayer player, double maxDistance) {
Location eyeLocation = player.bukkitPlayer.getEyeLocation(); // How do I compensate for latency?
Vector direction = eyeLocation.getDirection().normalize();

for (int i = 0; i <= maxDistance; i++) {
Vector vec = direction.clone().multiply(i);
Block block = eyeLocation.add(vec).getBlock();
eyeLocation.subtract(vec);

if (block.getType() != Material.AIR) {
return block;
}
}

return null;
}

private boolean isInteractableBlock(Material type) {
switch (type) {
case ANVIL:
case BARREL:
case BEACON:
case BEEHIVE:
case BEE_NEST:
case BLAST_FURNACE:
case BREWING_STAND:
case CAMPFIRE:
case CARTOGRAPHY_TABLE:
case CHEST:
case CHEST_MINECART:
case CHIPPED_ANVIL:
case COMPOSTER:
case CRAFTING_TABLE:
case DAMAGED_ANVIL:
case DISPENSER:
case DROPPER:
case ENCHANTING_TABLE:
case ENDER_CHEST:
case FURNACE:
case FURNACE_MINECART:
case FLETCHING_TABLE:
case GRINDSTONE:
case HOPPER:
case HOPPER_MINECART:
case ITEM_FRAME:
case JUKEBOX:
case LECTERN:
case LOOM:
case RESPAWN_ANCHOR:
case SHULKER_BOX:
case SMITHING_TABLE:
case SMOKER:
case SOUL_CAMPFIRE:
case STONECUTTER:
case TRAPPED_CHEST:

// Do we really need to check for creative mode blocks?
case COMMAND_BLOCK:
case STRUCTURE_BLOCK:
case JIGSAW:
return true;
default:
return false;
}
}
}
1 change: 1 addition & 0 deletions src/main/java/ac/grim/grimac/manager/CheckManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ public CheckManager(GrimPlayer player) {
.put(FastBreak.class, new FastBreak(player))
.put(TransactionOrder.class, new TransactionOrder(player))
.put(NoSlowB.class, new NoSlowB(player))
.put(ContainerLOS.class, new ContainerLOS(player))
.put(SetbackBlocker.class, new SetbackBlocker(player)) // Must be last class otherwise we can't check while blocking packets
.build();
positionCheck = new ImmutableClassToInstanceMap.Builder<PositionCheck>()
Expand Down

0 comments on commit 0d70608

Please sign in to comment.