Skip to content

Commit 9f3e1fd

Browse files
committed
Rewrite turtle block destroying
- Try to make drop capturing a little more generic. This now allows for capturing a block's drop at a given position, as well as any drop within a bounding box (for things which don't play nicely). - Use as much of Minecraft's block breaking logic as possible, hopefully simplifying things and making it more consistent with other mods.
1 parent 914df8b commit 9f3e1fd

9 files changed

Lines changed: 212 additions & 213 deletions

File tree

src/main/java/dan200/computercraft/ComputerCraft.java

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,10 @@
4848
import dan200.computercraft.shared.turtle.blocks.BlockTurtle;
4949
import dan200.computercraft.shared.turtle.blocks.TileTurtle;
5050
import dan200.computercraft.shared.turtle.upgrades.*;
51-
import dan200.computercraft.shared.util.*;
51+
import dan200.computercraft.shared.util.CreativeTabMain;
52+
import dan200.computercraft.shared.util.IDAssigner;
53+
import dan200.computercraft.shared.util.InventoryUtil;
54+
import dan200.computercraft.shared.util.WorldUtil;
5255
import io.netty.buffer.Unpooled;
5356
import net.minecraft.entity.Entity;
5457
import net.minecraft.entity.player.EntityPlayer;
@@ -85,6 +88,7 @@
8588
import java.util.HashMap;
8689
import java.util.List;
8790
import java.util.Map;
91+
import java.util.function.Consumer;
8892
import java.util.zip.ZipEntry;
8993
import java.util.zip.ZipFile;
9094

@@ -1015,13 +1019,18 @@ public static void addAllUpgradedTurtles( NonNullList<ItemStack> list )
10151019
turtleProxy.addAllUpgradedTurtles( list );
10161020
}
10171021

1018-
public static void setEntityDropConsumer( Entity entity, IEntityDropConsumer consumer )
1022+
public static void setDropConsumer( Entity entity, Consumer<ItemStack> consumer )
10191023
{
1020-
turtleProxy.setEntityDropConsumer( entity, consumer );
1024+
turtleProxy.setDropConsumer( entity, consumer );
10211025
}
10221026

1023-
public static void clearEntityDropConsumer( Entity entity )
1027+
public static void setDropConsumer( World world, BlockPos pos, Consumer<ItemStack> consumer )
10241028
{
1025-
turtleProxy.clearEntityDropConsumer( entity );
1029+
turtleProxy.setDropConsumer( world, pos, consumer );
1030+
}
1031+
1032+
public static void clearDropConsumer( )
1033+
{
1034+
turtleProxy.clearDropConsumer();
10261035
}
10271036
}

src/main/java/dan200/computercraft/shared/proxy/CCTurtleProxyCommon.java

Lines changed: 98 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@
2020
import dan200.computercraft.shared.turtle.items.TurtleItemFactory;
2121
import dan200.computercraft.shared.turtle.recipes.TurtleUpgradeRecipe;
2222
import dan200.computercraft.shared.turtle.upgrades.*;
23-
import dan200.computercraft.shared.util.IEntityDropConsumer;
2423
import dan200.computercraft.shared.util.ImpostorRecipe;
2524
import dan200.computercraft.shared.util.InventoryUtil;
2625
import net.minecraft.block.Block;
@@ -32,33 +31,47 @@
3231
import net.minecraft.item.crafting.IRecipe;
3332
import net.minecraft.util.NonNullList;
3433
import net.minecraft.util.ResourceLocation;
34+
import net.minecraft.util.math.AxisAlignedBB;
35+
import net.minecraft.util.math.BlockPos;
36+
import net.minecraft.world.World;
3537
import net.minecraftforge.common.MinecraftForge;
3638
import net.minecraftforge.event.RegistryEvent;
39+
import net.minecraftforge.event.entity.EntityJoinWorldEvent;
3740
import net.minecraftforge.event.entity.living.LivingDropsEvent;
41+
import net.minecraftforge.event.world.BlockEvent;
42+
import net.minecraftforge.fml.common.eventhandler.EventPriority;
3843
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
3944
import net.minecraftforge.fml.common.registry.EntityRegistry;
4045
import net.minecraftforge.fml.common.registry.GameRegistry;
4146
import net.minecraftforge.registries.IForgeRegistry;
4247

4348
import javax.annotation.Nonnull;
44-
import java.util.*;
49+
import java.lang.ref.WeakReference;
50+
import java.util.HashMap;
51+
import java.util.List;
52+
import java.util.Map;
53+
import java.util.function.Consumer;
4554

4655
public abstract class CCTurtleProxyCommon implements ICCTurtleProxy
47-
{
56+
{
4857
private Map<Integer, ITurtleUpgrade> m_legacyTurtleUpgrades;
4958
private Map<String, ITurtleUpgrade> m_turtleUpgrades;
50-
private Map<Entity, IEntityDropConsumer> m_dropConsumers;
59+
60+
private Consumer<ItemStack> dropConsumer;
61+
private WeakReference<World> dropWorld;
62+
private BlockPos dropPos;
63+
private AxisAlignedBB dropBounds;
64+
private WeakReference<Entity> dropEntity;
5165

5266
public CCTurtleProxyCommon()
5367
{
5468
m_legacyTurtleUpgrades = new HashMap<>();
5569
m_turtleUpgrades = new HashMap<>();
56-
m_dropConsumers = new WeakHashMap<>();
5770
}
58-
71+
5972
// ICCTurtleProxy implementation
60-
61-
@Override
73+
74+
@Override
6275
public void preInit()
6376
{
6477
MinecraftForge.EVENT_BUS.register( this );
@@ -74,8 +87,8 @@ public void preInit()
7487
// RecipeSorter.register( "computercraft:turtle", TurtleRecipe.class, RecipeSorter.Category.SHAPED, "after:minecraft:shapeless" );
7588
// RecipeSorter.register( "computercraft:turtle_upgrade", TurtleUpgradeRecipe.class, RecipeSorter.Category.SHAPED, "after:minecraft:shapeless" );
7689
}
77-
78-
@Override
90+
91+
@Override
7992
public void init()
8093
{
8194
registerForgeHandlers();
@@ -93,7 +106,7 @@ public void registerTurtleUpgrade( ITurtleUpgrade upgrade )
93106
ComputerCraft.log.error( message );
94107
throw new RuntimeException( message );
95108
}
96-
109+
97110
// Register
98111
registerTurtleUpgradeInternal( upgrade );
99112
}
@@ -109,7 +122,7 @@ public ITurtleUpgrade getTurtleUpgrade( int legacyId )
109122
{
110123
return m_legacyTurtleUpgrades.get( legacyId );
111124
}
112-
125+
113126
@Override
114127
public ITurtleUpgrade getTurtleUpgrade( @Nonnull ItemStack stack )
115128
{
@@ -125,7 +138,7 @@ public ITurtleUpgrade getTurtleUpgrade( @Nonnull ItemStack stack )
125138
}
126139
catch( Exception e )
127140
{
128-
ComputerCraft.log.error("Error getting computer upgrade item", e);
141+
ComputerCraft.log.error( "Error getting computer upgrade item", e );
129142
}
130143
}
131144
return null;
@@ -147,7 +160,7 @@ public static boolean isUpgradeSuitableForFamily( ComputerFamily family, ITurtle
147160
return true;
148161
}
149162
}
150-
163+
151164
private void addAllUpgradedTurtles( ComputerFamily family, NonNullList<ItemStack> list )
152165
{
153166
ItemStack basicStack = TurtleItemFactory.create( -1, null, -1, family, null, null, 0, null );
@@ -168,7 +181,7 @@ private void addAllUpgradedTurtles( ComputerFamily family, NonNullList<ItemStack
168181

169182
private void addUpgradedTurtle( ComputerFamily family, ITurtleUpgrade upgrade, List<ItemStack> list )
170183
{
171-
if ( isUpgradeSuitableForFamily( family, upgrade ) )
184+
if( isUpgradeSuitableForFamily( family, upgrade ) )
172185
{
173186
ItemStack stack = TurtleItemFactory.create( -1, null, -1, family, upgrade, null, 0, null );
174187
if( !stack.isEmpty() )
@@ -177,54 +190,58 @@ private void addUpgradedTurtle( ComputerFamily family, ITurtleUpgrade upgrade, L
177190
}
178191
}
179192
}
180-
193+
181194
@Override
182195
public void addAllUpgradedTurtles( NonNullList<ItemStack> list )
183196
{
184197
addAllUpgradedTurtles( ComputerFamily.Normal, list );
185198
addAllUpgradedTurtles( ComputerFamily.Advanced, list );
186199
}
187-
200+
188201
@Override
189-
public void setEntityDropConsumer( Entity entity, IEntityDropConsumer consumer )
202+
public void setDropConsumer( Entity entity, Consumer<ItemStack> consumer )
190203
{
191-
if( !m_dropConsumers.containsKey( entity ) )
192-
{
193-
boolean captured = entity.captureDrops;
194-
195-
if( !captured )
196-
{
197-
entity.captureDrops = true;
198-
ArrayList<EntityItem> items = entity.capturedDrops;
199-
200-
if( items == null || items.size() == 0 )
201-
{
202-
m_dropConsumers.put( entity, consumer );
203-
}
204-
}
205-
}
206-
}
207-
204+
dropConsumer = consumer;
205+
dropEntity = new WeakReference<>( entity );
206+
dropWorld = new WeakReference<>( entity.world );
207+
dropPos = null;
208+
dropBounds = new AxisAlignedBB( entity.getPosition() ).grow( 2, 2, 2 );
209+
210+
entity.captureDrops = true;
211+
}
212+
208213
@Override
209-
public void clearEntityDropConsumer( Entity entity )
214+
public void setDropConsumer( World world, BlockPos pos, Consumer<ItemStack> consumer )
210215
{
211-
if( m_dropConsumers.containsKey( entity ) )
216+
dropConsumer = consumer;
217+
dropEntity = null;
218+
dropWorld = new WeakReference<>( world );
219+
dropPos = pos;
220+
dropBounds = new AxisAlignedBB( pos ).grow( 2, 2, 2 );
221+
}
222+
223+
@Override
224+
public void clearDropConsumer()
225+
{
226+
if( dropEntity != null )
212227
{
213-
boolean captured = entity.captureDrops;
214-
215-
if( captured )
228+
Entity entity = dropEntity.get();
229+
if( entity != null )
216230
{
217231
entity.captureDrops = false;
218-
ArrayList<EntityItem> items = entity.capturedDrops;
219-
220-
if( items != null )
232+
if( entity.capturedDrops != null )
221233
{
222-
dispatchEntityDrops( entity, items );
223-
items.clear();
234+
for( EntityItem entityItem : entity.capturedDrops ) dropConsumer.accept( entityItem.getItem() );
235+
entity.capturedDrops.clear();
224236
}
225237
}
226-
m_dropConsumers.remove( entity );
227238
}
239+
240+
dropConsumer = null;
241+
dropEntity = null;
242+
dropWorld = null;
243+
dropPos = null;
244+
dropBounds = null;
228245
}
229246

230247
private void registerTurtleUpgradeInternal( ITurtleUpgrade upgrade )
@@ -288,7 +305,7 @@ public void registerItems( RegistryEvent.Register<Item> event )
288305
{
289306
IForgeRegistry<Item> registry = event.getRegistry();
290307

291-
registry.register( new ItemTurtleLegacy( ComputerCraft.Blocks.turtle).setRegistryName( new ResourceLocation( ComputerCraft.MOD_ID, "turtle" ) ) );
308+
registry.register( new ItemTurtleLegacy( ComputerCraft.Blocks.turtle ).setRegistryName( new ResourceLocation( ComputerCraft.MOD_ID, "turtle" ) ) );
292309
registry.register( new ItemTurtleNormal( ComputerCraft.Blocks.turtleExpanded ).setRegistryName( new ResourceLocation( ComputerCraft.MOD_ID, "turtle_expanded" ) ) );
293310
registry.register( new ItemTurtleAdvanced( ComputerCraft.Blocks.turtleAdvanced ).setRegistryName( new ResourceLocation( ComputerCraft.MOD_ID, "turtle_advanced" ) ) );
294311
}
@@ -361,7 +378,7 @@ public void registerRecipes( RegistryEvent.Register<IRecipe> event )
361378
private void registerUpgrades()
362379
{
363380
// Upgrades
364-
ComputerCraft.Upgrades.wirelessModem = new TurtleModem( false, new ResourceLocation( "computercraft", "wireless_modem" ), 1 );
381+
ComputerCraft.Upgrades.wirelessModem = new TurtleModem( false, new ResourceLocation( "computercraft", "wireless_modem" ), 1 );
365382
registerTurtleUpgradeInternal( ComputerCraft.Upgrades.wirelessModem );
366383

367384
ComputerCraft.Upgrades.craftingTable = new TurtleCraftingTable( 2 );
@@ -446,38 +463,53 @@ private void registerTileEntities()
446463
GameRegistry.registerTileEntity( TileTurtleExpanded.class, ComputerCraft.LOWER_ID + " : " + "turtleex" );
447464
GameRegistry.registerTileEntity( TileTurtleAdvanced.class, ComputerCraft.LOWER_ID + " : " + "turtleadv" );
448465
}
449-
466+
450467
private void registerForgeHandlers()
451468
{
452469
ForgeHandlers handlers = new ForgeHandlers();
453470
MinecraftForge.EVENT_BUS.register( handlers );
454471
}
455-
456-
public class ForgeHandlers
472+
473+
private class ForgeHandlers
457474
{
458-
private ForgeHandlers()
475+
@SubscribeEvent
476+
public void onEntityLivingDrops( LivingDropsEvent event )
459477
{
478+
// Capture any mob drops for the current entity
479+
if( dropEntity != null && event.getEntity() == dropEntity.get() )
480+
{
481+
List<EntityItem> drops = event.getDrops();
482+
for( EntityItem entityItem : drops ) dropConsumer.accept( entityItem.getItem() );
483+
drops.clear();
484+
}
460485
}
461486

462-
// Forge event responses
463-
@SubscribeEvent
464-
public void onEntityLivingDrops( LivingDropsEvent event )
487+
@SubscribeEvent(priority = EventPriority.LOWEST)
488+
public void onHarvestDrops( BlockEvent.HarvestDropsEvent event )
465489
{
466-
dispatchEntityDrops( event.getEntity(), event.getDrops() );
490+
// Capture block drops for the current entity
491+
if( dropWorld != null && dropWorld.get() == event.getWorld()
492+
&& dropPos != null && dropPos.equals( event.getPos() ) )
493+
{
494+
for( ItemStack item : event.getDrops() )
495+
{
496+
if( event.getWorld().rand.nextFloat() < event.getDropChance() ) dropConsumer.accept( item );
497+
}
498+
event.getDrops().clear();
499+
}
467500
}
468-
}
469-
470-
private void dispatchEntityDrops( Entity entity, java.util.List<EntityItem> drops )
471-
{
472-
IEntityDropConsumer consumer = m_dropConsumers.get( entity );
473-
if( consumer != null )
501+
502+
@SubscribeEvent(priority = EventPriority.LOWEST)
503+
public void onEntitySpawn( EntityJoinWorldEvent event )
474504
{
475-
// All checks have passed, lets dispatch the drops
476-
for(EntityItem entityItem : drops)
505+
// Capture any nearby item spawns
506+
if( dropWorld != null && dropWorld.get() == event.getWorld() && event.getEntity() instanceof EntityItem
507+
&& dropBounds.contains( event.getEntity().getPositionVector() ) )
477508
{
478-
consumer.consumeDrop( entity, entityItem.getItem() );
509+
dropConsumer.accept( ((EntityItem) event.getEntity()).getItem() );
510+
event.setCanceled( true );
479511
}
480-
drops.clear();
481512
}
482513
}
514+
483515
}

src/main/java/dan200/computercraft/shared/proxy/ICCTurtleProxy.java

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,14 @@
77
package dan200.computercraft.shared.proxy;
88

99
import dan200.computercraft.api.turtle.ITurtleUpgrade;
10-
import dan200.computercraft.shared.util.IEntityDropConsumer;
1110
import net.minecraft.entity.Entity;
1211
import net.minecraft.item.ItemStack;
1312
import net.minecraft.util.NonNullList;
13+
import net.minecraft.util.math.BlockPos;
14+
import net.minecraft.world.World;
1415

1516
import javax.annotation.Nonnull;
17+
import java.util.function.Consumer;
1618

1719
public interface ICCTurtleProxy
1820
{
@@ -25,6 +27,7 @@ public interface ICCTurtleProxy
2527
ITurtleUpgrade getTurtleUpgrade( @Nonnull ItemStack item );
2628
void addAllUpgradedTurtles( NonNullList<ItemStack> list );
2729

28-
void setEntityDropConsumer( Entity entity, IEntityDropConsumer consumer );
29-
void clearEntityDropConsumer( Entity entity );
30+
void setDropConsumer( Entity entity, Consumer<ItemStack> consumer );
31+
void setDropConsumer( World world, BlockPos pos, Consumer<ItemStack> consumer );
32+
void clearDropConsumer();
3033
}

src/main/java/dan200/computercraft/shared/turtle/core/TurtlePlaceCommand.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -224,7 +224,7 @@ private static ItemStack deployOnEntity( @Nonnull ItemStack stack, final ITurtle
224224
// Start claiming entity drops
225225
Entity hitEntity = hit.getKey();
226226
Vec3d hitPos = hit.getValue();
227-
ComputerCraft.setEntityDropConsumer( hitEntity, ( entity, drop ) ->
227+
ComputerCraft.setDropConsumer( hitEntity, ( drop ) ->
228228
{
229229
ItemStack remainder = InventoryUtil.storeItems( drop, turtle.getItemHandler(), turtle.getSelectedSlot() );
230230
if( !remainder.isEmpty() )
@@ -268,7 +268,7 @@ else if( hitEntity instanceof EntityLivingBase )
268268
}
269269

270270
// Stop claiming drops
271-
ComputerCraft.clearEntityDropConsumer( hitEntity );
271+
ComputerCraft.clearDropConsumer();
272272

273273
// Put everything we collected into the turtles inventory, then return
274274
ItemStack remainder = turtlePlayer.unloadInventory( turtle );

0 commit comments

Comments
 (0)