2019-10-27 15:45:44 +00:00
package me.rigamortis.seppuku.impl.module.combat ;
2020-12-06 04:59:32 +00:00
import com.google.common.collect.Lists ;
2019-10-27 15:45:44 +00:00
import me.rigamortis.seppuku.Seppuku ;
import me.rigamortis.seppuku.api.event.EventStageable ;
import me.rigamortis.seppuku.api.event.player.EventUpdateWalkingPlayer ;
2020-12-06 04:59:32 +00:00
import me.rigamortis.seppuku.api.event.world.EventLoadWorld ;
2019-10-27 15:45:44 +00:00
import me.rigamortis.seppuku.api.module.Module ;
2020-12-06 04:59:32 +00:00
import me.rigamortis.seppuku.api.task.hand.HandSwapContext ;
2021-01-08 06:32:44 +00:00
import me.rigamortis.seppuku.api.task.rotation.RotationTask ;
2021-01-16 21:07:51 +00:00
import me.rigamortis.seppuku.api.util.InventoryUtil ;
2019-10-27 15:45:44 +00:00
import me.rigamortis.seppuku.api.util.MathUtil ;
2019-12-03 21:59:48 +00:00
import me.rigamortis.seppuku.api.util.Timer ;
2019-12-01 16:45:36 +00:00
import me.rigamortis.seppuku.api.value.Value ;
2019-10-27 15:45:44 +00:00
import me.rigamortis.seppuku.impl.module.player.FreeCamModule ;
import net.minecraft.block.Block ;
2019-12-04 17:10:26 +00:00
import net.minecraft.block.state.IBlockState ;
2019-10-27 15:45:44 +00:00
import net.minecraft.client.Minecraft ;
2021-01-08 06:32:44 +00:00
import net.minecraft.init.Blocks ;
2019-12-10 18:09:29 +00:00
import net.minecraft.network.play.client.CPacketAnimation ;
2019-10-27 15:45:44 +00:00
import net.minecraft.network.play.client.CPacketEntityAction ;
2020-12-06 04:59:32 +00:00
import net.minecraft.network.play.client.CPacketPlayer ;
2019-12-04 13:57:55 +00:00
import net.minecraft.network.play.client.CPacketPlayerTryUseItemOnBlock ;
2019-10-27 15:45:44 +00:00
import net.minecraft.util.EnumFacing ;
import net.minecraft.util.EnumHand ;
import net.minecraft.util.math.AxisAlignedBB ;
import net.minecraft.util.math.BlockPos ;
import net.minecraft.util.math.Vec3d ;
import team.stiff.pomelo.impl.annotated.handler.annotation.Listener ;
2020-11-25 20:00:59 +00:00
2020-12-06 04:59:32 +00:00
import java.util.List ;
2019-10-27 15:45:44 +00:00
/ * *
2019-12-10 21:41:39 +00:00
* @author Seth
2021-01-08 06:32:44 +00:00
* @author noil
2019-10-27 15:45:44 +00:00
* /
public final class NoCrystalModule extends Module {
private final Minecraft mc = Minecraft . getMinecraft ( ) ;
2020-12-06 04:59:32 +00:00
public final Value < Boolean > visible = new Value < Boolean > ( " Visible " , new String [ ] { " Visible " , " v " } , " When disabled, you will not see swing animations or sounds. " , true ) ;
public final Value < Boolean > rotate = new Value < Boolean > ( " Rotate " , new String [ ] { " rotation " , " r " , " rotate " } , " Rotate to place blocks. " , true ) ;
public final Value < Boolean > center = new Value < Boolean > ( " Center " , new String [ ] { " centered " , " c " , " cen " } , " Centers the player on their current block when beginning to place. " , true ) ;
2020-12-06 04:59:32 +00:00
public final Value < Boolean > extended = new Value < Boolean > ( " Extended " , new String [ ] { " extend " , " e " , " big " } , " Enlarges the size of the fortress. " , false ) ;
2020-12-06 04:59:32 +00:00
public final Value < Boolean > disable = new Value < Boolean > ( " Disable " , new String [ ] { " dis " , " autodisable " , " autodis " , " d " } , " Automatically disable after obsidian is placed. " , false ) ;
2020-11-25 20:00:59 +00:00
public final Value < Boolean > sneak = new Value < Boolean > ( " PlaceOnSneak " , new String [ ] { " sneak " , " s " , " pos " , " sneakPlace " } , " When true, NoCrystal will only place while the player is sneaking. " , false ) ;
2021-01-10 02:09:40 +00:00
public final Value < Float > range = new Value < Float > ( " Range " , new String [ ] { " MaxRange " , " MaximumRange " } , " The maximum block reaching range to continue building in. " , 6 . 0f , 1 . 0f , 10 . 0f , 0 . 5f ) ;
2021-01-07 23:01:44 +00:00
public final Value < Float > placeDelay = new Value < Float > ( " Delay " , new String [ ] { " PlaceDelay " , " PlaceDel " } , " The delay(ms) between obsidian blocks being placed. " , 100 . 0f , 0 . 0f , 500 . 0f , 1 . 0f ) ;
2019-12-03 21:59:48 +00:00
2020-12-06 04:59:32 +00:00
private final Timer placeTimer = new Timer ( ) ;
2021-01-08 06:32:44 +00:00
private final RotationTask rotationTask = new RotationTask ( " NoCrystalTask " , 8 ) ;
2019-12-03 21:59:48 +00:00
2020-12-06 04:59:32 +00:00
private FreeCamModule freeCamModule = null ;
2019-10-27 15:45:44 +00:00
public NoCrystalModule ( ) {
2020-06-24 11:34:50 +00:00
super ( " NoCrystal " , new String [ ] { " AntiCrystal " , " FeetPlace " , " Surround " } , " Automatically places obsidian around you to avoid crystal damage " , " NONE " , - 1 , ModuleType . COMBAT ) ;
2019-12-04 13:57:55 +00:00
}
2019-10-27 15:45:44 +00:00
2021-01-08 06:32:44 +00:00
@Override
public void onDisable ( ) {
super . onDisable ( ) ;
Seppuku . INSTANCE . getRotationManager ( ) . finishTask ( this . rotationTask ) ;
}
2019-10-27 15:45:44 +00:00
@Listener
public void onWalkingUpdate ( EventUpdateWalkingPlayer event ) {
2021-01-08 06:32:44 +00:00
if ( event . getStage ( ) ! = EventStageable . EventStage . PRE )
2020-12-06 04:59:32 +00:00
return ;
if ( freeCamModule ! = null & & freeCamModule . isEnabled ( ) )
return ;
final Vec3d pos = MathUtil . interpolateEntity ( mc . player , mc . getRenderPartialTicks ( ) ) ;
final float playerSpeed = ( float ) MathUtil . getDistance ( pos , mc . player . posX , mc . player . posY , mc . player . posZ ) ;
if ( ! mc . player . onGround | | playerSpeed > 0 . 005f )
return ;
final BlockPos interpolatedPos = new BlockPos ( pos . x , pos . y , pos . z ) ;
final BlockPos north = interpolatedPos . north ( ) ;
final BlockPos south = interpolatedPos . south ( ) ;
final BlockPos east = interpolatedPos . east ( ) ;
final BlockPos west = interpolatedPos . west ( ) ;
BlockPos [ ] surroundBlocks ;
if ( this . extended . getValue ( ) ) {
// ..x..
// .xxx. x = to place block
// xx@xx . = to ignore
// .xxx. @ = player
// ..x..
surroundBlocks = new BlockPos [ ] { north . down ( ) , south . down ( ) , east . down ( ) , west . down ( ) ,
north , south , east , west , north . east ( ) , north . west ( ) , south . east ( ) , south . west ( ) ,
north . north ( ) , south . south ( ) , east . east ( ) , west . west ( ) } ;
} else {
// ..x.. x = to place block
// .x@x. . = to ignore
// ..x.. @ = player
surroundBlocks = new BlockPos [ ] { north . down ( ) , south . down ( ) , east . down ( ) , west . down ( ) ,
north , south , east , west } ;
}
2020-12-06 05:57:40 +00:00
final List < BlockPos > blocksToPlace = Lists . newArrayListWithCapacity ( 16 ) ;
2020-12-06 04:59:32 +00:00
// find missing blocks (starting from under the player first and going upwards)
for ( int i = 0 ; i < surroundBlocks . length ; i + + ) {
BlockPos blockPos = surroundBlocks [ i ] ;
if ( ! this . valid ( blockPos ) )
continue ;
blocksToPlace . add ( blockPos ) ;
}
2021-01-09 04:56:10 +00:00
if ( blocksToPlace . size ( ) ! = 0 ) { // we have blocks to place
2020-12-06 04:59:32 +00:00
final HandSwapContext handSwapContext = new HandSwapContext (
2021-01-16 21:07:51 +00:00
mc . player . inventory . currentItem , InventoryUtil . findObsidianInHotbar ( mc . player ) ) ;
2021-01-08 06:32:44 +00:00
if ( handSwapContext . getNewSlot ( ) = = - 1 ) {
Seppuku . INSTANCE . getRotationManager ( ) . finishTask ( this . rotationTask ) ;
return ;
}
if ( ! mc . player . isSneaking ( ) & & this . sneak . getValue ( ) ) {
if ( this . rotationTask . isOnline ( ) ) {
Seppuku . INSTANCE . getRotationManager ( ) . finishTask ( this . rotationTask ) ;
}
2020-12-06 04:59:32 +00:00
return ;
2021-01-08 06:32:44 +00:00
}
2020-12-06 04:59:32 +00:00
2021-01-08 06:32:44 +00:00
Seppuku . INSTANCE . getRotationManager ( ) . startTask ( this . rotationTask ) ;
if ( this . rotationTask . isOnline ( ) ) {
// swap to obby
handSwapContext . handleHandSwap ( false , mc ) ;
2020-12-06 04:59:32 +00:00
if ( this . center . getValue ( ) ) {
final double [ ] newPos = { Math . floor ( mc . player . posX ) + 0 . 5d , mc . player . posY , Math . floor ( mc . player . posZ ) + 0 . 5d } ;
final CPacketPlayer . Position middleOfPos = new CPacketPlayer . Position ( newPos [ 0 ] , newPos [ 1 ] , newPos [ 2 ] , mc . player . onGround ) ;
2021-01-08 06:32:44 +00:00
if ( ! mc . world . isAirBlock ( new BlockPos ( newPos [ 0 ] , newPos [ 1 ] , newPos [ 2 ] ) . down ( ) ) ) {
if ( mc . player . posX ! = middleOfPos . x & & mc . player . posZ ! = middleOfPos . z ) {
mc . player . connection . sendPacket ( middleOfPos ) ;
mc . player . setPosition ( newPos [ 0 ] , newPos [ 1 ] , newPos [ 2 ] ) ;
}
}
2020-12-06 04:59:32 +00:00
}
2021-01-08 06:32:44 +00:00
for ( BlockPos blockPos : blocksToPlace ) {
if ( ! this . valid ( blockPos ) )
continue ;
if ( this . placeDelay . getValue ( ) < = 0 . 0f ) {
this . place ( blockPos ) ;
} else if ( placeTimer . passed ( this . placeDelay . getValue ( ) ) ) {
this . place ( blockPos ) ;
this . placeTimer . reset ( ) ;
}
2019-10-27 15:45:44 +00:00
}
2020-12-06 04:59:32 +00:00
2021-01-08 06:32:44 +00:00
// swap back to original
handSwapContext . handleHandSwap ( true , mc ) ;
}
} else {
Seppuku . INSTANCE . getRotationManager ( ) . finishTask ( this . rotationTask ) ;
2020-12-06 04:59:32 +00:00
}
if ( this . disable . getValue ( ) ) {
if ( blocksToPlace . size ( ) = = 0 ) // no more blocks
this . toggle ( ) ; // auto disable
2019-10-27 15:45:44 +00:00
}
}
2020-12-06 04:59:32 +00:00
@Listener
public void onLoadWorld ( EventLoadWorld event ) {
if ( event . getWorld ( ) ! = null ) {
freeCamModule = ( FreeCamModule ) Seppuku . INSTANCE . getModuleManager ( ) . find ( FreeCamModule . class ) ;
2019-10-27 15:45:44 +00:00
}
2020-12-06 04:59:32 +00:00
}
2020-11-25 20:00:59 +00:00
private boolean valid ( BlockPos pos ) {
2021-01-09 04:56:10 +00:00
// There are no entities colliding with block placement
2020-12-06 04:59:32 +00:00
if ( ! mc . world . checkNoEntityCollision ( new AxisAlignedBB ( pos ) ) )
return false ;
2021-01-09 04:56:10 +00:00
// Player is too far from distance
2021-01-10 02:09:40 +00:00
if ( mc . player . getDistance ( pos . getX ( ) , pos . getY ( ) , pos . getZ ( ) ) > this . range . getValue ( ) )
2021-01-09 04:56:10 +00:00
return false ;
2019-11-27 02:54:16 +00:00
// Check if the block is replaceable
2021-01-08 06:32:44 +00:00
final Block block = mc . world . getBlockState ( pos ) . getBlock ( ) ;
return block . isReplaceable ( mc . world , pos ) & & ! ( block = = Blocks . OBSIDIAN ) & & ! ( block = = Blocks . BEDROCK ) ;
2019-10-27 15:45:44 +00:00
}
2019-12-04 17:10:26 +00:00
private void place ( BlockPos pos ) {
2019-11-27 02:54:16 +00:00
final Block block = mc . world . getBlockState ( pos ) . getBlock ( ) ;
2020-12-06 04:59:32 +00:00
final EnumFacing direction = this . calcSide ( pos ) ;
if ( direction = = null )
return ;
final boolean activated = block . onBlockActivated ( mc . world , pos , mc . world . getBlockState ( pos ) , mc . player , EnumHand . MAIN_HAND , direction , 0 , 0 , 0 ) ;
2019-12-10 21:41:39 +00:00
2019-12-05 22:48:49 +00:00
if ( activated )
2019-11-27 02:54:16 +00:00
mc . player . connection . sendPacket ( new CPacketEntityAction ( mc . player , CPacketEntityAction . Action . START_SNEAKING ) ) ;
2019-12-04 13:57:55 +00:00
2020-12-06 04:59:32 +00:00
final EnumFacing otherSide = direction . getOpposite ( ) ;
final BlockPos sideOffset = pos . offset ( direction ) ;
if ( rotate . getValue ( ) ) {
final float [ ] angle = MathUtil . calcAngle ( mc . player . getPositionEyes ( mc . getRenderPartialTicks ( ) ) , new Vec3d ( pos . getX ( ) + 0 . 5f , pos . getY ( ) + 0 . 5f , pos . getZ ( ) + 0 . 5f ) ) ;
Seppuku . INSTANCE . getRotationManager ( ) . setPlayerRotations ( angle [ 0 ] , angle [ 1 ] ) ;
2019-12-04 03:56:41 +00:00
}
2020-12-06 04:59:32 +00:00
if ( ! visible . getValue ( ) ) {
mc . player . connection . sendPacket ( new CPacketPlayerTryUseItemOnBlock ( sideOffset , otherSide , EnumHand . MAIN_HAND , 0 . 5F , 0 . 5F , 0 . 5F ) ) ;
mc . player . connection . sendPacket ( new CPacketAnimation ( EnumHand . MAIN_HAND ) ) ;
} else {
mc . playerController . processRightClickBlock ( mc . player , mc . world , sideOffset , otherSide , new Vec3d ( 0 . 5F , 0 . 5F , 0 . 5F ) , EnumHand . MAIN_HAND ) ;
mc . player . swingArm ( EnumHand . MAIN_HAND ) ;
}
2019-12-05 22:48:49 +00:00
if ( activated )
2019-11-27 02:54:16 +00:00
mc . player . connection . sendPacket ( new CPacketEntityAction ( mc . player , CPacketEntityAction . Action . STOP_SNEAKING ) ) ;
}
2019-12-04 17:10:26 +00:00
private EnumFacing calcSide ( BlockPos pos ) {
for ( EnumFacing side : EnumFacing . values ( ) ) {
2019-12-05 03:10:22 +00:00
BlockPos sideOffset = pos . offset ( side ) ;
IBlockState offsetState = mc . world . getBlockState ( sideOffset ) ;
2019-12-05 22:48:49 +00:00
if ( ! offsetState . getBlock ( ) . canCollideCheck ( offsetState , false ) ) continue ;
if ( ! offsetState . getMaterial ( ) . isReplaceable ( ) ) return side ;
2019-12-04 17:10:26 +00:00
}
return null ;
}
2019-10-27 15:45:44 +00:00
}