From c6c9a8f8eb2a611d281c3341ab6bcfd87bd5ec0d Mon Sep 17 00:00:00 2001 From: simibubi <31564874+simibubi@users.noreply.github.com> Date: Sat, 13 Jul 2019 12:55:28 +0200 Subject: [PATCH] Schematicannon Physics - Blocks fired now follow a semi-reasonable trajectory - Added models and animations - Added a Creative block for use with the cannon to ignore materials --- .../java/com/simibubi/create/AllBlocks.java | 6 + .../com/simibubi/create/AllTileEntities.java | 10 +- .../create/block/CreativeCrateBlock.java | 35 ++++ .../simibubi/create/block/RenderingBlock.java | 12 ++ .../create/block/SchematicTableBlock.java | 47 ++++- .../create/block/SchematicTableContainer.java | 4 +- .../create/block/SchematicannonBlock.java | 6 + .../create/block/SchematicannonRenderer.java | 120 ++++++++++++ .../block/SchematicannonTileEntity.java | 173 +++++++++++++++++- .../create/gui/SchematicTableScreen.java | 48 ++++- .../create/blockstates/creative_crate.json | 6 + .../create/blockstates/schematic_table.json | 8 +- .../create/blockstates/schematicannon.json | 2 +- .../blockstates/schematicannon_connector.json | 6 + .../blockstates/schematicannon_pipe.json | 6 + .../create/models/block/creative_crate.json | 24 +++ .../create/models/block/schematic_table.json | 77 ++++++++ .../models/block/schematicannon_base.json | 52 ++++++ .../block/schematicannon_connector.json | 48 +++++ .../models/block/schematicannon_pipe.json | 61 ++++++ .../create/models/item/creative_crate.json | 3 + .../create/models/item/schematic_table.json | 2 +- .../create/models/item/schematicannon.json | 150 ++++++++++++++- .../textures/block/creative_crate_side.png | Bin 0 -> 524 bytes .../textures/block/creative_crate_top.png | Bin 0 -> 316 bytes .../textures/block/schematic_table_side.png | Bin 0 -> 440 bytes .../textures/block/schematic_table_top.png | Bin 0 -> 328 bytes 27 files changed, 877 insertions(+), 29 deletions(-) create mode 100644 src/main/java/com/simibubi/create/block/CreativeCrateBlock.java create mode 100644 src/main/java/com/simibubi/create/block/RenderingBlock.java create mode 100644 src/main/java/com/simibubi/create/block/SchematicannonRenderer.java create mode 100644 src/main/resources/assets/create/blockstates/creative_crate.json create mode 100644 src/main/resources/assets/create/blockstates/schematicannon_connector.json create mode 100644 src/main/resources/assets/create/blockstates/schematicannon_pipe.json create mode 100644 src/main/resources/assets/create/models/block/creative_crate.json create mode 100644 src/main/resources/assets/create/models/block/schematic_table.json create mode 100644 src/main/resources/assets/create/models/block/schematicannon_base.json create mode 100644 src/main/resources/assets/create/models/block/schematicannon_connector.json create mode 100644 src/main/resources/assets/create/models/block/schematicannon_pipe.json create mode 100644 src/main/resources/assets/create/models/item/creative_crate.json create mode 100644 src/main/resources/assets/create/textures/block/creative_crate_side.png create mode 100644 src/main/resources/assets/create/textures/block/creative_crate_top.png create mode 100644 src/main/resources/assets/create/textures/block/schematic_table_side.png create mode 100644 src/main/resources/assets/create/textures/block/schematic_table_top.png diff --git a/src/main/java/com/simibubi/create/AllBlocks.java b/src/main/java/com/simibubi/create/AllBlocks.java index 26ebed300..839528156 100644 --- a/src/main/java/com/simibubi/create/AllBlocks.java +++ b/src/main/java/com/simibubi/create/AllBlocks.java @@ -1,6 +1,8 @@ package com.simibubi.create; +import com.simibubi.create.block.CreativeCrateBlock; import com.simibubi.create.block.IJustForRendering; +import com.simibubi.create.block.RenderingBlock; import com.simibubi.create.block.SchematicTableBlock; import com.simibubi.create.block.SchematicannonBlock; import com.simibubi.create.block.symmetry.BlockSymmetryCrossPlane; @@ -16,6 +18,10 @@ import net.minecraftforge.registries.IForgeRegistry; public enum AllBlocks { SCHEMATICANNON(new SchematicannonBlock()), + SCHEMATICANNON_CONNECTOR(new RenderingBlock()), + SCHEMATICANNON_PIPE(new RenderingBlock()), + CREATIVE_CRATE(new CreativeCrateBlock()), + SCHEMATIC_TABLE(new SchematicTableBlock()), SYMMETRY_PLANE(new BlockSymmetryPlane()), diff --git a/src/main/java/com/simibubi/create/AllTileEntities.java b/src/main/java/com/simibubi/create/AllTileEntities.java index b7592d262..45fb8105a 100644 --- a/src/main/java/com/simibubi/create/AllTileEntities.java +++ b/src/main/java/com/simibubi/create/AllTileEntities.java @@ -3,13 +3,16 @@ package com.simibubi.create; import java.util.function.Supplier; import com.simibubi.create.block.SchematicTableTileEntity; +import com.simibubi.create.block.SchematicannonRenderer; import com.simibubi.create.block.SchematicannonTileEntity; +import net.minecraft.client.renderer.tileentity.TileEntityRenderer; import net.minecraft.tileentity.TileEntity; import net.minecraft.tileentity.TileEntityType; import net.minecraft.util.ResourceLocation; import net.minecraftforge.event.RegistryEvent; import net.minecraftforge.eventbus.api.SubscribeEvent; +import net.minecraftforge.fml.client.registry.ClientRegistry; import net.minecraftforge.fml.common.Mod; import net.minecraftforge.fml.common.Mod.EventBusSubscriber.Bus; @@ -40,10 +43,11 @@ public enum AllTileEntities { } public static void registerRenderers() { + bind(SchematicannonTileEntity.class, new SchematicannonRenderer()); } -// private static void bind(Class clazz, TileEntityRenderer renderer) { -// ClientRegistry.bindTileEntitySpecialRenderer(clazz, renderer); -// } + private static void bind(Class clazz, TileEntityRenderer renderer) { + ClientRegistry.bindTileEntitySpecialRenderer(clazz, renderer); + } } diff --git a/src/main/java/com/simibubi/create/block/CreativeCrateBlock.java b/src/main/java/com/simibubi/create/block/CreativeCrateBlock.java new file mode 100644 index 000000000..50a1542ab --- /dev/null +++ b/src/main/java/com/simibubi/create/block/CreativeCrateBlock.java @@ -0,0 +1,35 @@ +package com.simibubi.create.block; + +import net.minecraft.block.Block; +import net.minecraft.block.BlockState; +import net.minecraft.block.material.Material; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.shapes.ISelectionContext; +import net.minecraft.util.math.shapes.VoxelShape; +import net.minecraft.world.IBlockReader; + +public class CreativeCrateBlock extends Block { + + protected static final VoxelShape shape = makeCuboidShape(1, 0, 1, 15, 14, 15); + + public CreativeCrateBlock() { + super(Properties.create(Material.WOOD)); + } + + @Override + public boolean isSolid(BlockState state) { + return false; + } + + @Override + public VoxelShape getShape(BlockState state, IBlockReader worldIn, BlockPos pos, ISelectionContext context) { + return shape; + } + + @Override + public VoxelShape getCollisionShape(BlockState state, IBlockReader worldIn, BlockPos pos, + ISelectionContext context) { + return shape; + } + +} diff --git a/src/main/java/com/simibubi/create/block/RenderingBlock.java b/src/main/java/com/simibubi/create/block/RenderingBlock.java new file mode 100644 index 000000000..0418fb616 --- /dev/null +++ b/src/main/java/com/simibubi/create/block/RenderingBlock.java @@ -0,0 +1,12 @@ +package com.simibubi.create.block; + +import net.minecraft.block.Block; +import net.minecraft.block.material.Material; + +public class RenderingBlock extends Block implements IJustForRendering { + + public RenderingBlock() { + super(Properties.create(Material.AIR)); + } + +} diff --git a/src/main/java/com/simibubi/create/block/SchematicTableBlock.java b/src/main/java/com/simibubi/create/block/SchematicTableBlock.java index 17d89235b..39904510d 100644 --- a/src/main/java/com/simibubi/create/block/SchematicTableBlock.java +++ b/src/main/java/com/simibubi/create/block/SchematicTableBlock.java @@ -1,12 +1,17 @@ package com.simibubi.create.block; -import net.minecraft.block.BlockRenderType; +import javax.annotation.Nullable; + +import net.minecraft.block.Block; import net.minecraft.block.BlockState; import net.minecraft.block.Blocks; -import net.minecraft.block.ContainerBlock; +import net.minecraft.block.HorizontalBlock; +import net.minecraft.block.ITileEntityProvider; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.inventory.InventoryHelper; import net.minecraft.inventory.container.INamedContainerProvider; +import net.minecraft.item.BlockItemUseContext; +import net.minecraft.state.StateContainer.Builder; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.Hand; import net.minecraft.util.math.BlockPos; @@ -14,17 +19,29 @@ import net.minecraft.util.math.BlockRayTraceResult; import net.minecraft.world.IBlockReader; import net.minecraft.world.World; -public class SchematicTableBlock extends ContainerBlock { +@SuppressWarnings("deprecation") +public class SchematicTableBlock extends HorizontalBlock implements ITileEntityProvider { public SchematicTableBlock() { super(Properties.from(Blocks.OAK_PLANKS)); } @Override - public BlockRenderType getRenderType(BlockState state) { - return BlockRenderType.MODEL; + protected void fillStateContainer(Builder builder) { + builder.add(HORIZONTAL_FACING); + super.fillStateContainer(builder); } + @Override + public boolean isSolid(BlockState state) { + return false; + } + + @Override + public BlockState getStateForPlacement(BlockItemUseContext context) { + return this.getDefaultState().with(HORIZONTAL_FACING, context.getPlacementHorizontalFacing().getOpposite()); + } + @Override public boolean hasTileEntity() { return true; @@ -49,18 +66,30 @@ public class SchematicTableBlock extends ContainerBlock { public TileEntity createNewTileEntity(IBlockReader worldIn) { return new SchematicTableTileEntity(); } - + @Override public void onReplaced(BlockState state, World worldIn, BlockPos pos, BlockState newState, boolean isMoving) { - if (worldIn.getTileEntity(pos) == null) + if (worldIn.getTileEntity(pos) == null) return; - + SchematicTableTileEntity te = (SchematicTableTileEntity) worldIn.getTileEntity(pos); if (!te.inputStack.isEmpty()) InventoryHelper.spawnItemStack(worldIn, pos.getX(), pos.getY(), pos.getZ(), te.inputStack); if (!te.outputStack.isEmpty()) InventoryHelper.spawnItemStack(worldIn, pos.getX(), pos.getY(), pos.getZ(), te.outputStack); - + + } + + public boolean eventReceived(BlockState state, World worldIn, BlockPos pos, int id, int param) { + super.eventReceived(state, worldIn, pos, id, param); + TileEntity tileentity = worldIn.getTileEntity(pos); + return tileentity == null ? false : tileentity.receiveClientEvent(id, param); + } + + @Nullable + public INamedContainerProvider getContainer(BlockState state, World worldIn, BlockPos pos) { + TileEntity tileentity = worldIn.getTileEntity(pos); + return tileentity instanceof INamedContainerProvider ? (INamedContainerProvider) tileentity : null; } } diff --git a/src/main/java/com/simibubi/create/block/SchematicTableContainer.java b/src/main/java/com/simibubi/create/block/SchematicTableContainer.java index 7d07a1e51..e614a8f5e 100644 --- a/src/main/java/com/simibubi/create/block/SchematicTableContainer.java +++ b/src/main/java/com/simibubi/create/block/SchematicTableContainer.java @@ -45,14 +45,14 @@ public class SchematicTableContainer extends Container { this.player = inv.player; this.te = te; - inputSlot = new Slot(tableInventory, 0, 31, 15) { + inputSlot = new Slot(tableInventory, 0, -9, 15) { @Override public boolean isItemValid(ItemStack stack) { return AllItems.EMPTY_BLUEPRINT.typeOf(stack); } }; - outputSlot = new Slot(tableInventory, 1, 115, 15) { + outputSlot = new Slot(tableInventory, 1, 75, 15) { @Override public boolean isItemValid(ItemStack stack) { return false; diff --git a/src/main/java/com/simibubi/create/block/SchematicannonBlock.java b/src/main/java/com/simibubi/create/block/SchematicannonBlock.java index d15fe2fcd..a42ffeb42 100644 --- a/src/main/java/com/simibubi/create/block/SchematicannonBlock.java +++ b/src/main/java/com/simibubi/create/block/SchematicannonBlock.java @@ -33,6 +33,12 @@ public class SchematicannonBlock extends Block { return stateIn; } + @Override + public boolean isSolid(BlockState state) { + return false; + } + + @Override public void onNeighborChange(BlockState state, IWorldReader world, BlockPos pos, BlockPos neighbor) { ((SchematicannonTileEntity) world.getTileEntity(pos)).findInventories(); diff --git a/src/main/java/com/simibubi/create/block/SchematicannonRenderer.java b/src/main/java/com/simibubi/create/block/SchematicannonRenderer.java new file mode 100644 index 000000000..b8bbb5321 --- /dev/null +++ b/src/main/java/com/simibubi/create/block/SchematicannonRenderer.java @@ -0,0 +1,120 @@ +package com.simibubi.create.block; + +import com.mojang.blaze3d.platform.GlStateManager; +import com.simibubi.create.AllBlocks; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.texture.AtlasTexture; +import net.minecraft.client.renderer.tileentity.TileEntityRenderer; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.MathHelper; +import net.minecraft.util.math.Vec3d; + +public class SchematicannonRenderer extends TileEntityRenderer { + + @Override + public void render(SchematicannonTileEntity tileEntityIn, double x, double y, double z, float partialTicks, + int destroyStage) { + + Minecraft.getInstance().getTextureManager().bindTexture(AtlasTexture.LOCATION_BLOCKS_TEXTURE); + + double yaw = 0; + double pitch = 40; + double recoil = 0; + + BlockPos pos = tileEntityIn.getPos(); + if (tileEntityIn.target != null) { + + // Calculate Angle of Cannon + Vec3d diff = new Vec3d(tileEntityIn.target.subtract(pos)); + if (tileEntityIn.previousTarget != null) { + diff = (new Vec3d(tileEntityIn.previousTarget) + .add(new Vec3d(tileEntityIn.target.subtract(tileEntityIn.previousTarget)).scale(partialTicks))) + .subtract(new Vec3d(pos)); + } + + double diffX = diff.getX(); + double diffZ = diff.getZ(); + yaw = MathHelper.atan2(diffX, diffZ); + yaw = yaw / Math.PI * 180; + + float distance = MathHelper.sqrt(diffX * diffX + diffZ * diffZ); + double yOffset = 0 + distance * 2f; + pitch = MathHelper.atan2(distance, diff.getY() * 3 + yOffset); + pitch = pitch / Math.PI * 180 + 10; + + } + + if (!tileEntityIn.flyingBlocks.isEmpty()) { + for (SchematicannonTileEntity.LaunchedBlock block : tileEntityIn.flyingBlocks) { + + if (block.ticksRemaining == 0) + continue; + + // Calculate position of flying block + Vec3d start = new Vec3d(tileEntityIn.getPos().add(.5f, 1, .5f)); + Vec3d target = new Vec3d(block.target).add(-.5, 0, 1); + Vec3d distance = target.subtract(start); + + double targetY = target.y - start.y; + double throwHeight = Math.sqrt(distance.lengthSquared()) * .6f + targetY; + Vec3d cannonOffset = distance.add(0, throwHeight, 0).normalize().scale(2); + start = start.add(cannonOffset); + + double progress = ((double) block.totalTicks - (block.ticksRemaining + 1 - partialTicks)) + / block.totalTicks; + Vec3d blockLocationXZ = new Vec3d(x + .5, y + .5, z + .5) + .add(target.subtract(start).scale(progress).mul(1, 0, 1)); + + // Height is determined through a bezier curve + double t = progress; + double yOffset = 2 * (1 - t) * t * throwHeight + t * t * targetY; + Vec3d blockLocation = blockLocationXZ.add(0, yOffset + 1, 0).add(cannonOffset); + + // Offset to position + GlStateManager.pushMatrix(); + GlStateManager.translated(blockLocation.x, blockLocation.y, blockLocation.z); + + // Rotation and Scaling effects + double scale = .3f; + GlStateManager.rotated(360 * t * 2, 1, 1, 0); + GlStateManager.scaled(scale, scale, scale); + + // Render the Block + Minecraft.getInstance().getBlockRendererDispatcher().renderBlockBrightness(block.state, 1); + GlStateManager.popMatrix(); + +// Minecraft.getInstance().world.addParticle(ParticleTypes.END_ROD, blockLocation.x, blockLocation.y, +// blockLocation.z, 0, 0, 0); + + // Apply Recoil if block was just launched + if ((block.ticksRemaining + 1 - partialTicks) > block.totalTicks - 10) { + recoil = Math.max(recoil, (block.ticksRemaining + 1 - partialTicks) - block.totalTicks + 10); + } + } + } + + GlStateManager.pushMatrix(); + GlStateManager.translated(x + .5f, y, z + 1 - .5f); + GlStateManager.rotated(yaw, 0, 1, 0); + GlStateManager.translated(-0.5f, 0, 0.5f); + Minecraft.getInstance().getBlockRendererDispatcher() + .renderBlockBrightness(AllBlocks.SCHEMATICANNON_CONNECTOR.get().getDefaultState(), 1); + GlStateManager.popMatrix(); + + GlStateManager.pushMatrix(); + GlStateManager.translated(x + .5f, y + .90f, z + 1 - .5f); + GlStateManager.rotated(yaw, 0, 1, 0); + GlStateManager.rotated(pitch, 1, 0, 0); + GlStateManager.translated(-0.5f, -.90f, 0.5f); + + GlStateManager.translated(0, -recoil / 100, 0); + + Minecraft.getInstance().getBlockRendererDispatcher() + .renderBlockBrightness(AllBlocks.SCHEMATICANNON_PIPE.get().getDefaultState(), 1); + GlStateManager.popMatrix(); + + super.render(tileEntityIn, x, y, z, partialTicks, destroyStage); + } + +} diff --git a/src/main/java/com/simibubi/create/block/SchematicannonTileEntity.java b/src/main/java/com/simibubi/create/block/SchematicannonTileEntity.java index 7dcf46dc7..d556ad35b 100644 --- a/src/main/java/com/simibubi/create/block/SchematicannonTileEntity.java +++ b/src/main/java/com/simibubi/create/block/SchematicannonTileEntity.java @@ -11,6 +11,7 @@ import java.util.List; import org.apache.commons.io.IOUtils; +import com.simibubi.create.AllBlocks; import com.simibubi.create.AllTileEntities; import com.simibubi.create.ServerSchematicLoader; import com.simibubi.create.schematic.Cuboid; @@ -19,50 +20,109 @@ import com.simibubi.create.utility.TileEntitySynced; import net.minecraft.block.BlockState; import net.minecraft.block.Blocks; +import net.minecraft.entity.Entity; import net.minecraft.item.BlockItem; import net.minecraft.item.ItemStack; import net.minecraft.item.Items; import net.minecraft.nbt.CompoundNBT; import net.minecraft.nbt.CompressedStreamTools; +import net.minecraft.nbt.ListNBT; +import net.minecraft.nbt.NBTUtil; import net.minecraft.tileentity.ITickableTileEntity; import net.minecraft.tileentity.TileEntity; import net.minecraft.tileentity.TileEntityType; import net.minecraft.util.Direction; +import net.minecraft.util.math.AxisAlignedBB; import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.MathHelper; +import net.minecraft.util.math.Vec3d; +import net.minecraft.world.Explosion; import net.minecraft.world.gen.feature.template.PlacementSettings; import net.minecraft.world.gen.feature.template.Template; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; import net.minecraftforge.common.util.LazyOptional; import net.minecraftforge.items.CapabilityItemHandler; import net.minecraftforge.items.IItemHandler; public class SchematicannonTileEntity extends TileEntitySynced implements ITickableTileEntity { - public static final int PLACEMENT_DELAY = 2; + public static final int PLACEMENT_DELAY = 10; private SchematicWorld reader; - private BlockPos currentPos; + public BlockPos currentPos; public BlockPos anchor; public String schematicToPrint; public boolean missingBlock; + public boolean creative; + + public BlockPos target; + public BlockPos previousTarget; public List attachedInventories; + public List flyingBlocks; private int cooldown; + public class LaunchedBlock { + public int totalTicks; + public int ticksRemaining; + public BlockPos target; + public BlockState state; + + public LaunchedBlock(BlockPos target, BlockState state) { + this.target = target; + this.state = state; + totalTicks = (int) (Math.max(10, MathHelper.sqrt(MathHelper.sqrt(target.distanceSq(pos))) * 4f)); + ticksRemaining = totalTicks; + } + + public LaunchedBlock(BlockPos target, BlockState state, int ticksLeft, int total) { + this.target = target; + this.state = state; + this.totalTicks = total; + this.ticksRemaining = ticksLeft; + } + + public void update() { + if (ticksRemaining > 0) + ticksRemaining--; + } + } + public SchematicannonTileEntity() { this(AllTileEntities.Schematicannon.type); } + @Override + public double getMaxRenderDistanceSquared() { + return 65536.0D; + } + + @OnlyIn(Dist.CLIENT) + @Override + public AxisAlignedBB getRenderBoundingBox() { + return INFINITE_EXTENT_AABB; + } + public SchematicannonTileEntity(TileEntityType tileEntityTypeIn) { super(tileEntityTypeIn); attachedInventories = new LinkedList<>(); + flyingBlocks = new LinkedList<>(); } public void findInventories() { + creative = false; for (Direction facing : Direction.values()) { + + if (AllBlocks.CREATIVE_CRATE.typeOf(world.getBlockState(pos.offset(facing)))) { + creative = true; + } + TileEntity tileEntity = world.getTileEntity(pos.offset(facing)); if (tileEntity != null) { - LazyOptional capability = tileEntity.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, facing.getOpposite()); + LazyOptional capability = tileEntity + .getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, facing.getOpposite()); if (capability.isPresent()) { attachedInventories.add(capability.orElse(null)); } @@ -72,16 +132,86 @@ public class SchematicannonTileEntity extends TileEntitySynced implements ITicka @Override public void read(CompoundNBT compound) { + if (compound.contains("Target")) { + target = NBTUtil.readBlockPos(compound.getCompound("Target")); + } + + if (compound.contains("FlyingBlocks")) { + + ListNBT tagBlocks = compound.getList("FlyingBlocks", 10); + if (tagBlocks.isEmpty()) + flyingBlocks.clear(); + + boolean pastDead = false; + + for (int i = 0; i < tagBlocks.size(); i++) { + CompoundNBT c = tagBlocks.getCompound(i); + + BlockPos readBlockPos = NBTUtil.readBlockPos(c.getCompound("Target")); + BlockState readBlockState = NBTUtil.readBlockState(c.getCompound("Block")); + int int1 = c.getInt("TicksLeft"); + int int2 = c.getInt("TotalTicks"); + + // Always write to Server tile + if (!world.isRemote) { + flyingBlocks.add(new LaunchedBlock(readBlockPos, readBlockState, int1, int2)); + continue; + } + + // Delete all Client side blocks that are now missing on the server + while (!pastDead && !flyingBlocks.isEmpty() && !flyingBlocks.get(0).target.equals(readBlockPos)) { + flyingBlocks.remove(0); + } + + pastDead = true; + + // Add new server side blocks + if (i >= flyingBlocks.size()) { + flyingBlocks.add(new LaunchedBlock(readBlockPos, readBlockState, int1, int2)); + continue; + } + + // Don't do anything with existing + } + } + super.read(compound); } @Override public CompoundNBT write(CompoundNBT compound) { + if (target != null) { + compound.put("Target", NBTUtil.writeBlockPos(target)); + } + + ListNBT tagBlocks = new ListNBT(); + for (LaunchedBlock b : flyingBlocks) { + CompoundNBT c = new CompoundNBT(); + c.putInt("TotalTicks", b.totalTicks); + c.putInt("TicksLeft", b.ticksRemaining); + c.put("Target", NBTUtil.writeBlockPos(b.target)); + c.put("Block", NBTUtil.writeBlockState(b.state)); + tagBlocks.add(c); + } + compound.put("FlyingBlocks", tagBlocks); + return super.write(compound); } @Override public void tick() { + previousTarget = target; + + List toRemove = new LinkedList<>(); + for (LaunchedBlock b : flyingBlocks) { + b.update(); + if (b.ticksRemaining <= 0 && !world.isRemote) { + world.setBlockState(b.target, b.state); + toRemove.add(b); + } + } + flyingBlocks.removeAll(toRemove); + if (world.isRemote) return; if (schematicToPrint == null) @@ -117,7 +247,8 @@ public class SchematicannonTileEntity extends TileEntitySynced implements ITicka BlockPos size = reader.getBounds().getSize(); BlockState state; do { - if (!missingBlock) + // Find next block to place + if (!missingBlock || creative) currentPos = currentPos.offset(Direction.EAST); if (currentPos.getX() > size.getX()) { currentPos = new BlockPos(0, currentPos.getY(), currentPos.getZ() + 1); @@ -135,21 +266,49 @@ public class SchematicannonTileEntity extends TileEntitySynced implements ITicka } state = reader.getBlockState(anchor.add(currentPos)); } while (state.getBlock() == Blocks.AIR); - + + target = anchor.add(currentPos); + + // Update orientation + world.notifyBlockUpdate(getPos(), getBlockState(), getBlockState(), 3); + + if (creative) { + launchBlock(currentPos.add(anchor), state); + missingBlock = false; + return; + } + + if (world.getBlockState(target).getBlock() == state.getBlock()) { + // Don't overwrite tiles + if (world.getTileEntity(target) != null) + return; + + // Overwrite in case its rotated + launchBlock(target, state); + missingBlock = false; + } + + // Search for required item missingBlock = true; ItemStack requiredItem = new ItemStack(BlockItem.BLOCK_TO_ITEM.getOrDefault(state.getBlock(), Items.AIR)); for (IItemHandler iItemHandler : attachedInventories) { for (int slot = 0; slot < iItemHandler.getSlots(); slot++) { ItemStack stackInSlot = iItemHandler.getStackInSlot(slot); - if (!stackInSlot.isItemEqual(requiredItem)) + if (!stackInSlot.isItemEqual(requiredItem)) continue; iItemHandler.extractItem(slot, 1, false); - world.setBlockState(currentPos.add(anchor), state); + launchBlock(target, state); missingBlock = false; return; } } + } + private void launchBlock(BlockPos target, BlockState state) { + flyingBlocks.add(new LaunchedBlock(target, state)); + Vec3d explosionPos = new Vec3d(pos).add(new Vec3d(target.subtract(pos)).normalize()); + this.world.createExplosion((Entity) null, explosionPos.x, explosionPos.y + 1.5f, explosionPos.z, 0, + Explosion.Mode.NONE); } } diff --git a/src/main/java/com/simibubi/create/gui/SchematicTableScreen.java b/src/main/java/com/simibubi/create/gui/SchematicTableScreen.java index 30332a0f2..4fb5b7406 100644 --- a/src/main/java/com/simibubi/create/gui/SchematicTableScreen.java +++ b/src/main/java/com/simibubi/create/gui/SchematicTableScreen.java @@ -2,7 +2,10 @@ package com.simibubi.create.gui; import java.util.List; +import org.lwjgl.opengl.GL11; + import com.mojang.blaze3d.platform.GlStateManager; +import com.simibubi.create.AllBlocks; import com.simibubi.create.Create; import com.simibubi.create.block.SchematicTableContainer; import com.simibubi.create.gui.widgets.AbstractSimiWidget; @@ -11,12 +14,19 @@ import com.simibubi.create.gui.widgets.OptionScrollArea; import com.simibubi.create.gui.widgets.ScrollArea; import com.simibubi.create.gui.widgets.SimiButton; +import net.minecraft.client.Minecraft; import net.minecraft.client.gui.IHasContainer; import net.minecraft.client.gui.screen.inventory.ContainerScreen; import net.minecraft.client.gui.widget.Widget; +import net.minecraft.client.renderer.BufferBuilder; +import net.minecraft.client.renderer.Tessellator; +import net.minecraft.client.renderer.texture.AtlasTexture; +import net.minecraft.client.renderer.vertex.DefaultVertexFormats; import net.minecraft.entity.player.PlayerInventory; +import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.MathHelper; import net.minecraft.util.text.ITextComponent; +import net.minecraftforge.client.model.data.EmptyModelData; public class SchematicTableScreen extends ContainerScreen implements IHasContainer { @@ -44,7 +54,7 @@ public class SchematicTableScreen extends ContainerScreenPx#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D02p*dSaefwW^{L9 za%BK;VQFr3E^cLXAT%y9E;jv63FrU-0ewkCK~y+TrIOD|0#OvkeUHqt66rsQNmMFX zive8(7A56K(ii<}L-j)*jylcn>s@=#QYe z{D9bS7@xs5p4Td<`zy!|9;3BVMRp*G@@x^8qgk|l4WuTbGJuLB#t>4DDDr~H8Z)K@ zo)&LdV`(POKsDDL(tS}>=dW=x8Iu8T>n()MA>8_lDA+|bJoh*<9iZ&|^r6Cr%1cy-u(C}z5=hGRS zTH@?9@_ew$A#>3%djO9MC48*D;8mz~rp+4&LY_oxO#r=@u1$mDr>G%3b^)k}64XrZ zqsW`IAi4mGTGE1O0(b#Q*+5c5dH|H<|GS>3hH7Hz*O$?yZ0w>eNjR_T}k O00000#LT=By}Z;C1rt3( zJ+r@loG*ZC)_S@)hFJJ7owQN#kO7bDW-d`%TLXqvF17_ttPu@n)m7X@=gaS_dr#xm zh|BSg*FP6KE$CGImE+%b)!FwKx9&Z9{q0UpjXm#|bM<~LdQow&@1YEfi0VeC=Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D02p*dSaefwW^{L9 za%BK;VQFr3E^cLXAT%y9E;jv63FrU-0VzpDK~y+Tb&$bI!$1^8=aU2%u5~Z?2ZG>6 z7g3CMXT%EPA_*9Yg&ITy;zFvB2?hiks!N=j<7`=P>c5w5BptR?_`R+eY&9JvN*juJ9wwLHy zs)vp=Ww_cC)(Ta|tN)34$uUjSL{Zdt^c>QFW+dbzY@jU5qA2K4 z1<1*=jHxydvjG;k;Xp#Tl!r@fz#mvu;n-W0#LT=By}Z;C1rt3( zJ+r@loG*ZCc6z!vhFJJ7on**$C_uoaSUa0v-~(IJ(yd!vtE@L}J&bT@Ers@;^^|uwX=eY$=I;+)w{&S7(Te<0fvl0*AVe0t)*F$QG%KF+I-G;Wt zdH+H)yBWA&Y+_(i6O^o6C|sas)TENs?82~YrPT_lZtjjf4j&k z6WqI$WozTy{&#F!8VentJpb*Za`G~R9;0~qX=Oo&-N{=wB<6|NaR0wz(;NRFvvKu- T{DX^uo?!5F^>bP0l+XkKs*HJ3 literal 0 HcmV?d00001