001/* 002 * This file is part of Baritone. 003 * 004 * Baritone is free software: you can redistribute it and/or modify 005 * it under the terms of the GNU Lesser General Public License as published by 006 * the Free Software Foundation, either version 3 of the License, or 007 * (at your option) any later version. 008 * 009 * Baritone is distributed in the hope that it will be useful, 010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 012 * GNU Lesser General Public License for more details. 013 * 014 * You should have received a copy of the GNU Lesser General Public License 015 * along with Baritone. If not, see <https://www.gnu.org/licenses/>. 016 */ 017 018package baritone.api.utils; 019 020import baritone.api.cache.IWorldData; 021import net.minecraft.client.Minecraft; 022import net.minecraft.client.multiplayer.ClientLevel; 023import net.minecraft.client.player.LocalPlayer; 024import net.minecraft.core.BlockPos; 025import net.minecraft.world.entity.Entity; 026import net.minecraft.world.level.Level; 027import net.minecraft.world.level.block.SlabBlock; 028import net.minecraft.world.phys.BlockHitResult; 029import net.minecraft.world.phys.HitResult; 030import net.minecraft.world.phys.Vec3; 031 032import java.util.Optional; 033import java.util.stream.Stream; 034import java.util.stream.StreamSupport; 035 036/** 037 * @author Brady 038 * @since 11/12/2018 039 */ 040public interface IPlayerContext { 041 042 Minecraft minecraft(); 043 044 LocalPlayer player(); 045 046 IPlayerController playerController(); 047 048 Level world(); 049 050 default Iterable<Entity> entities() { 051 return ((ClientLevel) world()).entitiesForRendering(); 052 } 053 054 default Stream<Entity> entitiesStream() { 055 return StreamSupport.stream(entities().spliterator(), false); 056 } 057 058 059 IWorldData worldData(); 060 061 HitResult objectMouseOver(); 062 063 default BetterBlockPos playerFeet() { 064 // TODO find a better way to deal with soul sand!!!!! 065 BetterBlockPos feet = new BetterBlockPos(player().position().x, player().position().y + 0.1251, player().position().z); 066 067 // sometimes when calling this from another thread or while world is null, it'll throw a NullPointerException 068 // that causes the game to immediately crash 069 // 070 // so of course crashing on 2b is horribly bad due to queue times and logout spot 071 // catch the NPE and ignore it if it does happen 072 // 073 // this does not impact performance at all since we're not null checking constantly 074 // if there is an exception, the only overhead is Java generating the exception object... so we can ignore it 075 try { 076 if (world().getBlockState(feet).getBlock() instanceof SlabBlock) { 077 return feet.above(); 078 } 079 } catch (NullPointerException ignored) {} 080 081 return feet; 082 } 083 084 default Vec3 playerFeetAsVec() { 085 return new Vec3(player().position().x, player().position().y, player().position().z); 086 } 087 088 default Vec3 playerHead() { 089 return new Vec3(player().position().x, player().position().y + player().getEyeHeight(), player().position().z); 090 } 091 092 default Vec3 playerMotion() { 093 return player().getDeltaMovement(); 094 } 095 096 BetterBlockPos viewerPos(); 097 098 default Rotation playerRotations() { 099 return new Rotation(player().getYRot(), player().getXRot()); 100 } 101 102 /** 103 * Returns the player's eye height, taking into account whether or not the player is sneaking. 104 * 105 * @param ifSneaking Whether or not the player is sneaking 106 * @return The player's eye height 107 * @deprecated Use entity.getEyeHeight(Pose.CROUCHING) instead 108 */ 109 @Deprecated 110 static double eyeHeight(boolean ifSneaking) { 111 return ifSneaking ? 1.27 : 1.62; 112 } 113 114 /** 115 * Returns the block that the crosshair is currently placed over. Updated once per tick. 116 * 117 * @return The position of the highlighted block 118 */ 119 default Optional<BlockPos> getSelectedBlock() { 120 HitResult result = objectMouseOver(); 121 if (result != null && result.getType() == HitResult.Type.BLOCK) { 122 return Optional.of(((BlockHitResult) result).getBlockPos()); 123 } 124 return Optional.empty(); 125 } 126 127 default boolean isLookingAt(BlockPos pos) { 128 return getSelectedBlock().equals(Optional.of(pos)); 129 } 130}