diff --git a/src/main/java/de/ellpeck/naturesaura/Helper.java b/src/main/java/de/ellpeck/naturesaura/Helper.java index ba6199d2..1db7028a 100644 --- a/src/main/java/de/ellpeck/naturesaura/Helper.java +++ b/src/main/java/de/ellpeck/naturesaura/Helper.java @@ -9,6 +9,7 @@ import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.GlStateManager; import net.minecraft.client.renderer.RenderHelper; import net.minecraft.client.renderer.block.model.ItemCameraTransforms; +import net.minecraft.entity.item.EntityItemFrame; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.init.SoundEvents; import net.minecraft.item.ItemStack; @@ -16,6 +17,7 @@ import net.minecraft.tileentity.TileEntity; import net.minecraft.util.EnumFacing; import net.minecraft.util.EnumHand; import net.minecraft.util.SoundCategory; +import net.minecraft.util.math.AxisAlignedBB; import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; import net.minecraft.world.chunk.IChunkProvider; @@ -48,6 +50,17 @@ public final class Helper { } } + public static List getAttachedItemFrames(World world, BlockPos pos) { + List frames = world.getEntitiesWithinAABB(EntityItemFrame.class, new AxisAlignedBB(pos).grow(0.25)); + for (int i = frames.size() - 1; i >= 0; i--) { + EntityItemFrame frame = frames.get(i); + BlockPos framePos = frame.getHangingPosition().offset(frame.facingDirection.getOpposite()); + if (!pos.equals(framePos)) + frames.remove(i); + } + return frames; + } + // For some reason this method isn't public in World, but I also don't want to have to make a new BlockPos // or use the messy MutableBlockPos system just to see if a chunk is loaded, so this will have to do I guess public static boolean isChunkLoaded(World world, int x, int z) { diff --git a/src/main/java/de/ellpeck/naturesaura/blocks/BlockPlacer.java b/src/main/java/de/ellpeck/naturesaura/blocks/BlockPlacer.java new file mode 100644 index 00000000..db0d4d77 --- /dev/null +++ b/src/main/java/de/ellpeck/naturesaura/blocks/BlockPlacer.java @@ -0,0 +1,14 @@ +package de.ellpeck.naturesaura.blocks; + +import de.ellpeck.naturesaura.blocks.tiles.TileEntityPlacer; +import net.minecraft.block.SoundType; +import net.minecraft.block.material.Material; + +public class BlockPlacer extends BlockContainerImpl { + + public BlockPlacer() { + super(Material.ROCK, "placer", TileEntityPlacer.class, "placer"); + this.setSoundType(SoundType.STONE); + this.setHardness(2.5F); + } +} diff --git a/src/main/java/de/ellpeck/naturesaura/blocks/ModBlocks.java b/src/main/java/de/ellpeck/naturesaura/blocks/ModBlocks.java index af497ca0..427e74c5 100644 --- a/src/main/java/de/ellpeck/naturesaura/blocks/ModBlocks.java +++ b/src/main/java/de/ellpeck/naturesaura/blocks/ModBlocks.java @@ -29,4 +29,5 @@ public final class ModBlocks { public static final Block AURA_DETECTOR = new BlockAuraDetector(); public static final Block CONVERSION_CATALYST = new BlockImpl("conversion_catalyst", Material.ROCK).setSoundType(SoundType.STONE).setHardness(2.5F); public static final Block FLOWER_GENERATOR = new BlockFlowerGenerator(); + public static final Block PLACER = new BlockPlacer(); } diff --git a/src/main/java/de/ellpeck/naturesaura/blocks/tiles/TileEntityNatureAltar.java b/src/main/java/de/ellpeck/naturesaura/blocks/tiles/TileEntityNatureAltar.java index 7174bc42..2456e7d2 100644 --- a/src/main/java/de/ellpeck/naturesaura/blocks/tiles/TileEntityNatureAltar.java +++ b/src/main/java/de/ellpeck/naturesaura/blocks/tiles/TileEntityNatureAltar.java @@ -188,10 +188,11 @@ public class TileEntityNatureAltar extends TileEntityImpl implements ITickable { @Override public void writeNBT(NBTTagCompound compound, SaveType type) { super.writeNBT(compound, type); - compound.setTag("items", this.items.serializeNBT()); - compound.setBoolean("fine", this.structureFine); - this.container.writeNBT(compound); - + if (type != SaveType.BLOCK) { + compound.setTag("items", this.items.serializeNBT()); + compound.setBoolean("fine", this.structureFine); + this.container.writeNBT(compound); + } if (type == SaveType.TILE) { if (this.currentRecipe != null) { compound.setString("recipe", this.currentRecipe.name.toString()); @@ -203,10 +204,11 @@ public class TileEntityNatureAltar extends TileEntityImpl implements ITickable { @Override public void readNBT(NBTTagCompound compound, SaveType type) { super.readNBT(compound, type); - this.items.deserializeNBT(compound.getCompoundTag("items")); - this.structureFine = compound.getBoolean("fine"); - this.container.readNBT(compound); - + if (type != SaveType.BLOCK) { + this.items.deserializeNBT(compound.getCompoundTag("items")); + this.structureFine = compound.getBoolean("fine"); + this.container.readNBT(compound); + } if (type == SaveType.TILE) { if (compound.hasKey("recipe")) { this.currentRecipe = AltarRecipe.RECIPES.get(new ResourceLocation(compound.getString("recipe"))); diff --git a/src/main/java/de/ellpeck/naturesaura/blocks/tiles/TileEntityPlacer.java b/src/main/java/de/ellpeck/naturesaura/blocks/tiles/TileEntityPlacer.java new file mode 100644 index 00000000..1fa7fc8f --- /dev/null +++ b/src/main/java/de/ellpeck/naturesaura/blocks/tiles/TileEntityPlacer.java @@ -0,0 +1,144 @@ +package de.ellpeck.naturesaura.blocks.tiles; + +import de.ellpeck.naturesaura.Helper; +import de.ellpeck.naturesaura.aura.chunk.AuraChunk; +import de.ellpeck.naturesaura.blocks.ModBlocks; +import net.minecraft.block.state.IBlockState; +import net.minecraft.entity.item.EntityItemFrame; +import net.minecraft.init.Blocks; +import net.minecraft.init.Items; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.EnumFacing; +import net.minecraft.util.EnumHand; +import net.minecraft.util.ITickable; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.WorldServer; +import net.minecraftforge.common.IPlantable; +import net.minecraftforge.common.util.FakePlayer; +import net.minecraftforge.common.util.FakePlayerFactory; +import net.minecraftforge.items.CapabilityItemHandler; +import net.minecraftforge.items.IItemHandler; +import net.minecraftforge.items.IItemHandlerModifiable; + +import java.util.ArrayList; +import java.util.List; + +public class TileEntityPlacer extends TileEntityImpl implements ITickable { + + private final ItemStackHandlerNA handler = new ItemStackHandlerNA(1, this, true); + + @Override + public void update() { + if (!this.world.isRemote && this.world.getTotalWorldTime() % 15 == 0) { + TileEntity tileUp = this.world.getTileEntity(this.pos.up()); + if (tileUp == null || !tileUp.hasCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, EnumFacing.DOWN)) + return; + IItemHandler handler = tileUp.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, EnumFacing.DOWN); + if (handler == null) + return; + List frames = Helper.getAttachedItemFrames(this.world, this.pos); + if (frames.isEmpty()) + return; + + List validPositions = new ArrayList<>(); + int range = 5; + for (int x = -range; x <= range; x++) + for (int y = -range; y <= range; y++) + for (int z = -range; z <= range; z++) { + BlockPos pos = this.pos.add(x, y, z); + if (!this.framesContain(frames, pos, this.world.getBlockState(pos))) + continue; + + BlockPos up = pos.up(); + IBlockState state = this.world.getBlockState(up); + if (state.getBlock().isReplaceable(this.world, up)) + validPositions.add(up); + } + if (validPositions.isEmpty()) + return; + + for (int i = 0; i < handler.getSlots(); i++) { + ItemStack stack = handler.extractItem(i, 1, true); + if (stack.isEmpty()) + continue; + + BlockPos pos = validPositions.get(this.world.rand.nextInt(validPositions.size())); + ItemStack left = this.tryPlace(stack.copy(), pos); + if (ItemStack.areItemStacksEqual(stack, left)) + continue; + + handler.extractItem(i, 1, false); + BlockPos spot = AuraChunk.getHighestSpot(this.world, this.pos, 10, this.pos); + AuraChunk.getAuraChunk(this.world, spot).drainAura(spot, 10); + return; + } + } + } + + private boolean framesContain(List frames, BlockPos pos, IBlockState state) { + ItemStack stack = state.getBlock().getItem(this.world, pos, state); + if (stack.isEmpty()) + return false; + + for (EntityItemFrame frame : frames) { + ItemStack frameStack = frame.getDisplayedItem(); + if (!frameStack.isEmpty() && stack.isItemEqual(frameStack)) + return true; + } + return false; + } + + private ItemStack tryPlace(ItemStack stack, BlockPos pos) { + if (this.handleSpecialCases(stack, pos)) + return stack; + + if (!(this.world instanceof WorldServer)) + return stack; + + FakePlayer fake = FakePlayerFactory.getMinecraft((WorldServer) this.world); + fake.inventory.mainInventory.set(fake.inventory.currentItem, stack); + fake.interactionManager.processRightClickBlock(fake, this.world, fake.getHeldItemMainhand(), EnumHand.MAIN_HAND, + pos, EnumFacing.DOWN, 0.5F, 0.5F, 0.5F); + return fake.getHeldItemMainhand().copy(); + } + + private boolean handleSpecialCases(ItemStack stack, BlockPos pos) { + if (stack.getItem() == Items.REDSTONE) + this.world.setBlockState(pos, Blocks.REDSTONE_WIRE.getDefaultState()); + else if (stack.getItem() == Item.getItemFromBlock(ModBlocks.GOLD_POWDER)) + this.world.setBlockState(pos, ModBlocks.GOLD_POWDER.getDefaultState()); + else if (stack.getItem() instanceof IPlantable) { + IPlantable plantable = (IPlantable) stack.getItem(); + IBlockState plant = plantable.getPlant(this.world, pos); + if (!plant.getBlock().canPlaceBlockAt(this.world, pos)) + return false; + this.world.setBlockState(pos, plant); + } else + return false; + + stack.shrink(1); + return true; + } + + @Override + public IItemHandlerModifiable getItemHandler(EnumFacing facing) { + return this.handler; + } + + @Override + public void readNBT(NBTTagCompound compound, SaveType type) { + super.readNBT(compound, type); + if (type != SaveType.BLOCK) + this.handler.deserializeNBT(compound.getCompoundTag("items")); + } + + @Override + public void writeNBT(NBTTagCompound compound, SaveType type) { + super.writeNBT(compound, type); + if (type != SaveType.BLOCK) + compound.setTag("items", this.handler.serializeNBT()); + } +} diff --git a/src/main/java/de/ellpeck/naturesaura/blocks/tiles/TileEntityWoodStand.java b/src/main/java/de/ellpeck/naturesaura/blocks/tiles/TileEntityWoodStand.java index 3d7b6dc5..da3b7fc4 100644 --- a/src/main/java/de/ellpeck/naturesaura/blocks/tiles/TileEntityWoodStand.java +++ b/src/main/java/de/ellpeck/naturesaura/blocks/tiles/TileEntityWoodStand.java @@ -164,7 +164,8 @@ public class TileEntityWoodStand extends TileEntityImpl implements ITickable { @Override public void writeNBT(NBTTagCompound compound, SaveType type) { super.writeNBT(compound, type); - compound.setTag("items", this.items.serializeNBT()); + if (type != SaveType.BLOCK) + compound.setTag("items", this.items.serializeNBT()); if (type == SaveType.TILE) { if (this.ritualPos != null && this.recipe != null) { @@ -178,7 +179,8 @@ public class TileEntityWoodStand extends TileEntityImpl implements ITickable { @Override public void readNBT(NBTTagCompound compound, SaveType type) { super.readNBT(compound, type); - this.items.deserializeNBT(compound.getCompoundTag("items")); + if (type != SaveType.BLOCK) + this.items.deserializeNBT(compound.getCompoundTag("items")); if (type == SaveType.TILE) { if (compound.hasKey("recipe")) { diff --git a/src/main/resources/assets/naturesaura/blockstates/placer.json b/src/main/resources/assets/naturesaura/blockstates/placer.json new file mode 100644 index 00000000..3aa44af8 --- /dev/null +++ b/src/main/resources/assets/naturesaura/blockstates/placer.json @@ -0,0 +1,20 @@ +{ + "forge_marker": 1, + "defaults": { + "model": "minecraft:cube", + "textures": { + "particle": "naturesaura:blocks/placer", + "up": "naturesaura:blocks/placer_top", + "down": "naturesaura:blocks/placer_top", + "north": "#particle", + "east": "#particle", + "south": "#particle", + "west": "#particle" + }, + "transform": "forge:default-block" + }, + "variants": { + "normal": [{}], + "inventory": [{}] + } +} \ No newline at end of file diff --git a/src/main/resources/assets/naturesaura/lang/en_US.lang b/src/main/resources/assets/naturesaura/lang/en_US.lang index cccecf0b..14d36468 100644 --- a/src/main/resources/assets/naturesaura/lang/en_US.lang +++ b/src/main/resources/assets/naturesaura/lang/en_US.lang @@ -26,6 +26,7 @@ tile.naturesaura.infused_brick_stairs.name=Infused Brick Stairs tile.naturesaura.infused_brick_slab.name=Infused Brick Slab tile.naturesaura.infused_brick_slab_double.name=Infused Brick Double Slab tile.naturesaura.flower_generator.name=Herbivorous Absorber +tile.naturesaura.placer.name=Imperceptible Builder item.naturesaura.eye.name=Environmental Eye item.naturesaura.gold_fiber.name=Brilliant Fiber diff --git a/src/main/resources/assets/naturesaura/textures/blocks/placer.png b/src/main/resources/assets/naturesaura/textures/blocks/placer.png new file mode 100644 index 00000000..d13cf29a Binary files /dev/null and b/src/main/resources/assets/naturesaura/textures/blocks/placer.png differ diff --git a/src/main/resources/assets/naturesaura/textures/blocks/placer_top.png b/src/main/resources/assets/naturesaura/textures/blocks/placer_top.png new file mode 100644 index 00000000..1ccaf940 Binary files /dev/null and b/src/main/resources/assets/naturesaura/textures/blocks/placer_top.png differ