1
0
mirror of https://github.com/SquidDev-CC/CC-Tweaked synced 2024-06-23 13:43:22 +00:00

Convert turtle refuelling into an event

This should allow us (or other mods) to register custom refuel handlers
should they so wish.
This commit is contained in:
SquidDev 2019-03-27 20:38:39 +00:00
parent c4b371b124
commit 6ed03e1fcd
3 changed files with 164 additions and 69 deletions

View File

@ -0,0 +1,90 @@
/*
* This file is part of ComputerCraft - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2019. Do not distribute without permission.
* Send enquiries to dratcliffe@gmail.com
*/
package dan200.computercraft.api.turtle.event;
import dan200.computercraft.api.turtle.ITurtleAccess;
import net.minecraft.item.ItemStack;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.Objects;
/**
* Fired when a turtle attempts to refuel from an item.
*
* One may use {@link #setCanceled(boolean, String)} to prevent refueling from this specific item. Additionally, you
* may use {@link #setHandler(Handler)} to register a custom fuel provider.
*/
public class TurtleRefuelEvent extends TurtleActionEvent
{
private final ItemStack stack;
private Handler handler;
public TurtleRefuelEvent( @Nonnull ITurtleAccess turtle, @Nonnull ItemStack stack )
{
super( turtle, TurtleAction.REFUEL );
Objects.requireNonNull( turtle, "turtle cannot be null" );
this.stack = stack;
}
/**
* Get the stack we are attempting to refuel from.
*
* Do not modify the returned stack - all modifications should be done within the {@link Handler}.
*
* @return The stack to refuel from.
*/
public ItemStack getStack()
{
return stack;
}
/**
* Get the refuel handler for this stack.
*
* @return The refuel handler, or {@code null} if none has currently been set.
* @see #setHandler(Handler)
*/
@Nullable
public Handler getHandler()
{
return handler;
}
/**
* Set the refuel handler for this stack.
*
* You should call this if you can actually refuel from this item, and ideally only if there are no existing
* handlers.
*
* @param handler The new refuel handler.
* @see #getHandler()
*/
public void setHandler( @Nullable Handler handler )
{
this.handler = handler;
}
/**
* Handles refuelling a turtle from a specific item.
*/
public interface Handler
{
/**
* Refuel a turtle using an item.
*
* @param turtle The turtle to refuel.
* @param stack The stack to refuel with.
* @param slot The slot the stack resides within. This may be used to modify the inventory afterwards.
* @param limit The maximum number of refuel operations to perform. This will often correspond to the number of
* items to consume.
* @return The amount of fuel gained.
*/
int refuel( @Nonnull ITurtleAccess turtle, @Nonnull ItemStack stack, int slot, int limit );
}
}

View File

@ -0,0 +1,61 @@
/*
* This file is part of ComputerCraft - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2019. Do not distribute without permission.
* Send enquiries to dratcliffe@gmail.com
*/
package dan200.computercraft.shared.turtle;
import dan200.computercraft.ComputerCraft;
import dan200.computercraft.api.turtle.ITurtleAccess;
import dan200.computercraft.api.turtle.event.TurtleRefuelEvent;
import dan200.computercraft.shared.util.InventoryUtil;
import dan200.computercraft.shared.util.WorldUtil;
import net.minecraft.item.ItemStack;
import net.minecraft.tileentity.TileEntityFurnace;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
import javax.annotation.Nonnull;
@Mod.EventBusSubscriber( modid = ComputerCraft.MOD_ID )
public final class FurnaceRefuelHandler implements TurtleRefuelEvent.Handler
{
private static final FurnaceRefuelHandler INSTANCE = new FurnaceRefuelHandler();
private FurnaceRefuelHandler()
{
}
@Override
public int refuel( @Nonnull ITurtleAccess turtle, @Nonnull ItemStack currentStack, int slot, int limit )
{
ItemStack stack = turtle.getItemHandler().extractItem( slot, limit, false );
int fuelToGive = getFuelPerItem( stack ) * stack.getCount();
// Store the replacement item in the inventory
ItemStack replacementStack = stack.getItem().getContainerItem( stack );
if( !replacementStack.isEmpty() )
{
ItemStack remainder = InventoryUtil.storeItems( replacementStack, turtle.getItemHandler(), turtle.getSelectedSlot() );
if( !remainder.isEmpty() )
{
WorldUtil.dropItemStack( remainder, turtle.getWorld(), turtle.getPosition(), turtle.getDirection().getOpposite() );
}
}
return fuelToGive;
}
private static int getFuelPerItem( @Nonnull ItemStack stack )
{
return (TileEntityFurnace.getItemBurnTime( stack ) * 5) / 100;
}
@SubscribeEvent
public static void onTurtleRefuel( TurtleRefuelEvent event )
{
if( event.getHandler() == null && getFuelPerItem( event.getStack() ) > 0 ) event.setHandler( INSTANCE );
}
}

View File

@ -10,92 +10,36 @@
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 dan200.computercraft.api.turtle.event.TurtleRefuelEvent;
import net.minecraft.item.ItemStack;
import net.minecraft.tileentity.TileEntityFurnace;
import net.minecraftforge.common.MinecraftForge;
import javax.annotation.Nonnull;
public class TurtleRefuelCommand implements ITurtleCommand
{
private final int m_limit;
private final int limit;
public TurtleRefuelCommand( int limit )
{
m_limit = limit;
this.limit = limit;
}
@Nonnull
@Override
public TurtleCommandResult execute( @Nonnull ITurtleAccess turtle )
{
if( m_limit == 0 )
int slot = turtle.getSelectedSlot();
ItemStack stack = turtle.getInventory().getStackInSlot( slot );
if( stack.isEmpty() ) return TurtleCommandResult.failure( "No items to combust" );
TurtleRefuelEvent event = new TurtleRefuelEvent( turtle, stack );
if( MinecraftForge.EVENT_BUS.post( event ) ) return TurtleCommandResult.failure( event.getFailureMessage() );
if( event.getHandler() == null ) return TurtleCommandResult.failure( "Items not combustible" );
if( limit != 0 )
{
// If limit is zero, just check the item is combustible
ItemStack dummyStack = turtle.getInventory().getStackInSlot( turtle.getSelectedSlot() );
if( !dummyStack.isEmpty() )
{
return refuel( turtle, dummyStack, true );
}
}
else
{
// Otherwise, refuel for real
// Remove items from inventory
ItemStack stack = InventoryUtil.takeItems( m_limit, turtle.getItemHandler(), turtle.getSelectedSlot(), 1, turtle.getSelectedSlot() );
if( !stack.isEmpty() )
{
TurtleCommandResult result = refuel( turtle, stack, false );
if( !result.isSuccess() )
{
// If the items weren't burnt, put them back
InventoryUtil.storeItems( stack, turtle.getItemHandler(), turtle.getSelectedSlot() );
}
return result;
}
}
return TurtleCommandResult.failure( "No items to combust" );
}
private int getFuelPerItem( @Nonnull ItemStack stack )
{
return (TileEntityFurnace.getItemBurnTime( stack ) * 5) / 100;
}
private TurtleCommandResult refuel( ITurtleAccess turtle, @Nonnull ItemStack stack, boolean testOnly )
{
// Check if item is fuel
int fuelPerItem = getFuelPerItem( stack );
if( fuelPerItem <= 0 )
{
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
int fuelToGive = fuelPerItem * stack.getCount();
ItemStack replacementStack = stack.getItem().getContainerItem( stack );
// Update fuel level
turtle.addFuel( fuelToGive );
// Store the replacement item in the inventory
if( !replacementStack.isEmpty() )
{
InventoryUtil.storeItems( replacementStack, turtle.getItemHandler(), turtle.getSelectedSlot() );
}
// Animate
turtle.addFuel( event.getHandler().refuel( turtle, stack, slot, limit ) );
turtle.playAnimation( TurtleAnimation.Wait );
}