package com.amadornes.framez.movement; import java.util.ArrayList; import java.util.List; import net.minecraft.entity.Entity; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.util.AxisAlignedBB; import net.minecraft.world.World; import uk.co.qmunity.lib.vec.Vec3d; import com.amadornes.framez.api.movement.IMovement; import com.amadornes.framez.api.movement.IMovingBlock; import com.amadornes.framez.api.movement.IMovingStructure; import com.amadornes.framez.network.NetworkHandler; import com.amadornes.framez.network.PacketBlockSync; import com.amadornes.framez.network.PacketStartMoving; import com.amadornes.framez.tile.TileMotor; import com.amadornes.framez.world.FakeWorld; import cpw.mods.fml.common.gameevent.TickEvent.Phase; public class MovingStructure implements IMovingStructure { private TileMotor motor; private IMovement movement; private List<IMovingBlock> blocks = new ArrayList<IMovingBlock>(); private double progress = 0, speed = 1; public MovingStructure(TileMotor motor, IMovement movement, double speed) { this.motor = motor; this.movement = movement; this.speed = speed; } public MovingStructure(TileMotor motor, IMovement movement, double speed, List<MovingBlock> blocks) { this(motor, movement, speed); this.blocks.addAll(blocks); for (MovingBlock b : blocks) b.setStructure(this); } @Override public World getWorld() { return motor.getWorld(); } @Override public List<IMovingBlock> getBlocks() { return blocks; } public MovingBlock getBlock(int x, int y, int z) { for (IMovingBlock b : getBlocks()) if (b.getX() == x && b.getY() == y && b.getZ() == z) return (MovingBlock) b; return null; } @Override public IMovement getMovement() { return movement; } public void addBlock(MovingBlock block) { blocks.add(block); block.setStructure(this); } @Override public double getProgress() { return progress;// Math.min(progress, 1); } @Override public double getInterpolatedProgress(double frame) { return Math.max(Math.min(((progress / getSpeed()) * (1 / (1 / getSpeed() - 1.75))) + (getSpeed() * frame) - getSpeed(), 1), 0); } public void setProgress(double progress) { this.progress = progress; } public double getSpeed() { return speed; } private void startMoving() { for (IMovingBlock bl : blocks) ((MovingBlock) bl).remove(); for (IMovingBlock bl : blocks) ((MovingBlock) bl).notifyRemoval(); } private void finishMoving() { for (IMovingBlock bl : blocks) ((MovingBlock) bl).place(); for (IMovingBlock bl : blocks) ((MovingBlock) bl).notifyPlacement(); } public void tick(Phase phase) { FakeWorld.getFakeWorld(this); if (progress >= 1) return; if (phase == Phase.END) { if (progress == 0) { if (!getWorld().isRemote) NetworkHandler.instance().sendToAllAround(new PacketStartMoving(motor, this), getWorld(), 128); startMoving(); if (!getWorld().isRemote) NetworkHandler.instance().sendToAllAround(new PacketBlockSync(motor, this), getWorld(), 128); } progress += speed; moveEntities(); if (progress >= 1) finishMoving(); } } @SuppressWarnings({ "rawtypes", "unchecked" }) private void moveEntities() { IMovement m = getMovement(); List<Entity> entities = new ArrayList<Entity>(); for (IMovingBlock mb : getBlocks()) { MovingBlock b = (MovingBlock) mb; List aabbs = new ArrayList(); try { b.getBlock().addCollisionBoxesToList(FakeWorld.getFakeWorld(this), b.getX(), b.getY(), b.getZ(), AxisAlignedBB.getBoundingBox(b.getX(), b.getY(), b.getZ(), b.getX() + 1, b.getY() + 1, b.getZ() + 1), aabbs, null); } catch (Exception ex) { aabbs.add(AxisAlignedBB.getBoundingBox(b.getX(), b.getY(), b.getZ(), b.getX() + 1, b.getY() + 1, b.getZ() + 1)); } for (Object o : aabbs) { AxisAlignedBB aabb = ((AxisAlignedBB) o); if (aabb == null) continue; aabb = aabb.copy(); // Translate { Vec3d min = m.transform(new Vec3d(aabb.minX, aabb.minY, aabb.minZ), getProgress()); Vec3d max = m.transform(new Vec3d(aabb.maxX, aabb.maxY, aabb.maxZ), getProgress()); aabb.minX = min.getX(); aabb.minY = min.getY(); aabb.minZ = min.getZ(); aabb.maxX = max.getX(); aabb.maxY = max.getY(); aabb.maxZ = max.getZ(); } aabb.maxY += 0.25; aabb.minX -= 0.25; aabb.minZ -= 0.25; aabb.maxX += 0.25; aabb.maxZ += 0.25; for (Object o2 : getWorld().getEntitiesWithinAABB(Entity.class, aabb)) { if (!entities.contains(o2)) { entities.add((Entity) o2); } } } } for (Entity e : entities) { Vec3d pos = m.transform(new Vec3d(e.posX, e.posY, e.posZ), getProgress()); if (pos.getY() >= e.posY) { try { moveEntity(e); } catch (Exception ex) { } } } } private void moveEntity(Entity entity) { Vec3d pos = getMovement().transform(new Vec3d(entity.posX, entity.posY, entity.posZ), 1).clone() .sub(new Vec3d(entity.posX, entity.posY, entity.posZ)).mul(1 / (1 / getSpeed() - 1)); pos.setY(Math.max(pos.getY(), 0)); entity.motionY = Math.max(entity.motionY, 0) + pos.getY(); if (!(entity instanceof EntityPlayer) || !(entity.isSneaking())) entity.moveEntity(pos.getX(), 0, pos.getZ()); entity.onGround = true; entity.fallDistance = 0; } @Override public String toString() { return "MovingStructure [world=" + getWorld() + ", blocks=" + blocks + ", progress=" + progress + "]"; } public TileMotor getMotor() { return motor; } }