2018-08-08 03:16:53 +00:00
/ *
* This file is part of Baritone .
*
* Baritone is free software : you can redistribute it and / or modify
2018-09-17 22:11:40 +00:00
* it under the terms of the GNU Lesser General Public License as published by
2018-08-08 03:16:53 +00:00
* the Free Software Foundation , either version 3 of the License , or
* ( at your option ) any later version .
*
2018-08-08 04:15:22 +00:00
* Baritone is distributed in the hope that it will be useful ,
2018-08-08 03:16:53 +00:00
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
2018-09-17 22:11:40 +00:00
* GNU Lesser General Public License for more details .
2018-08-08 03:16:53 +00:00
*
2018-09-17 22:11:40 +00:00
* You should have received a copy of the GNU Lesser General Public License
2018-08-08 03:16:53 +00:00
* along with Baritone . If not , see < https : //www.gnu.org/licenses/>.
* /
2018-08-22 20:15:56 +00:00
package baritone.utils ;
2018-08-02 17:25:46 +00:00
2018-08-22 20:15:56 +00:00
import baritone.Baritone ;
2018-11-13 21:14:29 +00:00
import baritone.api.utils.IPlayerContext ;
2018-09-24 23:55:57 +00:00
import baritone.cache.CachedRegion ;
2018-09-11 17:28:03 +00:00
import baritone.cache.WorldData ;
2018-11-23 17:00:52 +00:00
import baritone.utils.accessor.IChunkProviderClient ;
import it.unimi.dsi.fastutil.longs.Long2ObjectMap ;
2018-11-25 20:13:49 +00:00
import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap ;
2018-08-02 17:25:46 +00:00
import net.minecraft.block.Block ;
import net.minecraft.block.state.IBlockState ;
2018-11-23 17:00:52 +00:00
import net.minecraft.client.Minecraft ;
2018-08-06 21:32:54 +00:00
import net.minecraft.init.Blocks ;
2018-08-02 17:25:46 +00:00
import net.minecraft.util.math.BlockPos ;
2018-11-23 17:00:52 +00:00
import net.minecraft.util.math.ChunkPos ;
2018-11-11 20:35:04 +00:00
import net.minecraft.world.World ;
2018-08-08 00:41:13 +00:00
import net.minecraft.world.chunk.Chunk ;
2018-09-09 15:53:15 +00:00
/ * *
* Wraps get for chuck caching capability
*
* @author leijurv
* /
2018-11-13 22:33:45 +00:00
public class BlockStateInterface {
2018-08-02 17:25:46 +00:00
2018-11-23 17:00:52 +00:00
private final Long2ObjectMap < Chunk > loadedChunks ;
2018-11-12 01:36:54 +00:00
private final WorldData worldData ;
private Chunk prev = null ;
private CachedRegion prevCached = null ;
2018-09-09 16:50:19 +00:00
2019-01-11 02:55:55 +00:00
private final boolean useTheRealWorld ;
2018-10-14 05:23:49 +00:00
private static final IBlockState AIR = Blocks . AIR . getDefaultState ( ) ;
2018-09-01 19:26:55 +00:00
2018-11-13 21:14:29 +00:00
public BlockStateInterface ( IPlayerContext ctx ) {
2018-11-26 06:30:37 +00:00
this ( ctx , false ) ;
2018-11-13 21:14:29 +00:00
}
2018-11-26 06:30:37 +00:00
public BlockStateInterface ( IPlayerContext ctx , boolean copyLoadedChunks ) {
this ( ctx . world ( ) , ( WorldData ) ctx . worldData ( ) , copyLoadedChunks ) ;
}
public BlockStateInterface ( World world , WorldData worldData , boolean copyLoadedChunks ) {
2018-11-12 01:36:54 +00:00
this . worldData = worldData ;
2018-11-26 06:30:37 +00:00
Long2ObjectMap < Chunk > worldLoaded = ( ( IChunkProviderClient ) world . getChunkProvider ( ) ) . loadedChunks ( ) ;
if ( copyLoadedChunks ) {
this . loadedChunks = new Long2ObjectOpenHashMap < > ( worldLoaded ) ; // make a copy that we can safely access from another thread
} else {
this . loadedChunks = worldLoaded ; // this will only be used on the main thread
}
2019-03-05 05:30:04 +00:00
this . useTheRealWorld = ! Baritone . settings ( ) . pathThroughCachedOnly . value ;
2018-11-23 17:00:52 +00:00
if ( ! Minecraft . getMinecraft ( ) . isCallingFromMinecraftThread ( ) ) {
throw new IllegalStateException ( ) ;
}
2018-09-09 15:53:15 +00:00
}
2018-11-23 17:03:51 +00:00
public boolean worldContainsLoadedChunk ( int blockX , int blockZ ) {
return loadedChunks . containsKey ( ChunkPos . asLong ( blockX > > 4 , blockZ > > 4 ) ) ;
2018-11-14 21:24:44 +00:00
}
2018-11-13 21:14:29 +00:00
public static Block getBlock ( IPlayerContext ctx , BlockPos pos ) { // won't be called from the pathing thread because the pathing thread doesn't make a single blockpos pog
return get ( ctx , pos ) . getBlock ( ) ;
2018-11-12 01:36:54 +00:00
}
2018-11-11 20:35:04 +00:00
2018-11-13 21:14:29 +00:00
public static IBlockState get ( IPlayerContext ctx , BlockPos pos ) {
return new BlockStateInterface ( ctx ) . get0 ( pos . getX ( ) , pos . getY ( ) , pos . getZ ( ) ) ; // immense iq
2018-11-12 02:23:18 +00:00
// can't just do world().get because that doesn't work for out of bounds
// and toBreak and stuff fails when the movement is instantiated out of load range but it's not able to BlockStateInterface.get what it's going to walk on
2018-11-11 20:35:04 +00:00
}
2018-11-23 17:00:52 +00:00
public IBlockState get0 ( BlockPos pos ) {
return get0 ( pos . getX ( ) , pos . getY ( ) , pos . getZ ( ) ) ;
}
2018-11-13 21:14:29 +00:00
public IBlockState get0 ( int x , int y , int z ) { // Mickey resigned
2018-08-08 00:41:13 +00:00
// Invalid vertical position
2018-09-09 15:53:15 +00:00
if ( y < 0 | | y > = 256 ) {
2018-09-09 16:50:19 +00:00
return AIR ;
2018-09-08 04:32:25 +00:00
}
2018-08-08 00:41:13 +00:00
2019-01-11 02:55:55 +00:00
if ( useTheRealWorld ) {
2018-08-31 18:51:43 +00:00
Chunk cached = prev ;
// there's great cache locality in block state lookups
// generally it's within each movement
// if it's the same chunk as last time
// we can just skip the mc.world.getChunk lookup
// which is a Long2ObjectOpenHashMap.get
2018-09-23 15:05:59 +00:00
// see issue #113
2018-09-09 15:53:15 +00:00
if ( cached ! = null & & cached . x = = x > > 4 & & cached . z = = z > > 4 ) {
return cached . getBlockState ( x , y , z ) ;
2018-08-31 18:51:43 +00:00
}
2018-11-23 17:03:51 +00:00
Chunk chunk = loadedChunks . get ( ChunkPos . asLong ( x > > 4 , z > > 4 ) ) ;
2018-11-23 17:00:52 +00:00
2018-11-23 17:03:51 +00:00
if ( chunk ! = null & & chunk . isLoaded ( ) ) {
2018-08-31 18:51:43 +00:00
prev = chunk ;
2018-09-09 15:53:15 +00:00
return chunk . getBlockState ( x , y , z ) ;
2018-08-22 19:04:44 +00:00
}
2018-08-14 03:17:16 +00:00
}
2018-09-09 16:50:19 +00:00
// same idea here, skip the Long2ObjectOpenHashMap.get if at all possible
// except here, it's 512x512 tiles instead of 16x16, so even better repetition
2018-09-24 23:55:57 +00:00
CachedRegion cached = prevCached ;
2018-09-11 18:56:59 +00:00
if ( cached = = null | | cached . getX ( ) ! = x > > 9 | | cached . getZ ( ) ! = z > > 9 ) {
2018-11-11 20:35:04 +00:00
if ( worldData = = null ) {
2018-09-09 16:50:19 +00:00
return AIR ;
}
2018-11-11 20:35:04 +00:00
CachedRegion region = worldData . cache . getRegion ( x > > 9 , z > > 9 ) ;
2018-09-11 18:56:59 +00:00
if ( region = = null ) {
return AIR ;
2018-08-08 00:41:13 +00:00
}
2018-09-11 18:56:59 +00:00
prevCached = region ;
cached = region ;
}
IBlockState type = cached . getBlock ( x & 511 , y , z & 511 ) ;
if ( type = = null ) {
return AIR ;
2018-08-08 00:41:13 +00:00
}
2018-09-11 18:56:59 +00:00
return type ;
2018-08-02 17:25:46 +00:00
}
2018-11-12 01:36:54 +00:00
public boolean isLoaded ( int x , int z ) {
2018-09-23 17:20:19 +00:00
Chunk prevChunk = prev ;
if ( prevChunk ! = null & & prevChunk . x = = x > > 4 & & prevChunk . z = = z > > 4 ) {
return true ;
}
2018-11-23 17:03:51 +00:00
prevChunk = loadedChunks . get ( ChunkPos . asLong ( x > > 4 , z > > 4 ) ) ;
if ( prevChunk ! = null & & prevChunk . isLoaded ( ) ) {
2018-09-24 19:44:34 +00:00
prev = prevChunk ;
2018-09-23 17:20:19 +00:00
return true ;
}
2018-09-24 23:55:57 +00:00
CachedRegion prevRegion = prevCached ;
2018-09-23 17:20:19 +00:00
if ( prevRegion ! = null & & prevRegion . getX ( ) = = x > > 9 & & prevRegion . getZ ( ) = = z > > 9 ) {
return prevRegion . isCached ( x & 511 , z & 511 ) ;
}
2018-11-12 01:36:54 +00:00
if ( worldData = = null ) {
2018-09-23 17:20:19 +00:00
return false ;
}
2018-11-12 01:36:54 +00:00
prevRegion = worldData . cache . getRegion ( x > > 9 , z > > 9 ) ;
2018-09-24 19:44:34 +00:00
if ( prevRegion = = null ) {
2018-09-23 17:20:19 +00:00
return false ;
}
2018-09-24 19:44:34 +00:00
prevCached = prevRegion ;
return prevRegion . isCached ( x & 511 , z & 511 ) ;
2018-09-23 17:20:19 +00:00
}
2018-08-02 17:25:46 +00:00
}