1010import gregtech .api .util .GTTransferUtils ;
1111import gregtech .api .util .GregFakePlayer ;
1212import gregtech .api .util .Mods ;
13+ import gregtech .api .util .function .TriPredicate ;
1314import gregtech .client .renderer .texture .Textures ;
1415import gregtech .client .utils .RenderUtil ;
1516
1617import net .minecraft .block .Block ;
1718import net .minecraft .block .BlockLiquid ;
18- import net .minecraft .block .material .Material ;
1919import net .minecraft .block .state .IBlockState ;
2020import net .minecraft .client .resources .I18n ;
2121import net .minecraft .entity .item .EntityItem ;
3131import net .minecraft .util .math .MathHelper ;
3232import net .minecraft .world .World ;
3333import net .minecraft .world .WorldServer ;
34+ import net .minecraftforge .common .util .FakePlayer ;
3435import net .minecraftforge .items .IItemHandlerModifiable ;
3536
3637import codechicken .lib .raytracer .CuboidRayTraceResult ;
4647import com .cleanroommc .modularui .widgets .ItemSlot ;
4748import com .cleanroommc .modularui .widgets .SlotGroupWidget ;
4849import com .cleanroommc .modularui .widgets .layout .Grid ;
50+ import com .feed_the_beast .ftblib .lib .EnumTeamStatus ;
51+ import com .feed_the_beast .ftblib .lib .data .ForgePlayer ;
4952import com .feed_the_beast .ftblib .lib .math .ChunkDimPos ;
5053import com .feed_the_beast .ftbutilities .data .ClaimedChunk ;
5154import com .feed_the_beast .ftbutilities .data .ClaimedChunks ;
55+ import it .unimi .dsi .fastutil .objects .ObjectArrayList ;
5256import org .jetbrains .annotations .NotNull ;
5357import org .jetbrains .annotations .Nullable ;
5458
@@ -63,6 +67,42 @@ public class MetaTileEntityBlockBreaker extends TieredMetaTileEntity {
6367 private EnumFacing outputFacing ;
6468 private int breakProgressTicksLeft ;
6569 private float currentBlockHardness ;
70+ private static final List <@ NotNull TriPredicate <@ NotNull World , @ NotNull BlockPos , @ NotNull FakePlayer >> PREDICATE_LIST = new ObjectArrayList <>(
71+ 2 );
72+
73+ static {
74+ PREDICATE_LIST .add ((world , blockPos , fakePlayer ) -> !world .isAirBlock (blockPos ));
75+ PREDICATE_LIST .add (
76+ (world , blockPos , fakePlayer ) -> !(world .getBlockState (blockPos ).getBlock () instanceof BlockLiquid ));
77+ PREDICATE_LIST .add ((world , blockPos , fakePlayer ) -> world .isBlockModifiable (fakePlayer , blockPos ));
78+ if (Mods .FTB_UTILITIES .isModLoaded ()) {
79+ PREDICATE_LIST .add ((world , blockPos , fakePlayer ) -> {
80+ ClaimedChunks instance = ClaimedChunks .instance ;
81+ ClaimedChunk claimedChunk = instance .getChunk (new ChunkDimPos (blockPos , world .provider .getDimension ()));
82+ if (claimedChunk != null ) {
83+ ForgePlayer forgePlayer = instance .universe .getPlayer (fakePlayer .getUniqueID ());
84+ EnumTeamStatus status = claimedChunk .getData ().getEditBlocksStatus ();
85+ return !claimedChunk .getTeam ().hasStatus (forgePlayer , status );
86+ } else {
87+ return true ;
88+ }
89+ });
90+ }
91+ }
92+
93+ /**
94+ * Add a predicate check to the block breaker. Intended to be used to prevent a certain block from being broken.
95+ * <br/>
96+ * <b>Warning!</b> the {@link FakePlayer} passed to the predicate is not a real player, but a fake one with
97+ * the same UUID as the real player who placed the block breaker <br/>
98+ * Return {@code false} to cancel a break attempt on this block. <br/>
99+ * Return {@code true} to move onto the next predicate, and eventually break the block only if all other predicates
100+ * returned {@code false}.
101+ */
102+ @ SuppressWarnings ("unused" )
103+ public static void registerBlockBreakerPredicate (@ NotNull TriPredicate <@ NotNull World , @ NotNull BlockPos , @ NotNull FakePlayer > predicate ) {
104+ PREDICATE_LIST .add (predicate );
105+ }
66106
67107 public MetaTileEntityBlockBreaker (ResourceLocation metaTileEntityId , int tier ) {
68108 super (metaTileEntityId , tier );
@@ -89,84 +129,78 @@ public void update() {
89129
90130 World world = getWorld ();
91131 if (!world .isRemote ) {
92- EntityPlayer fakePlayer = GregFakePlayer .get ((WorldServer ) world , getOwner ());
93- BlockPos selfPos = getPos ();
94- BlockPos lookingAtPos = selfPos .offset (getFrontFacing ());
132+ tryBreakBlock (world );
95133
96- boolean canEditBlock = world .isBlockModifiable (fakePlayer , lookingAtPos );
97- if (Mods .FTB_UTILITIES .isModLoaded ()) {
98- ClaimedChunks instance = ClaimedChunks .instance ;
99- ClaimedChunk claimedChunk = instance
100- .getChunk (new ChunkDimPos (lookingAtPos , world .provider .getDimension ()));
101- if (claimedChunk != null ) {
102- canEditBlock &= claimedChunk .getTeam ()
103- .hasStatus (instance .universe .getPlayer (getOwner ()),
104- claimedChunk .getData ().getEditBlocksStatus ());
105- }
134+ if (getOffsetTimer () % 5 == 0 ) {
135+ pushItemsIntoNearbyHandlers (getOutputFacing ());
106136 }
137+ }
138+ }
107139
108- if (breakProgressTicksLeft > 0 ) {
109- --breakProgressTicksLeft ;
110- if (breakProgressTicksLeft == 0 && energyContainer .getEnergyStored () >= getEnergyPerBlockBreak ()) {
111- IBlockState blockState = getWorld ().getBlockState (lookingAtPos );
112- float hardness = blockState .getBlockHardness (getWorld (), lookingAtPos );
113-
114- if (hardness >= 0.0f && canEditBlock && Math .abs (hardness - currentBlockHardness ) < 0.5f ) {
115- List <ItemStack > drops = attemptBreakBlockAndObtainDrops (lookingAtPos , blockState , fakePlayer );
116- addToInventoryOrDropItems (drops );
117- }
140+ protected void tryBreakBlock (@ NotNull World world ) {
141+ BlockPos selfPos = getPos ();
142+ BlockPos lookingAtPos = selfPos .offset (getFrontFacing ());
143+ FakePlayer fakePlayer = GregFakePlayer .get ((WorldServer ) world , getOwner ());
118144
119- currentBlockHardness = 0.0f ;
120- energyContainer . removeEnergy ( getEnergyPerBlockBreak ());
121- }
145+ for ( TriPredicate < World , BlockPos , FakePlayer > predicate : PREDICATE_LIST ) {
146+ if (! predicate . test ( world , lookingAtPos , fakePlayer )) {
147+ return ;
122148 }
149+ }
123150
124- if (breakProgressTicksLeft == 0 && isBlockRedstonePowered () && canEditBlock ) {
125- IBlockState blockState = getWorld ().getBlockState (lookingAtPos );
126- float hardness = blockState .getBlockHardness (getWorld (), lookingAtPos );
127- boolean skipBlock = blockState .getMaterial () == Material .AIR ||
128- blockState .getBlock ().isAir (blockState , getWorld (), getPos ()) ||
129- blockState .getBlock () instanceof BlockLiquid ;
130- if (!skipBlock && hardness >= 0.0f ) {
131- breakProgressTicksLeft = getTicksPerBlockBreak (hardness );
132- currentBlockHardness = hardness ;
133- }
151+ IBlockState blockState = world .getBlockState (lookingAtPos );
152+ if (breakProgressTicksLeft > 0 && --breakProgressTicksLeft == 0 &&
153+ energyContainer .getEnergyStored () >= getEnergyPerBlockBreak ()) {
154+ float hardness = blockState .getBlockHardness (world , lookingAtPos );
155+ if (hardness >= 0.0f && Math .abs (hardness - currentBlockHardness ) < 0.5f ) {
156+ List <ItemStack > drops = attemptBreakBlockAndObtainDrops (world , lookingAtPos , blockState , fakePlayer );
157+ addToInventoryOrDropItems (drops , world , getFrontFacing ());
134158 }
135159
136- if (getOffsetTimer () % 5 == 0 ) {
137- pushItemsIntoNearbyHandlers (getOutputFacing ());
160+ currentBlockHardness = 0.0f ;
161+ energyContainer .removeEnergy (getEnergyPerBlockBreak ());
162+ }
163+
164+ if (breakProgressTicksLeft == 0 && isBlockRedstonePowered ()) {
165+ float hardness = blockState .getBlockHardness (world , lookingAtPos );
166+ if (hardness >= 0.0f ) {
167+ breakProgressTicksLeft = getTicksPerBlockBreak (hardness );
168+ currentBlockHardness = hardness ;
138169 }
139170 }
140171 }
141172
142- private void addToInventoryOrDropItems (List <ItemStack > drops ) {
143- EnumFacing outputFacing = getOutputFacing ();
144- double itemSpawnX = getPos ().getX () + 0.5 + outputFacing .getXOffset ();
145- double itemSpawnY = getPos ().getY () + 0.5 + outputFacing .getYOffset ();
146- double itemSpawnZ = getPos ().getZ () + 0.5 + outputFacing .getZOffset ();
173+ protected void addToInventoryOrDropItems (@ NotNull List <ItemStack > drops , @ NotNull World world ,
174+ @ NotNull EnumFacing frontFacing ) {
175+ double itemSpawnX = getPos ().getX () + 0.5 + frontFacing .getXOffset ();
176+ double itemSpawnY = getPos ().getY () + 0.5 + frontFacing .getYOffset ();
177+ double itemSpawnZ = getPos ().getZ () + 0.5 + frontFacing .getZOffset ();
147178 for (ItemStack itemStack : drops ) {
148179 ItemStack remainStack = GTTransferUtils .insertItem (exportItems , itemStack , false );
149180 if (!remainStack .isEmpty ()) {
150- EntityItem entityitem = new EntityItem (getWorld () , itemSpawnX , itemSpawnY , itemSpawnZ , remainStack );
181+ EntityItem entityitem = new EntityItem (world , itemSpawnX , itemSpawnY , itemSpawnZ , remainStack );
151182 entityitem .setDefaultPickupDelay ();
152- getWorld () .spawnEntity (entityitem );
183+ world .spawnEntity (entityitem );
153184 }
154185 }
155186 }
156187
157- private List <ItemStack > attemptBreakBlockAndObtainDrops (BlockPos blockPos , IBlockState blockState ,
158- EntityPlayer entityPlayer ) {
159- TileEntity tileEntity = getWorld ().getTileEntity (blockPos );
160- boolean result = blockState .getBlock ().removedByPlayer (blockState , getWorld (), blockPos , entityPlayer , true );
188+ protected @ NotNull List <ItemStack > attemptBreakBlockAndObtainDrops (@ NotNull World world ,
189+ @ NotNull BlockPos lookingAtPos ,
190+ @ NotNull IBlockState blockState ,
191+ @ NotNull EntityPlayer entityPlayer ) {
192+ TileEntity tileEntity = world .getTileEntity (lookingAtPos );
193+ Block block = blockState .getBlock ();
194+ boolean result = block .removedByPlayer (blockState , world , lookingAtPos , entityPlayer , true );
161195 if (result ) {
162- getWorld () .playEvent (null , 2001 , blockPos , Block .getStateId (blockState ));
163- blockState . getBlock (). onPlayerDestroy (getWorld (), blockPos , blockState );
196+ world .playEvent (null , 2001 , lookingAtPos , Block .getStateId (blockState ));
197+ block . onPlayerDestroy (world , lookingAtPos , blockState );
164198
165199 BlockUtility .startCaptureDrops ();
166- blockState .getBlock ().harvestBlock (getWorld (), entityPlayer , blockPos , blockState , tileEntity ,
167- ItemStack .EMPTY );
200+ block .harvestBlock (world , entityPlayer , lookingAtPos , blockState , tileEntity , ItemStack .EMPTY );
168201 return BlockUtility .stopCaptureDrops ();
169202 }
203+
170204 return Collections .emptyList ();
171205 }
172206
@@ -249,23 +283,23 @@ public void setFrontFacing(EnumFacing frontFacing) {
249283 }
250284 }
251285
252- private int getEnergyPerBlockBreak () {
286+ public int getEnergyPerBlockBreak () {
253287 return (int ) GTValues .V [getTier ()];
254288 }
255289
256- private int getInventorySize () {
290+ protected int getInventorySize () {
257291 int sizeRoot = (1 + getTier ());
258292 return sizeRoot * sizeRoot ;
259293 }
260294
261- private int getTicksPerBlockBreak (float blockHardness ) {
295+ public int getTicksPerBlockBreak (float blockHardness ) {
262296 int ticksPerOneDurability = 5 ;
263297 int totalTicksPerBlock = (int ) Math .ceil (ticksPerOneDurability * blockHardness );
264298 float efficiencyMultiplier = 1.0f - getEfficiencyMultiplier ();
265299 return (int ) Math .ceil (totalTicksPerBlock * efficiencyMultiplier );
266300 }
267301
268- private float getEfficiencyMultiplier () {
302+ public float getEfficiencyMultiplier () {
269303 return 1.0f - MathHelper .clamp (1.0f - 0.2f * (getTier () - 1.0f ), 0.1f , 1.0f );
270304 }
271305
0 commit comments