Skip to content

Commit

Permalink
Rewrite turtle block destroying
Browse files Browse the repository at this point in the history
 - 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.
  • Loading branch information
SquidDev committed Jul 5, 2018
1 parent 914df8b commit 9f3e1fd
Show file tree
Hide file tree
Showing 9 changed files with 212 additions and 213 deletions.
19 changes: 14 additions & 5 deletions src/main/java/dan200/computercraft/ComputerCraft.java
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,10 @@
import dan200.computercraft.shared.turtle.blocks.BlockTurtle;
import dan200.computercraft.shared.turtle.blocks.TileTurtle;
import dan200.computercraft.shared.turtle.upgrades.*;
import dan200.computercraft.shared.util.*;
import dan200.computercraft.shared.util.CreativeTabMain;
import dan200.computercraft.shared.util.IDAssigner;
import dan200.computercraft.shared.util.InventoryUtil;
import dan200.computercraft.shared.util.WorldUtil;
import io.netty.buffer.Unpooled;
import net.minecraft.entity.Entity;
import net.minecraft.entity.player.EntityPlayer;
Expand Down Expand Up @@ -85,6 +88,7 @@
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Consumer;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;

Expand Down Expand Up @@ -1015,13 +1019,18 @@ public static void addAllUpgradedTurtles( NonNullList<ItemStack> list )
turtleProxy.addAllUpgradedTurtles( list );
}

public static void setEntityDropConsumer( Entity entity, IEntityDropConsumer consumer )
public static void setDropConsumer( Entity entity, Consumer<ItemStack> consumer )
{
turtleProxy.setEntityDropConsumer( entity, consumer );
turtleProxy.setDropConsumer( entity, consumer );
}

public static void clearEntityDropConsumer( Entity entity )
public static void setDropConsumer( World world, BlockPos pos, Consumer<ItemStack> consumer )
{
turtleProxy.clearEntityDropConsumer( entity );
turtleProxy.setDropConsumer( world, pos, consumer );
}

public static void clearDropConsumer( )
{
turtleProxy.clearDropConsumer();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@
import dan200.computercraft.shared.turtle.items.TurtleItemFactory;
import dan200.computercraft.shared.turtle.recipes.TurtleUpgradeRecipe;
import dan200.computercraft.shared.turtle.upgrades.*;
import dan200.computercraft.shared.util.IEntityDropConsumer;
import dan200.computercraft.shared.util.ImpostorRecipe;
import dan200.computercraft.shared.util.InventoryUtil;
import net.minecraft.block.Block;
Expand All @@ -32,33 +31,47 @@
import net.minecraft.item.crafting.IRecipe;
import net.minecraft.util.NonNullList;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.event.RegistryEvent;
import net.minecraftforge.event.entity.EntityJoinWorldEvent;
import net.minecraftforge.event.entity.living.LivingDropsEvent;
import net.minecraftforge.event.world.BlockEvent;
import net.minecraftforge.fml.common.eventhandler.EventPriority;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
import net.minecraftforge.fml.common.registry.EntityRegistry;
import net.minecraftforge.fml.common.registry.GameRegistry;
import net.minecraftforge.registries.IForgeRegistry;

import javax.annotation.Nonnull;
import java.util.*;
import java.lang.ref.WeakReference;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Consumer;

public abstract class CCTurtleProxyCommon implements ICCTurtleProxy
{
{
private Map<Integer, ITurtleUpgrade> m_legacyTurtleUpgrades;
private Map<String, ITurtleUpgrade> m_turtleUpgrades;
private Map<Entity, IEntityDropConsumer> m_dropConsumers;

private Consumer<ItemStack> dropConsumer;
private WeakReference<World> dropWorld;
private BlockPos dropPos;
private AxisAlignedBB dropBounds;
private WeakReference<Entity> dropEntity;

public CCTurtleProxyCommon()
{
m_legacyTurtleUpgrades = new HashMap<>();
m_turtleUpgrades = new HashMap<>();
m_dropConsumers = new WeakHashMap<>();
}

// ICCTurtleProxy implementation
@Override

@Override
public void preInit()
{
MinecraftForge.EVENT_BUS.register( this );
Expand All @@ -74,8 +87,8 @@ public void preInit()
// RecipeSorter.register( "computercraft:turtle", TurtleRecipe.class, RecipeSorter.Category.SHAPED, "after:minecraft:shapeless" );
// RecipeSorter.register( "computercraft:turtle_upgrade", TurtleUpgradeRecipe.class, RecipeSorter.Category.SHAPED, "after:minecraft:shapeless" );
}
@Override

@Override
public void init()
{
registerForgeHandlers();
Expand All @@ -93,7 +106,7 @@ public void registerTurtleUpgrade( ITurtleUpgrade upgrade )
ComputerCraft.log.error( message );
throw new RuntimeException( message );
}

// Register
registerTurtleUpgradeInternal( upgrade );
}
Expand All @@ -109,7 +122,7 @@ public ITurtleUpgrade getTurtleUpgrade( int legacyId )
{
return m_legacyTurtleUpgrades.get( legacyId );
}

@Override
public ITurtleUpgrade getTurtleUpgrade( @Nonnull ItemStack stack )
{
Expand All @@ -125,7 +138,7 @@ public ITurtleUpgrade getTurtleUpgrade( @Nonnull ItemStack stack )
}
catch( Exception e )
{
ComputerCraft.log.error("Error getting computer upgrade item", e);
ComputerCraft.log.error( "Error getting computer upgrade item", e );
}
}
return null;
Expand All @@ -147,7 +160,7 @@ public static boolean isUpgradeSuitableForFamily( ComputerFamily family, ITurtle
return true;
}
}

private void addAllUpgradedTurtles( ComputerFamily family, NonNullList<ItemStack> list )
{
ItemStack basicStack = TurtleItemFactory.create( -1, null, -1, family, null, null, 0, null );
Expand All @@ -168,7 +181,7 @@ private void addAllUpgradedTurtles( ComputerFamily family, NonNullList<ItemStack

private void addUpgradedTurtle( ComputerFamily family, ITurtleUpgrade upgrade, List<ItemStack> list )
{
if ( isUpgradeSuitableForFamily( family, upgrade ) )
if( isUpgradeSuitableForFamily( family, upgrade ) )
{
ItemStack stack = TurtleItemFactory.create( -1, null, -1, family, upgrade, null, 0, null );
if( !stack.isEmpty() )
Expand All @@ -177,54 +190,58 @@ private void addUpgradedTurtle( ComputerFamily family, ITurtleUpgrade upgrade, L
}
}
}

@Override
public void addAllUpgradedTurtles( NonNullList<ItemStack> list )
{
addAllUpgradedTurtles( ComputerFamily.Normal, list );
addAllUpgradedTurtles( ComputerFamily.Advanced, list );
}

@Override
public void setEntityDropConsumer( Entity entity, IEntityDropConsumer consumer )
public void setDropConsumer( Entity entity, Consumer<ItemStack> consumer )
{
if( !m_dropConsumers.containsKey( entity ) )
{
boolean captured = entity.captureDrops;

if( !captured )
{
entity.captureDrops = true;
ArrayList<EntityItem> items = entity.capturedDrops;

if( items == null || items.size() == 0 )
{
m_dropConsumers.put( entity, consumer );
}
}
}
}

dropConsumer = consumer;
dropEntity = new WeakReference<>( entity );
dropWorld = new WeakReference<>( entity.world );
dropPos = null;
dropBounds = new AxisAlignedBB( entity.getPosition() ).grow( 2, 2, 2 );

entity.captureDrops = true;
}

@Override
public void clearEntityDropConsumer( Entity entity )
public void setDropConsumer( World world, BlockPos pos, Consumer<ItemStack> consumer )
{
if( m_dropConsumers.containsKey( entity ) )
dropConsumer = consumer;
dropEntity = null;
dropWorld = new WeakReference<>( world );
dropPos = pos;
dropBounds = new AxisAlignedBB( pos ).grow( 2, 2, 2 );
}

@Override
public void clearDropConsumer()
{
if( dropEntity != null )
{
boolean captured = entity.captureDrops;

if( captured )
Entity entity = dropEntity.get();
if( entity != null )
{
entity.captureDrops = false;
ArrayList<EntityItem> items = entity.capturedDrops;

if( items != null )
if( entity.capturedDrops != null )
{
dispatchEntityDrops( entity, items );
items.clear();
for( EntityItem entityItem : entity.capturedDrops ) dropConsumer.accept( entityItem.getItem() );
entity.capturedDrops.clear();
}
}
m_dropConsumers.remove( entity );
}

dropConsumer = null;
dropEntity = null;
dropWorld = null;
dropPos = null;
dropBounds = null;
}

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

registry.register( new ItemTurtleLegacy( ComputerCraft.Blocks.turtle).setRegistryName( new ResourceLocation( ComputerCraft.MOD_ID, "turtle" ) ) );
registry.register( new ItemTurtleLegacy( ComputerCraft.Blocks.turtle ).setRegistryName( new ResourceLocation( ComputerCraft.MOD_ID, "turtle" ) ) );
registry.register( new ItemTurtleNormal( ComputerCraft.Blocks.turtleExpanded ).setRegistryName( new ResourceLocation( ComputerCraft.MOD_ID, "turtle_expanded" ) ) );
registry.register( new ItemTurtleAdvanced( ComputerCraft.Blocks.turtleAdvanced ).setRegistryName( new ResourceLocation( ComputerCraft.MOD_ID, "turtle_advanced" ) ) );
}
Expand Down Expand Up @@ -361,7 +378,7 @@ public void registerRecipes( RegistryEvent.Register<IRecipe> event )
private void registerUpgrades()
{
// Upgrades
ComputerCraft.Upgrades.wirelessModem = new TurtleModem( false, new ResourceLocation( "computercraft", "wireless_modem" ), 1 );
ComputerCraft.Upgrades.wirelessModem = new TurtleModem( false, new ResourceLocation( "computercraft", "wireless_modem" ), 1 );
registerTurtleUpgradeInternal( ComputerCraft.Upgrades.wirelessModem );

ComputerCraft.Upgrades.craftingTable = new TurtleCraftingTable( 2 );
Expand Down Expand Up @@ -446,38 +463,53 @@ private void registerTileEntities()
GameRegistry.registerTileEntity( TileTurtleExpanded.class, ComputerCraft.LOWER_ID + " : " + "turtleex" );
GameRegistry.registerTileEntity( TileTurtleAdvanced.class, ComputerCraft.LOWER_ID + " : " + "turtleadv" );
}

private void registerForgeHandlers()
{
ForgeHandlers handlers = new ForgeHandlers();
MinecraftForge.EVENT_BUS.register( handlers );
}
public class ForgeHandlers

private class ForgeHandlers
{
private ForgeHandlers()
@SubscribeEvent
public void onEntityLivingDrops( LivingDropsEvent event )
{
// Capture any mob drops for the current entity
if( dropEntity != null && event.getEntity() == dropEntity.get() )
{
List<EntityItem> drops = event.getDrops();
for( EntityItem entityItem : drops ) dropConsumer.accept( entityItem.getItem() );
drops.clear();
}
}

// Forge event responses
@SubscribeEvent
public void onEntityLivingDrops( LivingDropsEvent event )
@SubscribeEvent(priority = EventPriority.LOWEST)
public void onHarvestDrops( BlockEvent.HarvestDropsEvent event )
{
dispatchEntityDrops( event.getEntity(), event.getDrops() );
// Capture block drops for the current entity
if( dropWorld != null && dropWorld.get() == event.getWorld()
&& dropPos != null && dropPos.equals( event.getPos() ) )
{
for( ItemStack item : event.getDrops() )
{
if( event.getWorld().rand.nextFloat() < event.getDropChance() ) dropConsumer.accept( item );
}
event.getDrops().clear();
}
}
}

private void dispatchEntityDrops( Entity entity, java.util.List<EntityItem> drops )
{
IEntityDropConsumer consumer = m_dropConsumers.get( entity );
if( consumer != null )

@SubscribeEvent(priority = EventPriority.LOWEST)
public void onEntitySpawn( EntityJoinWorldEvent event )
{
// All checks have passed, lets dispatch the drops
for(EntityItem entityItem : drops)
// Capture any nearby item spawns
if( dropWorld != null && dropWorld.get() == event.getWorld() && event.getEntity() instanceof EntityItem
&& dropBounds.contains( event.getEntity().getPositionVector() ) )
{
consumer.consumeDrop( entity, entityItem.getItem() );
dropConsumer.accept( ((EntityItem) event.getEntity()).getItem() );
event.setCanceled( true );
}
drops.clear();
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,14 @@
package dan200.computercraft.shared.proxy;

import dan200.computercraft.api.turtle.ITurtleUpgrade;
import dan200.computercraft.shared.util.IEntityDropConsumer;
import net.minecraft.entity.Entity;
import net.minecraft.item.ItemStack;
import net.minecraft.util.NonNullList;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;

import javax.annotation.Nonnull;
import java.util.function.Consumer;

public interface ICCTurtleProxy
{
Expand All @@ -25,6 +27,7 @@ public interface ICCTurtleProxy
ITurtleUpgrade getTurtleUpgrade( @Nonnull ItemStack item );
void addAllUpgradedTurtles( NonNullList<ItemStack> list );

void setEntityDropConsumer( Entity entity, IEntityDropConsumer consumer );
void clearEntityDropConsumer( Entity entity );
void setDropConsumer( Entity entity, Consumer<ItemStack> consumer );
void setDropConsumer( World world, BlockPos pos, Consumer<ItemStack> consumer );
void clearDropConsumer();
}
Original file line number Diff line number Diff line change
Expand Up @@ -224,7 +224,7 @@ private static ItemStack deployOnEntity( @Nonnull ItemStack stack, final ITurtle
// Start claiming entity drops
Entity hitEntity = hit.getKey();
Vec3d hitPos = hit.getValue();
ComputerCraft.setEntityDropConsumer( hitEntity, ( entity, drop ) ->
ComputerCraft.setDropConsumer( hitEntity, ( drop ) ->
{
ItemStack remainder = InventoryUtil.storeItems( drop, turtle.getItemHandler(), turtle.getSelectedSlot() );
if( !remainder.isEmpty() )
Expand Down Expand Up @@ -268,7 +268,7 @@ else if( hitEntity instanceof EntityLivingBase )
}

// Stop claiming drops
ComputerCraft.clearEntityDropConsumer( hitEntity );
ComputerCraft.clearDropConsumer();

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

0 comments on commit 9f3e1fd

Please sign in to comment.