add the placer

This commit is contained in:
Ellpeck 2018-11-05 16:36:10 +01:00
parent 7f5c054f0a
commit 6eeebb1e2a
10 changed files with 207 additions and 10 deletions

View file

@ -9,6 +9,7 @@ import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.GlStateManager; import net.minecraft.client.renderer.GlStateManager;
import net.minecraft.client.renderer.RenderHelper; import net.minecraft.client.renderer.RenderHelper;
import net.minecraft.client.renderer.block.model.ItemCameraTransforms; import net.minecraft.client.renderer.block.model.ItemCameraTransforms;
import net.minecraft.entity.item.EntityItemFrame;
import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.init.SoundEvents; import net.minecraft.init.SoundEvents;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
@ -16,6 +17,7 @@ import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.EnumFacing; import net.minecraft.util.EnumFacing;
import net.minecraft.util.EnumHand; import net.minecraft.util.EnumHand;
import net.minecraft.util.SoundCategory; import net.minecraft.util.SoundCategory;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World; import net.minecraft.world.World;
import net.minecraft.world.chunk.IChunkProvider; import net.minecraft.world.chunk.IChunkProvider;
@ -48,6 +50,17 @@ public final class Helper {
} }
} }
public static List<EntityItemFrame> getAttachedItemFrames(World world, BlockPos pos) {
List<EntityItemFrame> 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 // 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 // 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) { public static boolean isChunkLoaded(World world, int x, int z) {

View file

@ -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);
}
}

View file

@ -29,4 +29,5 @@ public final class ModBlocks {
public static final Block AURA_DETECTOR = new BlockAuraDetector(); 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 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 FLOWER_GENERATOR = new BlockFlowerGenerator();
public static final Block PLACER = new BlockPlacer();
} }

View file

@ -188,10 +188,11 @@ public class TileEntityNatureAltar extends TileEntityImpl implements ITickable {
@Override @Override
public void writeNBT(NBTTagCompound compound, SaveType type) { public void writeNBT(NBTTagCompound compound, SaveType type) {
super.writeNBT(compound, type); super.writeNBT(compound, type);
compound.setTag("items", this.items.serializeNBT()); if (type != SaveType.BLOCK) {
compound.setBoolean("fine", this.structureFine); compound.setTag("items", this.items.serializeNBT());
this.container.writeNBT(compound); compound.setBoolean("fine", this.structureFine);
this.container.writeNBT(compound);
}
if (type == SaveType.TILE) { if (type == SaveType.TILE) {
if (this.currentRecipe != null) { if (this.currentRecipe != null) {
compound.setString("recipe", this.currentRecipe.name.toString()); compound.setString("recipe", this.currentRecipe.name.toString());
@ -203,10 +204,11 @@ public class TileEntityNatureAltar extends TileEntityImpl implements ITickable {
@Override @Override
public void readNBT(NBTTagCompound compound, SaveType type) { public void readNBT(NBTTagCompound compound, SaveType type) {
super.readNBT(compound, type); super.readNBT(compound, type);
this.items.deserializeNBT(compound.getCompoundTag("items")); if (type != SaveType.BLOCK) {
this.structureFine = compound.getBoolean("fine"); this.items.deserializeNBT(compound.getCompoundTag("items"));
this.container.readNBT(compound); this.structureFine = compound.getBoolean("fine");
this.container.readNBT(compound);
}
if (type == SaveType.TILE) { if (type == SaveType.TILE) {
if (compound.hasKey("recipe")) { if (compound.hasKey("recipe")) {
this.currentRecipe = AltarRecipe.RECIPES.get(new ResourceLocation(compound.getString("recipe"))); this.currentRecipe = AltarRecipe.RECIPES.get(new ResourceLocation(compound.getString("recipe")));

View file

@ -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<EntityItemFrame> frames = Helper.getAttachedItemFrames(this.world, this.pos);
if (frames.isEmpty())
return;
List<BlockPos> 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<EntityItemFrame> 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());
}
}

View file

@ -164,7 +164,8 @@ public class TileEntityWoodStand extends TileEntityImpl implements ITickable {
@Override @Override
public void writeNBT(NBTTagCompound compound, SaveType type) { public void writeNBT(NBTTagCompound compound, SaveType type) {
super.writeNBT(compound, 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 (type == SaveType.TILE) {
if (this.ritualPos != null && this.recipe != null) { if (this.ritualPos != null && this.recipe != null) {
@ -178,7 +179,8 @@ public class TileEntityWoodStand extends TileEntityImpl implements ITickable {
@Override @Override
public void readNBT(NBTTagCompound compound, SaveType type) { public void readNBT(NBTTagCompound compound, SaveType type) {
super.readNBT(compound, 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 (type == SaveType.TILE) {
if (compound.hasKey("recipe")) { if (compound.hasKey("recipe")) {

View file

@ -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": [{}]
}
}

View file

@ -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.name=Infused Brick Slab
tile.naturesaura.infused_brick_slab_double.name=Infused Brick Double Slab tile.naturesaura.infused_brick_slab_double.name=Infused Brick Double Slab
tile.naturesaura.flower_generator.name=Herbivorous Absorber tile.naturesaura.flower_generator.name=Herbivorous Absorber
tile.naturesaura.placer.name=Imperceptible Builder
item.naturesaura.eye.name=Environmental Eye item.naturesaura.eye.name=Environmental Eye
item.naturesaura.gold_fiber.name=Brilliant Fiber item.naturesaura.gold_fiber.name=Brilliant Fiber

Binary file not shown.

After

Width:  |  Height:  |  Size: 592 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 606 B