Advertisement
Guest User

elevator

a guest
Oct 21st, 2019
105
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 19.39 KB | None | 0 0
  1. package eu.lasersenigma.components;
  2.  
  3. import eu.lasersenigma.Main;
  4. import eu.lasersenigma.areas.Area;
  5. import eu.lasersenigma.components.attributes.ComponentType;
  6. import eu.lasersenigma.components.attributes.DetectionMode;
  7. import eu.lasersenigma.components.attributes.ElevatorDirection;
  8. import eu.lasersenigma.components.parents.AComponent;
  9. import eu.lasersenigma.components.parents.IAreaComponent;
  10. import org.bukkit.Location;
  11. import eu.lasersenigma.components.parents.IDetectionComponent;
  12. import eu.lasersenigma.tasks.DefeatSoundTask;
  13. import eu.lasersenigma.tasks.VictorySoundTask;
  14. import java.util.ArrayList;
  15. import java.util.Arrays;
  16. import java.util.LinkedList;
  17. import java.util.List;
  18. import java.util.logging.Level;
  19. import java.util.stream.Collectors;
  20. import org.bukkit.Bukkit;
  21. import org.bukkit.Material;
  22. import org.bukkit.World;
  23. import org.bukkit.block.Block;
  24. import org.bukkit.block.BlockState;
  25. import org.bukkit.util.Vector;
  26.  
  27. /**
  28.  * A block that transforms itself in redstone block if enough laser receivers
  29.  * are activated
  30.  */
  31. public class Elevator extends AComponent implements IDetectionComponent, IAreaComponent {
  32.  
  33.     /**
  34.      * the minimum number of [activated laser receivers | players inside the
  35.      * area] needed to activate this component
  36.      */
  37.     private int min;
  38.  
  39.     /**
  40.      * the maximum number of [activated laser receivers | players inside the
  41.      * area] needed to activate this component
  42.      */
  43.     private int max;
  44.  
  45.     /**
  46.      * The detection mode of the component ( number of activated laser receivers
  47.      * or number of players inside the area)
  48.      */
  49.     private DetectionMode mode;
  50.  
  51.     /**
  52.      * The actual number of (laser receivers activated | players inside the
  53.      * area)
  54.      */
  55.     private int nbActivated;
  56.  
  57.     private Location cageCurrentMin;
  58.  
  59.     private final Vector cageVectorFromMinToMax;
  60.  
  61.     private final LinkedList<Location> floorsCageMin;
  62.  
  63.     private boolean moving;
  64.  
  65.     private ElevatorDirection movementDirection;
  66.  
  67.     private Integer moveTaskId;
  68.  
  69.     /**
  70.      * Constructor used for creation from database
  71.      *
  72.      * @param area the area containing this elevator
  73.      * @param componentId the id of the component inside the database
  74.      * @param floorsCageMin ordered list of each floors locations
  75.      * @param cageCurrentMin the current position of the elevator cage corner
  76.      * with minimal coordinates.
  77.      * @param cageVectorFromMinToMax the vector determining the position of the
  78.      * cage corner with maximal coordinates from the cageCurrentMin location.
  79.      * @param min The minimum number of activated laser receivers | players |
  80.      * redstone sensors required to activate this elevator
  81.      * @param max The maximum number of activated laser receivers | players |
  82.      * redstone sensors required to make this block transform into a redstone
  83.      * block
  84.      * @param mode the detection mode
  85.      */
  86.     public Elevator(Area area, int componentId, List<Location> floorsCageMin, Location cageCurrentMin, Vector cageVectorFromMinToMax, int min, int max, DetectionMode mode) {
  87.         super(area, componentId, floorsCageMin.get(0), ComponentType.ELEVATOR);
  88.         this.min = min;
  89.         this.max = max;
  90.         this.nbActivated = -1;
  91.         this.mode = mode;
  92.         this.moving = false;
  93.         this.cageCurrentMin = cageCurrentMin;
  94.         this.floorsCageMin = new LinkedList<>(floorsCageMin);
  95.         this.cageVectorFromMinToMax = cageVectorFromMinToMax;
  96.         this.movementDirection = null;
  97.         this.moveTaskId = null;
  98.     }
  99.  
  100.     /**
  101.      * Constructor
  102.      *
  103.      * @param area the area containing this elevator
  104.      * @param minLoc the location of the elevator cage corner with minimal
  105.      * coordinates.
  106.      * @param maxLoc the location of the elevator cage corner with maximal
  107.      * coordinates.
  108.      */
  109.     public Elevator(Area area, Location minLoc, Location maxLoc) {
  110.         super(area, minLoc, ComponentType.ELEVATOR);
  111.         this.min = 0;
  112.         this.max = 10;
  113.         this.nbActivated = -1;
  114.         this.mode = DetectionMode.DETECTION_LASER_RECEIVERS;
  115.         this.moving = false;
  116.         this.cageCurrentMin = minLoc;
  117.         this.floorsCageMin = new LinkedList<>(Arrays.asList(cageCurrentMin.clone()));
  118.         this.cageVectorFromMinToMax = maxLoc.subtract(cageCurrentMin).toVector();
  119.         this.movementDirection = null;
  120.         this.moveTaskId = null;
  121.         dbCreate();
  122.     }
  123.  
  124.     public Location getShaftMinLocation() {
  125.         return getGroundFloorMin();
  126.     }
  127.  
  128.     @Override
  129.     public Location getMinLocation() {
  130.         return getShaftMinLocation();
  131.     }
  132.  
  133.     public Location getShaftMaxLocation() {
  134.  
  135.         Location cageCurrentMax = getCageMax();
  136.         Location topFloorMax = getTopFloorMax();
  137.  
  138.         return cageCurrentMax.getBlockY() > topFloorMax.getBlockY() ? cageCurrentMax : topFloorMax;
  139.     }
  140.  
  141.     @Override
  142.     public Location getMaxLocation() {
  143.         return getShaftMaxLocation();
  144.     }
  145.  
  146.     public Location getCageMin() {
  147.         return cageCurrentMin.clone();
  148.     }
  149.  
  150.     public LinkedList<Location> getFloorsCageMin() {
  151.         return floorsCageMin;
  152.     }
  153.  
  154.     public Location getCageMax() {
  155.         return cageCurrentMin.clone().add(cageVectorFromMinToMax);
  156.     }
  157.  
  158.     public Vector getCageVectorFromMinToMax() {
  159.         return cageVectorFromMinToMax;
  160.     }
  161.  
  162.     public int getGroundFloorIndex() {
  163.         return 0;
  164.     }
  165.  
  166.     public int getTopFloorIndex() {
  167.         return floorsCageMin.size() - 1;
  168.     }
  169.  
  170.     public Location getGroundFloorMin() {
  171.         return floorsCageMin.getFirst().clone();
  172.     }
  173.  
  174.     public Location getGroundFloorMax() {
  175.         return floorsCageMin.getFirst().clone().add(cageVectorFromMinToMax);
  176.     }
  177.  
  178.     public Location getTopFloorMin() {
  179.         return floorsCageMin.getLast().clone();
  180.     }
  181.  
  182.     public Location getTopFloorMax() {
  183.         return floorsCageMin.getLast().clone().add(cageVectorFromMinToMax);
  184.     }
  185.  
  186.     public boolean canGoDown() {
  187.         return cageCurrentMin.getBlockY() > getShaftMinLocation().getBlockY();
  188.     }
  189.  
  190.     public boolean canGoUp(boolean isEditingPuzzle) {
  191.         boolean underHigherFloor = getTopFloorMax().getBlockY() > getCageMax().getBlockY();
  192.         if (underHigherFloor) {
  193.             return true;
  194.         }
  195.         if (!isEditingPuzzle) {
  196.             return false;
  197.         }
  198.  
  199.         //We are higher than the highest floor
  200.         //Check max world height and if we are still inside the enigma area
  201.         int y = cageCurrentMin.getBlockY() + cageVectorFromMinToMax.getBlockY() + 1;
  202.         if (cageCurrentMin.getWorld().getMaxHeight() < y || getArea().getMaxLocation().getBlockY() < y) {
  203.             return false;
  204.         }
  205.         int minX = cageCurrentMin.getBlockX();
  206.         int minZ = cageCurrentMin.getBlockZ();
  207.         int maxX = minX + cageVectorFromMinToMax.getBlockX();
  208.         int maxZ = minZ + cageVectorFromMinToMax.getBlockZ();
  209.         //Check if each of those areaToCheck blocks are air AND if there is no component here
  210.         for (int x = minX; x <= maxX; x++) {
  211.             for (int z = minZ; z <= maxZ; z++) {
  212.                 Location locToCheck = new Location(cageCurrentMin.getWorld(), x, y, z);
  213.                 if (!locToCheck.getBlock().isEmpty()) {
  214.                     return false;
  215.                 }
  216.                 if (getArea().getComponentFromLocation(locToCheck) != null) {
  217.                     return false;
  218.                 }
  219.             }
  220.         }
  221.         return true;
  222.     }
  223.  
  224.     public int getNearestFloorIndex(Location location) {
  225.         int nearestFloorIndex = 0;
  226.         Double nearestFloorDistance = null;
  227.  
  228.         for (int i = 0; i < floorsCageMin.size(); i++) {
  229.             Vector cageVectorFromMinToCenter = new Vector(cageVectorFromMinToMax.getX() / 2, cageVectorFromMinToMax.getY() / 2, cageVectorFromMinToMax.getZ() / 2);
  230.             Location floorCenter = floorsCageMin.get(i).clone().add(cageVectorFromMinToCenter);
  231.             if (floorCenter.getWorld() != location.getWorld()) {
  232.                 continue;
  233.             }
  234.             double distance = floorCenter.distance(location);
  235.             if (nearestFloorDistance == null || nearestFloorDistance > distance) {
  236.                 nearestFloorDistance = distance;
  237.                 nearestFloorIndex = i;
  238.             }
  239.         }
  240.         return nearestFloorIndex;
  241.     }
  242.  
  243.     public int getCurrentFloorIndex() {
  244.         if (moving) {
  245.             return -1;
  246.         }
  247.         for (int i = 0; i < floorsCageMin.size(); i++) {
  248.             if (floorsCageMin.get(i).getBlockY() == cageCurrentMin.getBlockY()) {
  249.                 return i;
  250.             }
  251.         }
  252.         return -1;
  253.     }
  254.  
  255.     public int getPrevFloorIndex() {
  256.         Integer maxIndexUnderCurrentLocation = -1;
  257.         int currentY = cageCurrentMin.getBlockY();
  258.         for (int i = 0; i < floorsCageMin.size(); i++) {
  259.             if (floorsCageMin.get(i).getBlockY() < currentY) {
  260.                 maxIndexUnderCurrentLocation = Math.max(maxIndexUnderCurrentLocation, i);
  261.             }
  262.         }
  263.         return maxIndexUnderCurrentLocation;
  264.     }
  265.  
  266.     public int getNextFloorIndex() {
  267.         Integer minIndexAboveCurrentLocation = null;
  268.         int currentY = cageCurrentMin.getBlockY();
  269.         for (int i = 0; i < floorsCageMin.size(); i++) {
  270.             if (floorsCageMin.get(i).getBlockY() > currentY) {
  271.                 if (minIndexAboveCurrentLocation == null) {
  272.                     minIndexAboveCurrentLocation = i;
  273.                 } else {
  274.                     minIndexAboveCurrentLocation = Math.min(minIndexAboveCurrentLocation, i);
  275.                 }
  276.             }
  277.         }
  278.         if (minIndexAboveCurrentLocation == null) {
  279.             return -1;
  280.         }
  281.         return minIndexAboveCurrentLocation;
  282.     }
  283.  
  284.     @SuppressWarnings("ResultOfObjectAllocationIgnored")
  285.     public boolean onPlayerSneek(boolean isEditingPuzzle) {
  286.         if (this.isActivated() || isEditingPuzzle) {
  287.             if (moving) {
  288.                 if (isEditingPuzzle && this.movementDirection == ElevatorDirection.UP) {
  289.                     stopMoving();
  290.                     return true;
  291.                 }
  292.             } else {
  293.                 if (canGoDown()) {
  294.                     moveToFloor(getPrevFloorIndex(), isEditingPuzzle);
  295.                     return true;
  296.                 }
  297.             }
  298.             return false;
  299.         } else {
  300.             new DefeatSoundTask(this.getArea(), this);
  301.             return false;
  302.         }
  303.     }
  304.  
  305.     @SuppressWarnings("ResultOfObjectAllocationIgnored")
  306.     public boolean onPlayerJump(boolean isEditingPuzzle) {
  307.         Main.getInstance().getBetterLogger().log(Level.FINER, "onPlayerJump");
  308.         if (this.isActivated() || isEditingPuzzle) {
  309.             if (moving) {
  310.                 if (isEditingPuzzle && this.movementDirection == ElevatorDirection.DOWN) {
  311.                     stopMoving();
  312.                     return true;
  313.                 }
  314.             } else {
  315.                 if (canGoUp(isEditingPuzzle)) {
  316.                     boolean underHigherFloor = getTopFloorMax().getBlockY() > getCageMax().getBlockY();
  317.                     if (underHigherFloor) {
  318.                         return moveToFloor(getNextFloorIndex(), isEditingPuzzle);
  319.                     } else {
  320.                         moveSingleStep(1, false);
  321.                         return true;
  322.                     }
  323.                 }
  324.             }
  325.             return false;
  326.         } else {
  327.             new DefeatSoundTask(this.getArea(), this);
  328.             return false;
  329.         }
  330.     }
  331.  
  332.     @SuppressWarnings("ResultOfObjectAllocationIgnored")
  333.     public boolean onCallButtonPushed(CallButton callButton, boolean isEditingPuzzle) {
  334.         if (callButton.getElevator() != this || !getArea().isActivated()) {
  335.             return false;
  336.         }
  337.         if (!isActivated() && !isEditingPuzzle) {
  338.             new DefeatSoundTask(this.getArea(), callButton);
  339.             return false;
  340.         }
  341.         Location buttonLocation = callButton.getLocation();
  342.         int floorIndex = getNearestFloorIndex(buttonLocation);
  343.         return moveToFloor(floorIndex, isEditingPuzzle);
  344.     }
  345.  
  346.     public boolean moveToFloor(int floorIndex, boolean isInEditionMode) {
  347.         if (moving || !getArea().isActivated() || (!isActivated() && !isInEditionMode)) {
  348.             return false;
  349.         }
  350.         if (floorIndex < 0) {
  351.             return false;
  352.         }
  353.         if (floorIndex >= floorsCageMin.size()) {
  354.             return false;
  355.         }
  356.         if (getCurrentFloorIndex() == floorIndex) {
  357.             return false;
  358.         }
  359.         int yDiff = (floorsCageMin.get(floorIndex).getBlockY() - cageCurrentMin.getBlockY());
  360.         moveSingleStep(yDiff);
  361.         return true;
  362.     }
  363.  
  364.     private void moveSingleStep(int yDiff) {
  365.         moveSingleStep(yDiff, true);
  366.     }
  367.  
  368.     @SuppressWarnings("ResultOfObjectAllocationIgnored")
  369.     private void moveSingleStep(int yDiff, boolean playSound) {
  370.         int newYDiff;
  371.         if (yDiff == 0 || !getArea().isActivated() || !isActivated()) {
  372.             //Stop movement
  373.             stopMoving();
  374.             //Update database
  375.             dbUpdate();
  376.             return;
  377.         }
  378.         //Start movement
  379.         moving = true;
  380.         int y = 0;
  381.         int yEnd = 0;
  382.         int yIncrementor = 0;
  383.         if (yDiff > 0) {
  384.             movementDirection = ElevatorDirection.UP;
  385.             yIncrementor = -1;
  386.             y = getCageMax().getBlockY();
  387.             yEnd = cageCurrentMin.getBlockY();
  388.  
  389.         } else if (yDiff < 0) {
  390.             movementDirection = ElevatorDirection.DOWN;
  391.             yIncrementor = +1;
  392.             y = cageCurrentMin.getBlockY();
  393.             yEnd = getCageMax().getBlockY();
  394.         }
  395.  
  396.         World w = cageCurrentMin.getWorld();
  397.  
  398.         int minX = cageCurrentMin.getBlockX();
  399.         int minY = cageCurrentMin.getBlockY();
  400.         int minZ = cageCurrentMin.getBlockZ();
  401.         int maxX = getCageMax().getBlockX();
  402.         int maxY = getCageMax().getBlockY();
  403.         int maxZ = getCageMax().getBlockZ();
  404.  
  405.         //Move entities inside
  406.         w.getEntities().forEach((e) -> {
  407.             Location eLoc = e.getLocation();
  408.             int eX = eLoc.getBlockX();
  409.             int eY = eLoc.getBlockY();
  410.             int eZ = eLoc.getBlockZ();
  411.             if (minX <= eX && eX <= maxX && minY <= eY && eY <= maxY && minZ <= eZ && eZ <= maxZ) {
  412.                 e.teleport(eLoc.add(movementDirection.getVector()));
  413.             }
  414.         });
  415.  
  416.         //Move block
  417.         for (; (movementDirection == ElevatorDirection.UP ? y >= yEnd : y <= yEnd); y += yIncrementor) {
  418.             for (int x = minX; x <= maxX; x++) {
  419.                 for (int z = minZ; z <= maxZ; z++) {
  420.                     Block bFrom = w.getBlockAt(x, y, z);
  421.                     Block bTo = w.getBlockAt(x, y + ((movementDirection == ElevatorDirection.UP) ? 1 : -1), z);
  422.                     bTo.setType(bFrom.getType());
  423.                     BlockState toState = bTo.getState();
  424.                     toState.setType(bFrom.getType());
  425.                     toState.setData(bFrom.getState().getData());
  426.                     toState.update();
  427.                     if (y == yEnd) {
  428.                         bFrom.setType(Material.AIR);
  429.                         bFrom.getState().update();
  430.                     }
  431.                 }
  432.             }
  433.         }
  434.  
  435.         //update cageCurrentMin
  436.         this.cageCurrentMin = cageCurrentMin.add(movementDirection.getVector());
  437.  
  438.         //Play sound if we reached the aimed position
  439.         newYDiff = yDiff + yIncrementor;
  440.         if (newYDiff == 0 && playSound) {
  441.             new VictorySoundTask(getArea(),this);
  442.             stopMoving();
  443.             //Update database
  444.             dbUpdate();
  445.             return;
  446.         }
  447.  
  448.         //Restart recursivly with some delay
  449.         moveTaskId = Bukkit.getScheduler().runTaskLater(Main.getInstance(), () -> {
  450.             moveSingleStep(newYDiff, playSound);
  451.         }, 7).getTaskId();
  452.  
  453.     }
  454.  
  455.     private void stopMoving() {
  456.         if (moveTaskId != null) {
  457.             Bukkit.getScheduler().cancelTask(moveTaskId);
  458.             moveTaskId = null;
  459.         }
  460.         movementDirection = null;
  461.         moving = false;
  462.     }
  463.  
  464.     public boolean addFloorAtCurrentPosition() {
  465.         if (getCurrentFloorIndex() != -1) {
  466.             return false;
  467.         }
  468.         floorsCageMin.add(getPrevFloorIndex() + 1, cageCurrentMin.clone());
  469.         dbUpdate();
  470.         return true;
  471.     }
  472.  
  473.     public ArrayList<CallButton> getCallButtons() {
  474.         return getArea().getComponents().stream()
  475.                 .filter(c -> c instanceof CallButton)
  476.                 .map(c -> ((CallButton) c))
  477.                 .filter(c -> c.getElevator() == this)
  478.                 .collect(Collectors.toCollection(ArrayList::new));
  479.  
  480.     }
  481.  
  482.     @Override
  483.     public int getMin() {
  484.         return min;
  485.     }
  486.  
  487.     @Override
  488.     public void setMin(int min) {
  489.         this.min = min;
  490.         dbUpdate();
  491.     }
  492.  
  493.     @Override
  494.     public int getMax() {
  495.         return max;
  496.     }
  497.  
  498.     @Override
  499.     public void setMax(int max) {
  500.         this.max = max;
  501.         dbUpdate();
  502.     }
  503.  
  504.     @Override
  505.     public void changeMode(DetectionMode mode) {
  506.         if (mode.isSpecificToLaserSender()) {
  507.             throw new UnsupportedOperationException();
  508.         }
  509.         this.mode = mode;
  510.         dbUpdate();
  511.     }
  512.  
  513.     @Override
  514.     public DetectionMode getMode() {
  515.         return mode;
  516.     }
  517.  
  518.     @Override
  519.     public boolean isActivated() {
  520.         return (this.min <= this.nbActivated && this.nbActivated <= this.max);
  521.     }
  522.  
  523.     /**
  524.      * sets the current number of laser receivers activated
  525.      *
  526.      * @param nbActivated the current number of laser receivers activated
  527.      */
  528.     @Override
  529.     public void setNbActivated(int nbActivated) {
  530.         if (nbActivated != this.nbActivated) {
  531.             this.nbActivated = nbActivated;
  532.             updateDisplay();
  533.         }
  534.  
  535.     }
  536.  
  537.     /**
  538.      * resets this winner block
  539.      */
  540.     @Override
  541.     public void reset() {
  542.         this.nbActivated = 0;
  543.         stopMoving();
  544.     }
  545.  
  546.     /**
  547.      * updates this winner block
  548.      */
  549.     @Override
  550.     public void updateDisplay() {
  551.     }
  552.  
  553.     @Override
  554.     public void hide() {
  555.     }
  556.  
  557.     /**
  558.      * Removes the component from the database
  559.      */
  560.     @Override
  561.     public void remove() {
  562.         ArrayList<CallButton> callButtons = getArea().getComponents().stream()
  563.                 .filter(component -> component instanceof CallButton)
  564.                 .map(component -> (CallButton) component)
  565.                 .filter(callButton -> callButton.getElevator() == this)
  566.                 .collect(Collectors.toCollection(ArrayList::new));
  567.         callButtons.forEach((callButton) -> {
  568.             getArea().removeComponent(callButton);
  569.         });
  570.         hide();
  571.         dbRemove();
  572.     }
  573.  
  574.     public void goAsHighAsPossible() {
  575.         while (canGoUp(true)) {
  576.             moveSingleStep(1, false);
  577.         }
  578.     }
  579.  
  580.     public void clearFloors() {
  581.         while (floorsCageMin.size() > 1) {
  582.             floorsCageMin.removeLast();
  583.         }
  584.         dbUpdate();
  585.     }
  586.  
  587.     public Location getCageCenter() {
  588.         Vector cageVectorFromMinToCenter = new Vector(cageVectorFromMinToMax.getX() / 2, cageVectorFromMinToMax.getY() / 2, cageVectorFromMinToMax.getZ() / 2);
  589.         return getCageMin().clone().add(cageVectorFromMinToCenter);
  590.     }
  591.  
  592. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement