1
0
mirror of https://github.com/SquidDev-CC/CC-Tweaked synced 2025-11-12 19:33:00 +00:00

Add turtle events

The main aim of this is to allow for greater extensibility for other
mods. For instance, you can now prevent turtles placing dirt blocks, or
turning when on gravel.
This commit is contained in:
SquidDev
2018-02-16 10:33:32 +00:00
parent 3b3dd8071b
commit ecff23d027
19 changed files with 801 additions and 16 deletions

View File

@@ -11,11 +11,14 @@ import dan200.computercraft.api.lua.LuaException;
import dan200.computercraft.api.turtle.ITurtleAccess;
import dan200.computercraft.api.turtle.ITurtleCommand;
import dan200.computercraft.api.turtle.TurtleSide;
import dan200.computercraft.api.turtle.event.TurtleAction;
import dan200.computercraft.api.turtle.event.TurtleActionEvent;
import dan200.computercraft.core.apis.IAPIEnvironment;
import dan200.computercraft.core.apis.ILuaAPI;
import dan200.computercraft.shared.turtle.core.*;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraftforge.common.MinecraftForge;
import javax.annotation.Nonnull;
import java.util.HashMap;
@@ -439,6 +442,13 @@ public class TurtleAPI implements ILuaAPI
table.put( "name", name );
table.put( "damage", damage );
table.put( "count", count );
TurtleActionEvent event = new TurtleActionEvent( m_turtle, TurtleAction.INSPECT_ITEM );
if( MinecraftForge.EVENT_BUS.post( event ) )
{
return new Object[] { false, event.getFailureMessage() };
}
return new Object[] { table };
}
else

View File

@@ -10,12 +10,14 @@ import dan200.computercraft.api.turtle.ITurtleAccess;
import dan200.computercraft.api.turtle.ITurtleCommand;
import dan200.computercraft.api.turtle.TurtleAnimation;
import dan200.computercraft.api.turtle.TurtleCommandResult;
import dan200.computercraft.api.turtle.event.TurtleInventoryEvent;
import dan200.computercraft.shared.util.InventoryUtil;
import dan200.computercraft.shared.util.WorldUtil;
import net.minecraft.item.ItemStack;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.items.IItemHandler;
import javax.annotation.Nonnull;
@@ -59,6 +61,16 @@ public class TurtleDropCommand implements ITurtleCommand
EnumFacing side = direction.getOpposite();
IItemHandler inventory = InventoryUtil.getInventory( world, newPosition, side );
// Fire the event, restoring the inventory and exiting if it is cancelled.
TurtlePlayer player = TurtlePlaceCommand.createPlayer( turtle, oldPosition, direction );
TurtleInventoryEvent.Drop event = new TurtleInventoryEvent.Drop( turtle, player, world, newPosition, inventory, stack );
if( MinecraftForge.EVENT_BUS.post( event ) )
{
InventoryUtil.storeItems( stack, turtle.getItemHandler(), turtle.getSelectedSlot() );
return TurtleCommandResult.failure( event.getFailureMessage() );
}
if( inventory != null )
{
// Drop the item into the inventory

View File

@@ -8,11 +8,14 @@ package dan200.computercraft.shared.turtle.core;
import dan200.computercraft.ComputerCraft;
import dan200.computercraft.api.turtle.*;
import dan200.computercraft.api.turtle.event.TurtleAction;
import dan200.computercraft.api.turtle.event.TurtleActionEvent;
import dan200.computercraft.shared.proxy.CCTurtleProxyCommon;
import dan200.computercraft.shared.util.InventoryUtil;
import dan200.computercraft.shared.util.WorldUtil;
import net.minecraft.item.ItemStack;
import net.minecraft.util.math.BlockPos;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.items.IItemHandler;
import javax.annotation.Nonnull;
@@ -63,6 +66,12 @@ public class TurtleEquipCommand implements ITurtleCommand
oldUpgradeStack = null;
}
TurtleActionEvent event = new TurtleActionEvent( turtle, TurtleAction.EQUIP );
if( MinecraftForge.EVENT_BUS.post( event ) )
{
return TurtleCommandResult.failure( event.getFailureMessage() );
}
// Do the swapping:
if( newUpgradeStack != null )
{

View File

@@ -10,13 +10,15 @@ import com.google.common.collect.ImmutableMap;
import dan200.computercraft.api.turtle.ITurtleAccess;
import dan200.computercraft.api.turtle.ITurtleCommand;
import dan200.computercraft.api.turtle.TurtleCommandResult;
import dan200.computercraft.api.turtle.event.TurtleBlockEvent;
import dan200.computercraft.shared.util.WorldUtil;
import net.minecraft.block.Block;
import net.minecraft.block.properties.IProperty;
import net.minecraft.block.state.IBlockState;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import net.minecraftforge.common.MinecraftForge;
import javax.annotation.Nonnull;
import java.util.HashMap;
@@ -46,14 +48,14 @@ public class TurtleInspectCommand implements ITurtleCommand
if( WorldUtil.isBlockInWorld( world, newPosition ) )
{
if( !FAIL_ON_AIR || !world.isAirBlock( newPosition ) )
IBlockState state = world.getBlockState( newPosition );
if( !FAIL_ON_AIR || !state.getBlock().isAir( state, world, newPosition ) )
{
IBlockState state = world.getBlockState( newPosition );
Block block = state.getBlock();
String name = Block.REGISTRY.getNameForObject( block ).toString();
int metadata = block.getMetaFromState( state );
Map<Object, Object> table = new HashMap<>();
Map<String, Object> table = new HashMap<>();
table.put( "name", name );
table.put( "metadata", metadata );
@@ -73,7 +75,15 @@ public class TurtleInspectCommand implements ITurtleCommand
}
table.put( "state", stateTable );
return TurtleCommandResult.success( new Object[]{ table } );
// Fire the event, exiting if it is cancelled
TurtlePlayer turtlePlayer = TurtlePlaceCommand.createPlayer( turtle, oldPosition, direction );
TurtleBlockEvent.Inspect event = new TurtleBlockEvent.Inspect( turtle, turtlePlayer, world, newPosition, state, table );
if( MinecraftForge.EVENT_BUS.post( event ) )
{
return TurtleCommandResult.failure( event.getFailureMessage() );
}
return TurtleCommandResult.success( new Object[] { table } );
}
}
@@ -83,7 +93,7 @@ public class TurtleInspectCommand implements ITurtleCommand
table.put( "name", "minecraft:air" );
table.put( "metadata", 0 );
table.put( "state", new HashMap<>() );
return TurtleCommandResult.success( new Object[]{ table } );
return TurtleCommandResult.success( new Object[] { table } );
}
return TurtleCommandResult.failure( "No block to inspect" );
}

View File

@@ -11,13 +11,15 @@ import dan200.computercraft.api.turtle.ITurtleAccess;
import dan200.computercraft.api.turtle.ITurtleCommand;
import dan200.computercraft.api.turtle.TurtleAnimation;
import dan200.computercraft.api.turtle.TurtleCommandResult;
import dan200.computercraft.api.turtle.event.TurtleBlockEvent;
import dan200.computercraft.shared.util.WorldUtil;
import net.minecraft.block.Block;
import net.minecraft.entity.Entity;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.EnumFacing;
import net.minecraft.world.World;
import net.minecraftforge.common.MinecraftForge;
import javax.annotation.Nonnull;
import java.util.List;
@@ -103,6 +105,12 @@ public class TurtleMoveCommand implements ITurtleCommand
}
}
TurtleBlockEvent.Move moveEvent = new TurtleBlockEvent.Move( turtle, turtlePlayer, oldWorld, newPosition );
if( MinecraftForge.EVENT_BUS.post( moveEvent ) )
{
return TurtleCommandResult.failure( moveEvent.getFailureMessage() );
}
// Check fuel level
if( turtle.isFuelNeeded() && turtle.getFuelLevel() < 1 )
{

View File

@@ -11,6 +11,7 @@ import dan200.computercraft.api.turtle.ITurtleAccess;
import dan200.computercraft.api.turtle.ITurtleCommand;
import dan200.computercraft.api.turtle.TurtleAnimation;
import dan200.computercraft.api.turtle.TurtleCommandResult;
import dan200.computercraft.api.turtle.event.TurtleBlockEvent;
import dan200.computercraft.shared.util.DirectionUtil;
import dan200.computercraft.shared.util.InventoryUtil;
import dan200.computercraft.shared.util.WorldUtil;
@@ -31,6 +32,7 @@ import net.minecraft.util.text.TextComponentString;
import net.minecraft.world.World;
import net.minecraft.world.WorldServer;
import net.minecraftforge.common.ForgeHooks;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.event.entity.player.PlayerInteractEvent;
import net.minecraftforge.fml.common.eventhandler.Event;
import org.apache.commons.lang3.tuple.Pair;
@@ -64,6 +66,16 @@ public class TurtlePlaceCommand implements ITurtleCommand
World world = turtle.getWorld();
BlockPos coordinates = WorldUtil.moveCoords( turtle.getPosition(), direction );
// Create a fake player, and orient it appropriately
BlockPos playerPosition = WorldUtil.moveCoords( turtle.getPosition(), direction );
TurtlePlayer turtlePlayer = createPlayer( turtle, playerPosition, direction );
TurtleBlockEvent.Place place = new TurtleBlockEvent.Place( turtle, turtlePlayer, turtle.getWorld(), coordinates, stack );
if( MinecraftForge.EVENT_BUS.post( place ) )
{
return TurtleCommandResult.failure( place.getFailureMessage() );
}
IBlockState previousState;
if( WorldUtil.isBlockInWorld( world, coordinates ) )
{
@@ -75,8 +87,8 @@ public class TurtlePlaceCommand implements ITurtleCommand
}
// Do the deploying
String[] errorMessage = new String[1];
ItemStack remainder = deploy( stack, turtle, direction, m_extraArguments, errorMessage );
String[] errorMessage = new String[ 1 ];
ItemStack remainder = deploy( stack, turtle, turtlePlayer, direction, m_extraArguments, errorMessage );
if( remainder != stack )
{
// Put the remaining items back
@@ -117,6 +129,11 @@ public class TurtlePlaceCommand implements ITurtleCommand
BlockPos playerPosition = WorldUtil.moveCoords( turtle.getPosition(), direction );
TurtlePlayer turtlePlayer = createPlayer( turtle, playerPosition, direction );
return deploy( stack, turtle, turtlePlayer, direction, extraArguments, o_errorMessage );
}
public static ItemStack deploy( @Nonnull ItemStack stack, ITurtleAccess turtle, TurtlePlayer turtlePlayer, EnumFacing direction, Object[] extraArguments, String[] o_errorMessage )
{
// Deploy on an entity
ItemStack remainder = deployOnEntity( stack, turtle, turtlePlayer, direction, extraArguments, o_errorMessage );
if( remainder != stack )

View File

@@ -10,9 +10,12 @@ import dan200.computercraft.api.turtle.ITurtleAccess;
import dan200.computercraft.api.turtle.ITurtleCommand;
import dan200.computercraft.api.turtle.TurtleAnimation;
import dan200.computercraft.api.turtle.TurtleCommandResult;
import dan200.computercraft.api.turtle.event.TurtleAction;
import dan200.computercraft.api.turtle.event.TurtleActionEvent;
import dan200.computercraft.shared.util.InventoryUtil;
import net.minecraft.item.ItemStack;
import net.minecraft.tileentity.TileEntityFurnace;
import net.minecraftforge.common.MinecraftForge;
import javax.annotation.Nonnull;
@@ -71,6 +74,12 @@ public class TurtleRefuelCommand implements ITurtleCommand
return TurtleCommandResult.failure( "Items not combustible" );
}
TurtleActionEvent event = new TurtleActionEvent( turtle, TurtleAction.REFUEL );
if( MinecraftForge.EVENT_BUS.post( event ) )
{
return TurtleCommandResult.failure( event.getFailureMessage() );
}
if( !testOnly )
{
// Determine fuel to give and replacement item to leave behind

View File

@@ -10,6 +10,7 @@ import dan200.computercraft.api.turtle.ITurtleAccess;
import dan200.computercraft.api.turtle.ITurtleCommand;
import dan200.computercraft.api.turtle.TurtleAnimation;
import dan200.computercraft.api.turtle.TurtleCommandResult;
import dan200.computercraft.api.turtle.event.TurtleInventoryEvent;
import dan200.computercraft.shared.util.InventoryUtil;
import dan200.computercraft.shared.util.WorldUtil;
import net.minecraft.entity.Entity;
@@ -19,6 +20,7 @@ import net.minecraft.util.EnumFacing;
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.items.IItemHandler;
import javax.annotation.Nonnull;
@@ -56,6 +58,15 @@ public class TurtleSuckCommand implements ITurtleCommand
EnumFacing side = direction.getOpposite();
IItemHandler inventory = InventoryUtil.getInventory( world, newPosition, side );
// Fire the event, exiting if it is cancelled.
TurtlePlayer player = TurtlePlaceCommand.createPlayer( turtle, oldPosition, direction );
TurtleInventoryEvent.Suck event = new TurtleInventoryEvent.Suck( turtle, player, world, newPosition, inventory );
if( MinecraftForge.EVENT_BUS.post( event ) )
{
return TurtleCommandResult.failure( event.getFailureMessage() );
}
if( inventory != null )
{
// Take from inventory of thing in front

View File

@@ -10,7 +10,10 @@ import dan200.computercraft.api.turtle.ITurtleAccess;
import dan200.computercraft.api.turtle.ITurtleCommand;
import dan200.computercraft.api.turtle.TurtleAnimation;
import dan200.computercraft.api.turtle.TurtleCommandResult;
import dan200.computercraft.api.turtle.event.TurtleAction;
import dan200.computercraft.api.turtle.event.TurtleActionEvent;
import dan200.computercraft.shared.util.DirectionUtil;
import net.minecraftforge.common.MinecraftForge;
import javax.annotation.Nonnull;
@@ -27,6 +30,12 @@ public class TurtleTurnCommand implements ITurtleCommand
@Override
public TurtleCommandResult execute( @Nonnull ITurtleAccess turtle )
{
TurtleActionEvent event = new TurtleActionEvent( turtle, TurtleAction.TURN );
if( MinecraftForge.EVENT_BUS.post( event ) )
{
return TurtleCommandResult.failure( event.getFailureMessage() );
}
switch( m_direction )
{
case Left:

View File

@@ -9,6 +9,8 @@ package dan200.computercraft.shared.turtle.upgrades;
import dan200.computercraft.ComputerCraft;
import dan200.computercraft.api.peripheral.IPeripheral;
import dan200.computercraft.api.turtle.*;
import dan200.computercraft.api.turtle.event.TurtleAttackEvent;
import dan200.computercraft.api.turtle.event.TurtleBlockEvent;
import dan200.computercraft.shared.turtle.core.TurtleBrain;
import dan200.computercraft.shared.turtle.core.TurtlePlaceCommand;
import dan200.computercraft.shared.turtle.core.TurtlePlayer;
@@ -128,11 +130,11 @@ public class TurtleTool implements ITurtleUpgrade
{
case Attack:
{
return attack( turtle, direction );
return attack( turtle, direction, side );
}
case Dig:
{
return dig( turtle, direction );
return dig( turtle, direction, side );
}
default:
{
@@ -161,7 +163,7 @@ public class TurtleTool implements ITurtleUpgrade
return 3.0f;
}
private TurtleCommandResult attack( final ITurtleAccess turtle, EnumFacing direction )
private TurtleCommandResult attack( final ITurtleAccess turtle, EnumFacing direction, TurtleSide side )
{
// Create a fake player, and orient it appropriately
final World world = turtle.getWorld();
@@ -178,8 +180,21 @@ public class TurtleTool implements ITurtleUpgrade
ItemStack stackCopy = m_item.copy();
turtlePlayer.loadInventory( stackCopy );
// Start claiming entity drops
Entity hitEntity = hit.getKey();
// Fire several events to ensure we have permissions.
if( MinecraftForge.EVENT_BUS.post( new AttackEntityEvent( turtlePlayer, hitEntity ) ) || !hitEntity.canBeAttackedWithItem() )
{
return TurtleCommandResult.failure( "Nothing to attack here" );
}
TurtleAttackEvent attackEvent = new TurtleAttackEvent( turtle, turtlePlayer, hitEntity, this, side );
if( MinecraftForge.EVENT_BUS.post( attackEvent ) )
{
return TurtleCommandResult.failure( attackEvent.getFailureMessage() );
}
// Start claiming entity drops
ComputerCraft.setEntityDropConsumer( hitEntity, ( entity, drop ) ->
{
ItemStack remainder = InventoryUtil.storeItems( drop, turtle.getItemHandler(), turtle.getSelectedSlot() );
@@ -191,8 +206,7 @@ public class TurtleTool implements ITurtleUpgrade
// Attack the entity
boolean attacked = false;
if( hitEntity.canBeAttackedWithItem() && !hitEntity.hitByEntity( turtlePlayer )
&& !MinecraftForge.EVENT_BUS.post( new AttackEntityEvent( turtlePlayer, hitEntity ) ) )
if( !hitEntity.hitByEntity( turtlePlayer ) )
{
float damage = (float)turtlePlayer.getEntityAttribute( SharedMonsterAttributes.ATTACK_DAMAGE ).getAttributeValue();
damage *= getDamageMultiplier();
@@ -233,7 +247,7 @@ public class TurtleTool implements ITurtleUpgrade
return TurtleCommandResult.failure( "Nothing to attack here" );
}
private TurtleCommandResult dig( ITurtleAccess turtle, EnumFacing direction )
private TurtleCommandResult dig( ITurtleAccess turtle, EnumFacing direction, TurtleSide side )
{
// Get ready to dig
World world = turtle.getWorld();
@@ -266,6 +280,13 @@ public class TurtleTool implements ITurtleUpgrade
return TurtleCommandResult.failure( "Unbreakable block detected" );
}
// Fire the dig event, checking whether it was cancelled.
TurtleBlockEvent.Dig digEvent = new TurtleBlockEvent.Dig( turtle, turtlePlayer, world, newPosition, world.getBlockState( newPosition ), this, side );
if( MinecraftForge.EVENT_BUS.post( digEvent ) )
{
return TurtleCommandResult.failure( digEvent.getFailureMessage() );
}
// Consume the items the block drops
if( canHarvestBlock( world, newPosition ) )
{