1
0
mirror of https://github.com/SquidDev-CC/CC-Tweaked synced 2025-07-05 03:22:53 +00:00

Fix a whole bunch of bugs

This commit is contained in:
SquidDev 2019-04-25 11:18:02 +01:00
parent 536c2d9b2d
commit e8d7e6a562
18 changed files with 233 additions and 101 deletions

View File

@ -189,7 +189,7 @@ processResources {
inputs.property "commithash", hash inputs.property "commithash", hash
from(sourceSets.main.resources.srcDirs) { from(sourceSets.main.resources.srcDirs) {
include 'fabric.mods.json' include 'fabric.mod.json'
include 'data/computercraft/lua/rom/help/credits.txt' include 'data/computercraft/lua/rom/help/credits.txt'
expand 'version': mod_version, expand 'version': mod_version,
@ -198,7 +198,7 @@ processResources {
} }
from(sourceSets.main.resources.srcDirs) { from(sourceSets.main.resources.srcDirs) {
exclude 'fabric.mods.json' exclude 'fabric.mod.json'
exclude 'data/computercraft/lua/rom/help/credits.txt' exclude 'data/computercraft/lua/rom/help/credits.txt'
} }
} }
@ -250,7 +250,7 @@ curseforge {
project { project {
id = '282001' id = '282001'
addGameVersion '1.14-Snapshot' addGameVersion '1.14-Snapshot'
releaseType = 'alpha' releaseType = 'beta'
changelog = "Release notes can be found on the GitHub repository (https://github.com/SquidDev-CC/CC-Tweaked/releases/tag/v${mc_version}-${mod_version})." changelog = "Release notes can be found on the GitHub repository (https://github.com/SquidDev-CC/CC-Tweaked/releases/tag/v${mc_version}-${mod_version})."
} }
} }

View File

@ -1,5 +1,5 @@
# Mod properties # Mod properties
mod_version=1.82.3 mod_version=1.82.4
# Minecraft properties # Minecraft properties
mc_version=1.14 mc_version=1.14

View File

@ -12,14 +12,19 @@ import dan200.computercraft.shared.media.items.ItemDisk;
import dan200.computercraft.shared.pocket.items.ItemPocketComputer; import dan200.computercraft.shared.pocket.items.ItemPocketComputer;
import dan200.computercraft.shared.util.Colour; import dan200.computercraft.shared.util.Colour;
import net.fabricmc.fabric.api.client.render.ColorProviderRegistry; import net.fabricmc.fabric.api.client.render.ColorProviderRegistry;
import net.fabricmc.fabric.api.event.client.ClientSpriteRegistryCallback;
import net.minecraft.client.MinecraftClient; import net.minecraft.client.MinecraftClient;
import net.minecraft.client.render.model.BakedModel; import net.minecraft.client.render.model.BakedModel;
import net.minecraft.client.render.model.ModelLoader; import net.minecraft.client.render.model.ModelLoader;
import net.minecraft.client.render.model.ModelRotation; import net.minecraft.client.render.model.ModelRotation;
import net.minecraft.client.render.model.UnbakedModel; import net.minecraft.client.render.model.UnbakedModel;
import net.minecraft.client.texture.SpriteAtlasTexture; import net.minecraft.client.texture.SpriteAtlasTexture;
import net.minecraft.client.util.ModelIdentifier;
import net.minecraft.resource.ResourceManager;
import net.minecraft.util.Identifier;
import java.util.HashSet; import java.util.HashSet;
import java.util.function.Consumer;
/** /**
* Registers textures and models for items. * Registers textures and models for items.
@ -57,56 +62,22 @@ public final class ClientRegistry
private ClientRegistry() {} private ClientRegistry() {}
/* public static void onTextureStitchEvent( SpriteAtlasTexture atlasTexture, ClientSpriteRegistryCallback.Registry registry )
TODO: @SubscribeEvent
public static void registerModels( ModelRegistryEvent event )
{ {
ModelLoaderRegistry.registerLoader( TurtleModelLoader.INSTANCE );
}
TODO: @SubscribeEvent
public static void onTextureStitchEvent( TextureStitchEvent.Pre event )
{
ResourceManager manager = MinecraftClient.getInstance().getResourceManager();
for( String extra : EXTRA_TEXTURES ) for( String extra : EXTRA_TEXTURES )
{ {
event.getMap().registerSprite( manager, new Identifier( ComputerCraft.MOD_ID, extra ) ); registry.register( new Identifier( ComputerCraft.MOD_ID, extra ) );
} }
} }
TODO: @SubscribeEvent public static void onModelBakeEvent( ResourceManager manager, Consumer<ModelIdentifier> out )
public static void onModelBakeEvent( ModelBakeEvent event )
{ {
// Load all extra models
ModelLoader loader = event.getModelLoader();
Map<ModelIdentifier, BakedModel> registry = event.getModelRegistry();
for( String model : EXTRA_MODELS ) for( String model : EXTRA_MODELS )
{ {
BakedModel bakedModel = bake( loader, loader.getOrLoadModel( new Identifier( ComputerCraft.MOD_ID, "item/" + model ) ) ); out.accept( new ModelIdentifier( new Identifier( ComputerCraft.MOD_ID, model ), "inventory" ) );
if( bakedModel != null )
{
registry.put(
new ModelIdentifier( new Identifier( ComputerCraft.MOD_ID, model ), "inventory" ),
bakedModel
);
} }
} }
// And load the custom turtle models in too.
registry.put(
new ModelIdentifier( new Identifier( ComputerCraft.MOD_ID, "turtle_normal" ), "inventory" ),
bake( loader, TurtleModelLoader.INSTANCE.loadModel( new Identifier( ComputerCraft.MOD_ID, "item/turtle_normal" ) ) )
);
registry.put(
new ModelIdentifier( new Identifier( ComputerCraft.MOD_ID, "turtle_advanced" ), "inventory" ),
bake( loader, TurtleModelLoader.INSTANCE.loadModel( new Identifier( ComputerCraft.MOD_ID, "item/turtle_advanced" ) ) )
);
}
*/
public static void onItemColours() public static void onItemColours()
{ {
ColorProviderRegistry.ITEM.register( ColorProviderRegistry.ITEM.register(

View File

@ -19,6 +19,7 @@ import net.minecraft.container.Container;
import net.minecraft.entity.player.PlayerInventory; import net.minecraft.entity.player.PlayerInventory;
import net.minecraft.text.StringTextComponent; import net.minecraft.text.StringTextComponent;
import net.minecraft.util.Identifier; import net.minecraft.util.Identifier;
import org.lwjgl.glfw.GLFW;
public class GuiComputer<T extends Container> extends ContainerScreen<T> public class GuiComputer<T extends Container> extends ContainerScreen<T>
{ {
@ -141,9 +142,18 @@ public class GuiComputer<T extends Container> extends ContainerScreen<T>
drawMouseoverTooltip( mouseX, mouseY ); drawMouseoverTooltip( mouseX, mouseY );
} }
@Override
public boolean keyPressed( int key, int scancode, int modifiers )
{
// When pressing tab, send it to the computer first
return (key == GLFW.GLFW_KEY_TAB && getFocused() == terminalWrapper && terminalWrapper.keyPressed( key, scancode, modifiers ))
|| super.keyPressed( key, scancode, modifiers );
}
@Override @Override
public boolean mouseDragged( double x, double y, int button, double deltaX, double deltaY ) public boolean mouseDragged( double x, double y, int button, double deltaX, double deltaY )
{ {
// Make sure drag events are propagated to children
return (getFocused() != null && getFocused().mouseDragged( x, y, button, deltaX, deltaY )) return (getFocused() != null && getFocused().mouseDragged( x, y, button, deltaX, deltaY ))
|| super.mouseDragged( x, y, button, deltaX, deltaY ); || super.mouseDragged( x, y, button, deltaX, deltaY );
} }
@ -151,6 +161,7 @@ public class GuiComputer<T extends Container> extends ContainerScreen<T>
@Override @Override
public boolean mouseReleased( double x, double y, int button ) public boolean mouseReleased( double x, double y, int button )
{ {
// Make sure release events are propagated to children
return (getFocused() != null && getFocused().mouseReleased( x, y, button )) return (getFocused() != null && getFocused().mouseReleased( x, y, button ))
|| super.mouseReleased( x, y, button ); || super.mouseReleased( x, y, button );
} }

View File

@ -17,6 +17,7 @@ import dan200.computercraft.shared.turtle.inventory.ContainerTurtle;
import net.minecraft.client.gui.ContainerScreen; import net.minecraft.client.gui.ContainerScreen;
import net.minecraft.entity.player.PlayerInventory; import net.minecraft.entity.player.PlayerInventory;
import net.minecraft.util.Identifier; import net.minecraft.util.Identifier;
import org.lwjgl.glfw.GLFW;
public class GuiTurtle extends ContainerScreen<ContainerTurtle> public class GuiTurtle extends ContainerScreen<ContainerTurtle>
{ {
@ -116,4 +117,25 @@ public class GuiTurtle extends ContainerScreen<ContainerTurtle>
super.render( mouseX, mouseY, partialTicks ); super.render( mouseX, mouseY, partialTicks );
drawMouseoverTooltip( mouseX, mouseY ); drawMouseoverTooltip( mouseX, mouseY );
} }
@Override
public boolean keyPressed( int key, int scancode, int modifiers )
{
return (key == GLFW.GLFW_KEY_TAB && getFocused() == terminalWrapper && terminalWrapper.keyPressed( key, scancode, modifiers ))
|| super.keyPressed( key, scancode, modifiers );
}
@Override
public boolean mouseDragged( double x, double y, int button, double deltaX, double deltaY )
{
return (getFocused() != null && getFocused().mouseDragged( x, y, button, deltaX, deltaY ))
|| super.mouseDragged( x, y, button, deltaX, deltaY );
}
@Override
public boolean mouseReleased( double x, double y, int button )
{
return (getFocused() != null && getFocused().mouseReleased( x, y, button ))
|| super.mouseReleased( x, y, button );
}
} }

View File

@ -12,6 +12,7 @@ import dan200.computercraft.client.gui.*;
import dan200.computercraft.client.render.TileEntityCableRenderer; import dan200.computercraft.client.render.TileEntityCableRenderer;
import dan200.computercraft.client.render.TileEntityMonitorRenderer; import dan200.computercraft.client.render.TileEntityMonitorRenderer;
import dan200.computercraft.client.render.TileEntityTurtleRenderer; import dan200.computercraft.client.render.TileEntityTurtleRenderer;
import dan200.computercraft.client.render.TurtleModelLoader;
import dan200.computercraft.shared.computer.blocks.TileComputer; import dan200.computercraft.shared.computer.blocks.TileComputer;
import dan200.computercraft.shared.computer.core.ClientComputer; import dan200.computercraft.shared.computer.core.ClientComputer;
import dan200.computercraft.shared.computer.inventory.ContainerViewComputer; import dan200.computercraft.shared.computer.inventory.ContainerViewComputer;
@ -20,7 +21,9 @@ import dan200.computercraft.shared.peripheral.modem.wired.TileCable;
import dan200.computercraft.shared.peripheral.monitor.TileMonitor; import dan200.computercraft.shared.peripheral.monitor.TileMonitor;
import dan200.computercraft.shared.turtle.blocks.TileTurtle; import dan200.computercraft.shared.turtle.blocks.TileTurtle;
import dan200.computercraft.shared.turtle.inventory.ContainerTurtle; import dan200.computercraft.shared.turtle.inventory.ContainerTurtle;
import net.fabricmc.fabric.api.client.model.ModelLoadingRegistry;
import net.fabricmc.fabric.api.client.render.BlockEntityRendererRegistry; import net.fabricmc.fabric.api.client.render.BlockEntityRendererRegistry;
import net.fabricmc.fabric.api.event.client.ClientSpriteRegistryCallback;
public final class ComputerCraftProxyClient public final class ComputerCraftProxyClient
{ {
@ -34,6 +37,11 @@ public final class ComputerCraftProxyClient
BlockEntityRendererRegistry.INSTANCE.register( TileTurtle.class, new TileEntityTurtleRenderer() ); BlockEntityRendererRegistry.INSTANCE.register( TileTurtle.class, new TileEntityTurtleRenderer() );
ClientRegistry.onItemColours(); ClientRegistry.onItemColours();
ClientSpriteRegistryCallback.registerBlockAtlas( ClientRegistry::onTextureStitchEvent );
ModelLoadingRegistry.INSTANCE.registerAppender( ClientRegistry::onModelBakeEvent );
ModelLoadingRegistry.INSTANCE.registerResourceProvider( loader -> ( name, context ) ->
TurtleModelLoader.INSTANCE.accepts( name ) ? TurtleModelLoader.INSTANCE.loadModel( name ) : null
);
} }
private static void registerContainers() private static void registerContainers()

View File

@ -0,0 +1,34 @@
/*
* 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.mixin;
import dan200.computercraft.shared.util.DropConsumer;
import net.minecraft.block.Block;
import net.minecraft.item.ItemStack;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
/**
* @see Block#dropStack(World, BlockPos, ItemStack)
*/
@Mixin( Block.class )
public class MixinBlock
{
@Inject(
method = "dropStack",
at = @At( value = "INVOKE", target = "Lnet/minecraft/world/World;spawnEntity(Lnet/minecraft/entity/Entity;)Z" ),
cancellable = true
)
private static void dropStack( World world, BlockPos pos, ItemStack stack, CallbackInfo callbackInfo )
{
if( DropConsumer.onHarvestDrops( world, pos, stack ) ) callbackInfo.cancel();
}
}

View File

@ -0,0 +1,33 @@
/*
* 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.mixin;
import dan200.computercraft.shared.util.DropConsumer;
import net.minecraft.entity.Entity;
import net.minecraft.entity.ItemEntity;
import net.minecraft.item.ItemStack;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
/**
* @see Entity#dropStack(ItemStack, float)
*/
@Mixin( Entity.class )
public class MixinEntity
{
@Inject(
method = "dropStack(Lnet/minecraft/item/ItemStack;F)Lnet/minecraft/entity/ItemEntity;",
at = @At( value = "INVOKE", target = "Lnet/minecraft/world/World;spawnEntity(Lnet/minecraft/entity/Entity;)Z" ),
cancellable = true
)
public void dropStack( ItemStack stack, float height, CallbackInfoReturnable<ItemEntity> callbackInfo )
{
if( DropConsumer.onEntityLivingDrops( (Entity) (Object) this, stack ) ) callbackInfo.setReturnValue( null );
}
}

View File

@ -0,0 +1,28 @@
/*
* 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.mixin;
import dan200.computercraft.shared.util.DropConsumer;
import net.minecraft.entity.Entity;
import net.minecraft.server.world.ServerWorld;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
/**
* @see ServerWorld#spawnEntity(Entity)
*/
@Mixin( ServerWorld.class )
public class MixinServerWorld
{
@Inject( method = "spawnEntity", at = @At( "HEAD" ), cancellable = true )
public void spawnEntity( Entity entity, CallbackInfoReturnable<Boolean> callbackInfo )
{
if( DropConsumer.onEntitySpawn( entity ) ) callbackInfo.setReturnValue( false );
}
}

View File

@ -286,9 +286,8 @@ public class TurtlePlaceCommand implements ITurtleCommand
private static boolean canDeployOnBlock( @Nonnull ItemPlacementContext context, ITurtleAccess turtle, TurtlePlayer player, BlockPos position, Direction side, boolean allowReplaceable, String[] outErrorMessage ) private static boolean canDeployOnBlock( @Nonnull ItemPlacementContext context, ITurtleAccess turtle, TurtlePlayer player, BlockPos position, Direction side, boolean allowReplaceable, String[] outErrorMessage )
{ {
World world = turtle.getWorld(); World world = turtle.getWorld();
if( World.isValid( position ) && if( !World.isValid( position ) || world.isAir( position ) ||
!world.isAir( position ) && (context.getItemStack().getItem() instanceof BlockItem && WorldUtil.isLiquidBlock( world, position )) )
!(context.getItemStack().getItem() instanceof BlockItem && WorldUtil.isLiquidBlock( world, position )) )
{ {
return false; return false;
} }

View File

@ -21,6 +21,7 @@ import dan200.computercraft.shared.util.ItemStorage;
import dan200.computercraft.shared.util.WorldUtil; import dan200.computercraft.shared.util.WorldUtil;
import net.fabricmc.api.EnvType; import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment; import net.fabricmc.api.Environment;
import net.fabricmc.fabric.api.event.player.AttackEntityCallback;
import net.minecraft.block.Block; import net.minecraft.block.Block;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks; import net.minecraft.block.Blocks;
@ -33,6 +34,8 @@ import net.minecraft.entity.damage.DamageSource;
import net.minecraft.entity.decoration.ArmorStandEntity; import net.minecraft.entity.decoration.ArmorStandEntity;
import net.minecraft.item.Item; import net.minecraft.item.Item;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
import net.minecraft.util.ActionResult;
import net.minecraft.util.Hand;
import net.minecraft.util.Identifier; import net.minecraft.util.Identifier;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction; import net.minecraft.util.math.Direction;
@ -99,8 +102,7 @@ public class TurtleTool extends AbstractTurtleUpgrade
Block block = state.getBlock(); Block block = state.getBlock();
return !state.isAir() return !state.isAir()
&& block != Blocks.BEDROCK && block != Blocks.BEDROCK
&& state.getHardness( world, pos ) > 0 && state.calcBlockBreakingDelta( player, world, pos ) > 0;
/*&& block.canEntityDestroy( state, world, pos, player )*/;
} }
protected float getDamageMultiplier() protected float getDamageMultiplier()
@ -128,12 +130,11 @@ public class TurtleTool extends AbstractTurtleUpgrade
Entity hitEntity = hit.getKey(); Entity hitEntity = hit.getKey();
// Fire several events to ensure we have permissions. // Fire several events to ensure we have permissions.
/* if( AttackEntityCallback.EVENT.invoker().interact( turtlePlayer, world, Hand.MAIN, hitEntity, null ) == ActionResult.FAIL
if( MinecraftForge.EVENT_BUS.post( new AttackEntityEvent( turtlePlayer, hitEntity ) ) || !hitEntity.canBeAttackedWithItem() ) || !hitEntity.canPlayerAttack() )
{ {
return TurtleCommandResult.failure( "Nothing to attack here" ); return TurtleCommandResult.failure( "Nothing to attack here" );
} }
*/
TurtleAttackEvent attackEvent = new TurtleAttackEvent( turtle, turtlePlayer, hitEntity, this, side ); TurtleAttackEvent attackEvent = new TurtleAttackEvent( turtle, turtlePlayer, hitEntity, this, side );
if( TurtleEvent.post( attackEvent ) ) if( TurtleEvent.post( attackEvent ) )

View File

@ -7,6 +7,7 @@
package dan200.computercraft.shared.util; package dan200.computercraft.shared.util;
import net.minecraft.entity.Entity; import net.minecraft.entity.Entity;
import net.minecraft.entity.ItemEntity;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.BoundingBox; import net.minecraft.util.math.BoundingBox;
@ -87,44 +88,40 @@ public final class DropConsumer
if( !remaining.isEmpty() ) remainingDrops.add( remaining ); if( !remaining.isEmpty() ) remainingDrops.add( remaining );
} }
/* public static boolean onEntityLivingDrops( Entity entity, ItemStack stack )
@SubscribeEvent( priority = EventPriority.LOWEST )
public static void onEntityLivingDrops( LivingDropsEvent event )
{ {
// Capture any mob drops for the current entity // Capture any mob drops for the current entity
if( dropEntity != null && event.getEntity() == dropEntity.get() ) if( dropEntity != null && entity == dropEntity.get() )
{ {
Collection<EntityItem> drops = event.getDrops(); handleDrops( stack );
for( EntityItem entityItem : drops ) handleDrops( entityItem.getItem() ); return true;
drops.clear();
}
} }
@SubscribeEvent( priority = EventPriority.LOWEST ) return false;
public static void onHarvestDrops( BlockEvent.HarvestDropsEvent event ) }
public static boolean onHarvestDrops( World world, BlockPos pos, ItemStack stack )
{ {
// Capture block drops for the current entity // Capture block drops for the current entity
if( dropWorld != null && dropWorld.get() == event.getWorld() if( dropWorld != null && dropWorld.get() == world && dropPos != null && dropPos.equals( pos ) )
&& dropPos != null && dropPos.equals( event.getPos() ) )
{ {
for( ItemStack item : event.getDrops() ) handleDrops( stack );
{ return true;
if( event.getWorld().getRandom().nextFloat() < event.getDropChance() ) handleDrops( item );
}
event.getDrops().clear();
}
} }
@SubscribeEvent( priority = EventPriority.LOWEST ) return false;
public static void onEntitySpawn( EntityJoinWorldEvent event ) }
public static boolean onEntitySpawn( Entity entity )
{ {
// Capture any nearby item spawns // Capture any nearby item spawns
if( dropWorld != null && dropWorld.get() == event.getWorld() && event.getEntity() instanceof EntityItem if( dropWorld != null && dropWorld.get() == entity.getEntityWorld() && entity instanceof ItemEntity
&& dropBounds.contains( event.getEntity().getPositionVector() ) ) && dropBounds.contains( entity.getPos() ) )
{ {
handleDrops( ((EntityItem) event.getEntity()).getItem() ); handleDrops( ((ItemEntity) entity).getStack() );
event.setCanceled( true ); return true;
} }
return false;
} }
*/
} }

View File

@ -6,6 +6,7 @@
package dan200.computercraft.shared.util; package dan200.computercraft.shared.util;
import dan200.computercraft.ComputerCraft;
import net.minecraft.inventory.Inventory; import net.minecraft.inventory.Inventory;
import net.minecraft.inventory.SidedInventory; import net.minecraft.inventory.SidedInventory;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
@ -58,8 +59,8 @@ public interface ItemStorage
} }
@Override @Override
public @Nonnull @Nonnull
ItemStack take( int slot, int limit, @Nonnull ItemStack filter, boolean simulate ) public ItemStack take( int slot, int limit, @Nonnull ItemStack filter, boolean simulate )
{ {
ItemStack existing = inventory.getInvStack( slot ); ItemStack existing = inventory.getInvStack( slot );
if( existing.isEmpty() || !canExtract( slot, existing ) if( existing.isEmpty() || !canExtract( slot, existing )
@ -88,8 +89,8 @@ public interface ItemStorage
} }
@Override @Override
public @Nonnull @Nonnull
ItemStack store( int slot, @Nonnull ItemStack stack, boolean simulate ) public ItemStack store( int slot, @Nonnull ItemStack stack, boolean simulate )
{ {
if( stack.isEmpty() || !inventory.isValidInvStack( slot, stack ) ) return stack; if( stack.isEmpty() || !inventory.isValidInvStack( slot, stack ) ) return stack;
@ -97,7 +98,7 @@ public interface ItemStorage
if( existing.isEmpty() ) if( existing.isEmpty() )
{ {
int limit = Math.min( stack.getMaxAmount(), inventory.getInvMaxStackAmount() ); int limit = Math.min( stack.getMaxAmount(), inventory.getInvMaxStackAmount() );
if( limit <= 0 ) return ItemStack.EMPTY; if( limit <= 0 ) return stack;
if( stack.getAmount() < limit ) if( stack.getAmount() < limit )
{ {
@ -114,8 +115,8 @@ public interface ItemStorage
} }
else if( areStackable( stack, existing ) ) else if( areStackable( stack, existing ) )
{ {
int limit = Math.min( existing.getMaxAmount(), inventory.getInvMaxStackAmount() ) - stack.getAmount(); int limit = Math.min( existing.getMaxAmount(), inventory.getInvMaxStackAmount() ) - existing.getAmount();
if( limit <= 0 ) return ItemStack.EMPTY; if( limit <= 0 ) return stack;
if( stack.getAmount() < limit ) if( stack.getAmount() < limit )
{ {
@ -140,7 +141,7 @@ public interface ItemStorage
} }
else else
{ {
return ItemStack.EMPTY; return stack;
} }
} }
} }
@ -169,24 +170,23 @@ public interface ItemStorage
return super.canExtract( slot, stack ) && inventory.canExtractInvStack( slot, stack, facing ); return super.canExtract( slot, stack ) && inventory.canExtractInvStack( slot, stack, facing );
} }
@Nonnull
@Override @Override
public @Nonnull public ItemStack take( int slot, int limit, @Nonnull ItemStack filter, boolean simulate )
ItemStack take( int slot, int limit, @Nonnull ItemStack filter, boolean simulate )
{ {
int[] slots = inventory.getInvAvailableSlots( facing ); int[] slots = inventory.getInvAvailableSlots( facing );
return slot >= 0 && slot < slots.length ? super.take( slots[slot], limit, filter, simulate ) : ItemStack.EMPTY; return slot >= 0 && slot < slots.length ? super.take( slots[slot], limit, filter, simulate ) : ItemStack.EMPTY;
} }
@Nonnull
@Override @Override
public @Nonnull public ItemStack store( int slot, @Nonnull ItemStack stack, boolean simulate )
ItemStack store( int slot, @Nonnull ItemStack stack, boolean simulate )
{ {
int[] slots = inventory.getInvAvailableSlots( facing ); int[] slots = inventory.getInvAvailableSlots( facing );
if( slot < 0 || slot >= slots.length ) return ItemStack.EMPTY; if( slot < 0 || slot >= slots.length ) return stack;
int mappedSlot = slots[slot]; int mappedSlot = slots[slot];
if( !inventory.canInsertInvStack( slot, stack, facing ) ) return ItemStack.EMPTY; if( !inventory.canInsertInvStack( slot, stack, facing ) ) return stack;
return super.store( mappedSlot, stack, simulate ); return super.store( mappedSlot, stack, simulate );
} }
} }
@ -197,7 +197,7 @@ public interface ItemStorage
private final int start; private final int start;
private final int size; private final int size;
public View( ItemStorage parent, int start, int size ) View( ItemStorage parent, int start, int size )
{ {
this.parent = parent; this.parent = parent;
this.start = start; this.start = start;
@ -210,19 +210,19 @@ public interface ItemStorage
return size; return size;
} }
@Nonnull
@Override @Override
public @Nonnull public ItemStack take( int slot, int limit, @Nonnull ItemStack filter, boolean simulate )
ItemStack take( int slot, int limit, @Nonnull ItemStack filter, boolean simulate )
{ {
if( slot < start || slot >= start + size ) return ItemStack.EMPTY; if( slot < start || slot >= start + size ) return ItemStack.EMPTY;
return parent.take( slot - start, limit, filter, simulate ); return parent.take( slot - start, limit, filter, simulate );
} }
@Nonnull
@Override @Override
public @Nonnull public ItemStack store( int slot, @Nonnull ItemStack stack, boolean simulate )
ItemStack store( int slot, @Nonnull ItemStack stack, boolean simulate )
{ {
if( slot < start || slot >= start + size ) return ItemStack.EMPTY; if( slot < start || slot >= start + size ) return stack;
return parent.store( slot - start, stack, simulate ); return parent.store( slot - start, stack, simulate );
} }

View File

@ -8,9 +8,7 @@ package dan200.computercraft.shared.util;
import com.google.common.base.Predicate; import com.google.common.base.Predicate;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
import net.minecraft.entity.Entity; import net.minecraft.entity.*;
import net.minecraft.entity.ItemEntity;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
import net.minecraft.util.hit.HitResult; import net.minecraft.util.hit.HitResult;
@ -31,6 +29,21 @@ public final class WorldUtil
@SuppressWarnings( "Guava" ) @SuppressWarnings( "Guava" )
private static final Predicate<Entity> CAN_COLLIDE = x -> x != null && x.isAlive() && x.collides(); private static final Predicate<Entity> CAN_COLLIDE = x -> x != null && x.isAlive() && x.collides();
private static final Entity ENTITY = new ItemEntity( EntityType.ITEM, null )
{
@Override
public EntitySize getSize( EntityPose pos )
{
return EntitySize.constant( 0, 0 );
}
};
static
{
ENTITY.noClip = true;
ENTITY.refreshSize();
}
public static boolean isLiquidBlock( World world, BlockPos pos ) public static boolean isLiquidBlock( World world, BlockPos pos )
{ {
if( !World.isValid( pos ) ) return false; if( !World.isValid( pos ) ) return false;
@ -51,7 +64,8 @@ public final class WorldUtil
Vec3d vecEnd = vecStart.add( vecDir.x * distance, vecDir.y * distance, vecDir.z * distance ); Vec3d vecEnd = vecStart.add( vecDir.x * distance, vecDir.y * distance, vecDir.z * distance );
// Raycast for blocks // Raycast for blocks
HitResult result = world.rayTrace( new RayTraceContext( vecStart, vecEnd, RayTraceContext.ShapeType.OUTLINE, RayTraceContext.FluidHandling.NONE, null ) ); ENTITY.setPosition( vecStart.x, vecStart.y, vecStart.z );
HitResult result = world.rayTrace( new RayTraceContext( vecStart, vecEnd, RayTraceContext.ShapeType.OUTLINE, RayTraceContext.FluidHandling.NONE, ENTITY ) );
if( result != null && result.getType() == HitResult.Type.BLOCK ) if( result != null && result.getType() == HitResult.Type.BLOCK )
{ {
distance = vecStart.distanceTo( result.getPos() ); distance = vecStart.distanceTo( result.getPos() );

View File

@ -0,0 +1,13 @@
{
"required": true,
"package": "dan200.computercraft.shared.mixin",
"compatibilityLevel": "JAVA_8",
"mixins": [
"MixinBlock",
"MixinEntity",
"MixinServerWorld"
],
"injectors": {
"defaultRequire": 1
}
}

View File

@ -7,7 +7,7 @@
"has_redstone": { "has_redstone": {
"trigger": "minecraft:inventory_changed", "trigger": "minecraft:inventory_changed",
"conditions": { "conditions": {
"items": [ { "tag": "forge:dusts/redstone" } ] "items": [ { "item": "minecraft:redstone" } ]
} }
}, },
"has_the_recipe": { "has_the_recipe": {

View File

@ -7,7 +7,7 @@
"has_redstone": { "has_redstone": {
"trigger": "minecraft:inventory_changed", "trigger": "minecraft:inventory_changed",
"conditions": { "conditions": {
"items": [ { "tag": "forge:dusts/redstone" } ] "items": [ { "item": "minecraft:redstone" } ]
} }
}, },
"has_the_recipe": { "has_the_recipe": {

View File

@ -22,6 +22,7 @@
"main": [ "dan200.computercraft.ComputerCraft" ] "main": [ "dan200.computercraft.ComputerCraft" ]
}, },
"mixins": [ "mixins": [
{ "config": "computercraft.client.json", "environment": "client" } { "config": "computercraft.client.json", "environment": "client" },
"computercraft.common.json"
] ]
} }