Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- package eu.lasersenigma.components;
- import eu.lasersenigma.Main;
- import eu.lasersenigma.areas.Area;
- import eu.lasersenigma.components.attributes.ComponentType;
- import eu.lasersenigma.components.attributes.DetectionMode;
- import eu.lasersenigma.components.attributes.ElevatorDirection;
- import eu.lasersenigma.components.parents.AComponent;
- import eu.lasersenigma.components.parents.IAreaComponent;
- import org.bukkit.Location;
- import eu.lasersenigma.components.parents.IDetectionComponent;
- import eu.lasersenigma.tasks.DefeatSoundTask;
- import eu.lasersenigma.tasks.VictorySoundTask;
- import java.util.ArrayList;
- import java.util.Arrays;
- import java.util.LinkedList;
- import java.util.List;
- import java.util.logging.Level;
- import java.util.stream.Collectors;
- import org.bukkit.Bukkit;
- import org.bukkit.Material;
- import org.bukkit.World;
- import org.bukkit.block.Block;
- import org.bukkit.block.BlockState;
- import org.bukkit.util.Vector;
- /**
- * A block that transforms itself in redstone block if enough laser receivers
- * are activated
- */
- public class Elevator extends AComponent implements IDetectionComponent, IAreaComponent {
- /**
- * the minimum number of [activated laser receivers | players inside the
- * area] needed to activate this component
- */
- private int min;
- /**
- * the maximum number of [activated laser receivers | players inside the
- * area] needed to activate this component
- */
- private int max;
- /**
- * The detection mode of the component ( number of activated laser receivers
- * or number of players inside the area)
- */
- private DetectionMode mode;
- /**
- * The actual number of (laser receivers activated | players inside the
- * area)
- */
- private int nbActivated;
- private Location cageCurrentMin;
- private final Vector cageVectorFromMinToMax;
- private final LinkedList<Location> floorsCageMin;
- private boolean moving;
- private ElevatorDirection movementDirection;
- private Integer moveTaskId;
- /**
- * Constructor used for creation from database
- *
- * @param area the area containing this elevator
- * @param componentId the id of the component inside the database
- * @param floorsCageMin ordered list of each floors locations
- * @param cageCurrentMin the current position of the elevator cage corner
- * with minimal coordinates.
- * @param cageVectorFromMinToMax the vector determining the position of the
- * cage corner with maximal coordinates from the cageCurrentMin location.
- * @param min The minimum number of activated laser receivers | players |
- * redstone sensors required to activate this elevator
- * @param max The maximum number of activated laser receivers | players |
- * redstone sensors required to make this block transform into a redstone
- * block
- * @param mode the detection mode
- */
- public Elevator(Area area, int componentId, List<Location> floorsCageMin, Location cageCurrentMin, Vector cageVectorFromMinToMax, int min, int max, DetectionMode mode) {
- super(area, componentId, floorsCageMin.get(0), ComponentType.ELEVATOR);
- this.min = min;
- this.max = max;
- this.nbActivated = -1;
- this.mode = mode;
- this.moving = false;
- this.cageCurrentMin = cageCurrentMin;
- this.floorsCageMin = new LinkedList<>(floorsCageMin);
- this.cageVectorFromMinToMax = cageVectorFromMinToMax;
- this.movementDirection = null;
- this.moveTaskId = null;
- }
- /**
- * Constructor
- *
- * @param area the area containing this elevator
- * @param minLoc the location of the elevator cage corner with minimal
- * coordinates.
- * @param maxLoc the location of the elevator cage corner with maximal
- * coordinates.
- */
- public Elevator(Area area, Location minLoc, Location maxLoc) {
- super(area, minLoc, ComponentType.ELEVATOR);
- this.min = 0;
- this.max = 10;
- this.nbActivated = -1;
- this.mode = DetectionMode.DETECTION_LASER_RECEIVERS;
- this.moving = false;
- this.cageCurrentMin = minLoc;
- this.floorsCageMin = new LinkedList<>(Arrays.asList(cageCurrentMin.clone()));
- this.cageVectorFromMinToMax = maxLoc.subtract(cageCurrentMin).toVector();
- this.movementDirection = null;
- this.moveTaskId = null;
- dbCreate();
- }
- public Location getShaftMinLocation() {
- return getGroundFloorMin();
- }
- @Override
- public Location getMinLocation() {
- return getShaftMinLocation();
- }
- public Location getShaftMaxLocation() {
- Location cageCurrentMax = getCageMax();
- Location topFloorMax = getTopFloorMax();
- return cageCurrentMax.getBlockY() > topFloorMax.getBlockY() ? cageCurrentMax : topFloorMax;
- }
- @Override
- public Location getMaxLocation() {
- return getShaftMaxLocation();
- }
- public Location getCageMin() {
- return cageCurrentMin.clone();
- }
- public LinkedList<Location> getFloorsCageMin() {
- return floorsCageMin;
- }
- public Location getCageMax() {
- return cageCurrentMin.clone().add(cageVectorFromMinToMax);
- }
- public Vector getCageVectorFromMinToMax() {
- return cageVectorFromMinToMax;
- }
- public int getGroundFloorIndex() {
- return 0;
- }
- public int getTopFloorIndex() {
- return floorsCageMin.size() - 1;
- }
- public Location getGroundFloorMin() {
- return floorsCageMin.getFirst().clone();
- }
- public Location getGroundFloorMax() {
- return floorsCageMin.getFirst().clone().add(cageVectorFromMinToMax);
- }
- public Location getTopFloorMin() {
- return floorsCageMin.getLast().clone();
- }
- public Location getTopFloorMax() {
- return floorsCageMin.getLast().clone().add(cageVectorFromMinToMax);
- }
- public boolean canGoDown() {
- return cageCurrentMin.getBlockY() > getShaftMinLocation().getBlockY();
- }
- public boolean canGoUp(boolean isEditingPuzzle) {
- boolean underHigherFloor = getTopFloorMax().getBlockY() > getCageMax().getBlockY();
- if (underHigherFloor) {
- return true;
- }
- if (!isEditingPuzzle) {
- return false;
- }
- //We are higher than the highest floor
- //Check max world height and if we are still inside the enigma area
- int y = cageCurrentMin.getBlockY() + cageVectorFromMinToMax.getBlockY() + 1;
- if (cageCurrentMin.getWorld().getMaxHeight() < y || getArea().getMaxLocation().getBlockY() < y) {
- return false;
- }
- int minX = cageCurrentMin.getBlockX();
- int minZ = cageCurrentMin.getBlockZ();
- int maxX = minX + cageVectorFromMinToMax.getBlockX();
- int maxZ = minZ + cageVectorFromMinToMax.getBlockZ();
- //Check if each of those areaToCheck blocks are air AND if there is no component here
- for (int x = minX; x <= maxX; x++) {
- for (int z = minZ; z <= maxZ; z++) {
- Location locToCheck = new Location(cageCurrentMin.getWorld(), x, y, z);
- if (!locToCheck.getBlock().isEmpty()) {
- return false;
- }
- if (getArea().getComponentFromLocation(locToCheck) != null) {
- return false;
- }
- }
- }
- return true;
- }
- public int getNearestFloorIndex(Location location) {
- int nearestFloorIndex = 0;
- Double nearestFloorDistance = null;
- for (int i = 0; i < floorsCageMin.size(); i++) {
- Vector cageVectorFromMinToCenter = new Vector(cageVectorFromMinToMax.getX() / 2, cageVectorFromMinToMax.getY() / 2, cageVectorFromMinToMax.getZ() / 2);
- Location floorCenter = floorsCageMin.get(i).clone().add(cageVectorFromMinToCenter);
- if (floorCenter.getWorld() != location.getWorld()) {
- continue;
- }
- double distance = floorCenter.distance(location);
- if (nearestFloorDistance == null || nearestFloorDistance > distance) {
- nearestFloorDistance = distance;
- nearestFloorIndex = i;
- }
- }
- return nearestFloorIndex;
- }
- public int getCurrentFloorIndex() {
- if (moving) {
- return -1;
- }
- for (int i = 0; i < floorsCageMin.size(); i++) {
- if (floorsCageMin.get(i).getBlockY() == cageCurrentMin.getBlockY()) {
- return i;
- }
- }
- return -1;
- }
- public int getPrevFloorIndex() {
- Integer maxIndexUnderCurrentLocation = -1;
- int currentY = cageCurrentMin.getBlockY();
- for (int i = 0; i < floorsCageMin.size(); i++) {
- if (floorsCageMin.get(i).getBlockY() < currentY) {
- maxIndexUnderCurrentLocation = Math.max(maxIndexUnderCurrentLocation, i);
- }
- }
- return maxIndexUnderCurrentLocation;
- }
- public int getNextFloorIndex() {
- Integer minIndexAboveCurrentLocation = null;
- int currentY = cageCurrentMin.getBlockY();
- for (int i = 0; i < floorsCageMin.size(); i++) {
- if (floorsCageMin.get(i).getBlockY() > currentY) {
- if (minIndexAboveCurrentLocation == null) {
- minIndexAboveCurrentLocation = i;
- } else {
- minIndexAboveCurrentLocation = Math.min(minIndexAboveCurrentLocation, i);
- }
- }
- }
- if (minIndexAboveCurrentLocation == null) {
- return -1;
- }
- return minIndexAboveCurrentLocation;
- }
- @SuppressWarnings("ResultOfObjectAllocationIgnored")
- public boolean onPlayerSneek(boolean isEditingPuzzle) {
- if (this.isActivated() || isEditingPuzzle) {
- if (moving) {
- if (isEditingPuzzle && this.movementDirection == ElevatorDirection.UP) {
- stopMoving();
- return true;
- }
- } else {
- if (canGoDown()) {
- moveToFloor(getPrevFloorIndex(), isEditingPuzzle);
- return true;
- }
- }
- return false;
- } else {
- new DefeatSoundTask(this.getArea(), this);
- return false;
- }
- }
- @SuppressWarnings("ResultOfObjectAllocationIgnored")
- public boolean onPlayerJump(boolean isEditingPuzzle) {
- Main.getInstance().getBetterLogger().log(Level.FINER, "onPlayerJump");
- if (this.isActivated() || isEditingPuzzle) {
- if (moving) {
- if (isEditingPuzzle && this.movementDirection == ElevatorDirection.DOWN) {
- stopMoving();
- return true;
- }
- } else {
- if (canGoUp(isEditingPuzzle)) {
- boolean underHigherFloor = getTopFloorMax().getBlockY() > getCageMax().getBlockY();
- if (underHigherFloor) {
- return moveToFloor(getNextFloorIndex(), isEditingPuzzle);
- } else {
- moveSingleStep(1, false);
- return true;
- }
- }
- }
- return false;
- } else {
- new DefeatSoundTask(this.getArea(), this);
- return false;
- }
- }
- @SuppressWarnings("ResultOfObjectAllocationIgnored")
- public boolean onCallButtonPushed(CallButton callButton, boolean isEditingPuzzle) {
- if (callButton.getElevator() != this || !getArea().isActivated()) {
- return false;
- }
- if (!isActivated() && !isEditingPuzzle) {
- new DefeatSoundTask(this.getArea(), callButton);
- return false;
- }
- Location buttonLocation = callButton.getLocation();
- int floorIndex = getNearestFloorIndex(buttonLocation);
- return moveToFloor(floorIndex, isEditingPuzzle);
- }
- public boolean moveToFloor(int floorIndex, boolean isInEditionMode) {
- if (moving || !getArea().isActivated() || (!isActivated() && !isInEditionMode)) {
- return false;
- }
- if (floorIndex < 0) {
- return false;
- }
- if (floorIndex >= floorsCageMin.size()) {
- return false;
- }
- if (getCurrentFloorIndex() == floorIndex) {
- return false;
- }
- int yDiff = (floorsCageMin.get(floorIndex).getBlockY() - cageCurrentMin.getBlockY());
- moveSingleStep(yDiff);
- return true;
- }
- private void moveSingleStep(int yDiff) {
- moveSingleStep(yDiff, true);
- }
- @SuppressWarnings("ResultOfObjectAllocationIgnored")
- private void moveSingleStep(int yDiff, boolean playSound) {
- int newYDiff;
- if (yDiff == 0 || !getArea().isActivated() || !isActivated()) {
- //Stop movement
- stopMoving();
- //Update database
- dbUpdate();
- return;
- }
- //Start movement
- moving = true;
- int y = 0;
- int yEnd = 0;
- int yIncrementor = 0;
- if (yDiff > 0) {
- movementDirection = ElevatorDirection.UP;
- yIncrementor = -1;
- y = getCageMax().getBlockY();
- yEnd = cageCurrentMin.getBlockY();
- } else if (yDiff < 0) {
- movementDirection = ElevatorDirection.DOWN;
- yIncrementor = +1;
- y = cageCurrentMin.getBlockY();
- yEnd = getCageMax().getBlockY();
- }
- World w = cageCurrentMin.getWorld();
- int minX = cageCurrentMin.getBlockX();
- int minY = cageCurrentMin.getBlockY();
- int minZ = cageCurrentMin.getBlockZ();
- int maxX = getCageMax().getBlockX();
- int maxY = getCageMax().getBlockY();
- int maxZ = getCageMax().getBlockZ();
- //Move entities inside
- w.getEntities().forEach((e) -> {
- Location eLoc = e.getLocation();
- int eX = eLoc.getBlockX();
- int eY = eLoc.getBlockY();
- int eZ = eLoc.getBlockZ();
- if (minX <= eX && eX <= maxX && minY <= eY && eY <= maxY && minZ <= eZ && eZ <= maxZ) {
- e.teleport(eLoc.add(movementDirection.getVector()));
- }
- });
- //Move block
- for (; (movementDirection == ElevatorDirection.UP ? y >= yEnd : y <= yEnd); y += yIncrementor) {
- for (int x = minX; x <= maxX; x++) {
- for (int z = minZ; z <= maxZ; z++) {
- Block bFrom = w.getBlockAt(x, y, z);
- Block bTo = w.getBlockAt(x, y + ((movementDirection == ElevatorDirection.UP) ? 1 : -1), z);
- bTo.setType(bFrom.getType());
- BlockState toState = bTo.getState();
- toState.setType(bFrom.getType());
- toState.setData(bFrom.getState().getData());
- toState.update();
- if (y == yEnd) {
- bFrom.setType(Material.AIR);
- bFrom.getState().update();
- }
- }
- }
- }
- //update cageCurrentMin
- this.cageCurrentMin = cageCurrentMin.add(movementDirection.getVector());
- //Play sound if we reached the aimed position
- newYDiff = yDiff + yIncrementor;
- if (newYDiff == 0 && playSound) {
- new VictorySoundTask(getArea(),this);
- stopMoving();
- //Update database
- dbUpdate();
- return;
- }
- //Restart recursivly with some delay
- moveTaskId = Bukkit.getScheduler().runTaskLater(Main.getInstance(), () -> {
- moveSingleStep(newYDiff, playSound);
- }, 7).getTaskId();
- }
- private void stopMoving() {
- if (moveTaskId != null) {
- Bukkit.getScheduler().cancelTask(moveTaskId);
- moveTaskId = null;
- }
- movementDirection = null;
- moving = false;
- }
- public boolean addFloorAtCurrentPosition() {
- if (getCurrentFloorIndex() != -1) {
- return false;
- }
- floorsCageMin.add(getPrevFloorIndex() + 1, cageCurrentMin.clone());
- dbUpdate();
- return true;
- }
- public ArrayList<CallButton> getCallButtons() {
- return getArea().getComponents().stream()
- .filter(c -> c instanceof CallButton)
- .map(c -> ((CallButton) c))
- .filter(c -> c.getElevator() == this)
- .collect(Collectors.toCollection(ArrayList::new));
- }
- @Override
- public int getMin() {
- return min;
- }
- @Override
- public void setMin(int min) {
- this.min = min;
- dbUpdate();
- }
- @Override
- public int getMax() {
- return max;
- }
- @Override
- public void setMax(int max) {
- this.max = max;
- dbUpdate();
- }
- @Override
- public void changeMode(DetectionMode mode) {
- if (mode.isSpecificToLaserSender()) {
- throw new UnsupportedOperationException();
- }
- this.mode = mode;
- dbUpdate();
- }
- @Override
- public DetectionMode getMode() {
- return mode;
- }
- @Override
- public boolean isActivated() {
- return (this.min <= this.nbActivated && this.nbActivated <= this.max);
- }
- /**
- * sets the current number of laser receivers activated
- *
- * @param nbActivated the current number of laser receivers activated
- */
- @Override
- public void setNbActivated(int nbActivated) {
- if (nbActivated != this.nbActivated) {
- this.nbActivated = nbActivated;
- updateDisplay();
- }
- }
- /**
- * resets this winner block
- */
- @Override
- public void reset() {
- this.nbActivated = 0;
- stopMoving();
- }
- /**
- * updates this winner block
- */
- @Override
- public void updateDisplay() {
- }
- @Override
- public void hide() {
- }
- /**
- * Removes the component from the database
- */
- @Override
- public void remove() {
- ArrayList<CallButton> callButtons = getArea().getComponents().stream()
- .filter(component -> component instanceof CallButton)
- .map(component -> (CallButton) component)
- .filter(callButton -> callButton.getElevator() == this)
- .collect(Collectors.toCollection(ArrayList::new));
- callButtons.forEach((callButton) -> {
- getArea().removeComponent(callButton);
- });
- hide();
- dbRemove();
- }
- public void goAsHighAsPossible() {
- while (canGoUp(true)) {
- moveSingleStep(1, false);
- }
- }
- public void clearFloors() {
- while (floorsCageMin.size() > 1) {
- floorsCageMin.removeLast();
- }
- dbUpdate();
- }
- public Location getCageCenter() {
- Vector cageVectorFromMinToCenter = new Vector(cageVectorFromMinToMax.getX() / 2, cageVectorFromMinToMax.getY() / 2, cageVectorFromMinToMax.getZ() / 2);
- return getCageMin().clone().add(cageVectorFromMinToCenter);
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement