215 lines
7.7 KiB
Java
215 lines
7.7 KiB
Java
package net.knarcraft.stargate.portal;
|
|
|
|
import net.knarcraft.stargate.container.RelativeBlockVector;
|
|
|
|
import java.io.BufferedWriter;
|
|
import java.io.IOException;
|
|
import java.util.ArrayList;
|
|
import java.util.List;
|
|
|
|
/**
|
|
* The gate layout describes where every part of the gate should be
|
|
*
|
|
* <p>The gate layout parses a layout described by a Character matrix and stores the different parts of the gate as
|
|
* relative block vectors. All relative vectors has an origin in the top-left block when looking at the gate's front
|
|
* (the side with the sign)</p>
|
|
*/
|
|
public class GateLayout {
|
|
|
|
private final Character[][] layout;
|
|
private final List<RelativeBlockVector> exits = new ArrayList<>();
|
|
private RelativeBlockVector[] entrances = new RelativeBlockVector[0];
|
|
private RelativeBlockVector[] border = new RelativeBlockVector[0];
|
|
private RelativeBlockVector[] controls = new RelativeBlockVector[0];
|
|
private RelativeBlockVector exitBlock = null;
|
|
|
|
/**
|
|
* Instantiates a new gate layout
|
|
*
|
|
* @param layout <p>A character array describing the layout</p>
|
|
*/
|
|
public GateLayout(Character[][] layout) {
|
|
this.layout = layout;
|
|
readLayout();
|
|
}
|
|
|
|
/**
|
|
* Gets two of the corners of the gate layout creating the smallest box the gate can be contained within
|
|
*
|
|
* @return <p>Two of the gate's corners</p>
|
|
*/
|
|
public RelativeBlockVector[] getCorners() {
|
|
return new RelativeBlockVector[]{
|
|
new RelativeBlockVector(0, 0, 0),
|
|
new RelativeBlockVector(layout[0].length - 1, layout.length - 1, 1)
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Gets the character array describing this layout
|
|
*
|
|
* @return <p>The character array describing this layout</p>
|
|
*/
|
|
public Character[][] getLayout() {
|
|
return this.layout;
|
|
}
|
|
|
|
/**
|
|
* Gets the locations of entrances for this gate
|
|
*
|
|
* @return <p>The locations of entrances for this gate</p>
|
|
*/
|
|
public RelativeBlockVector[] getEntrances() {
|
|
return entrances;
|
|
}
|
|
|
|
/**
|
|
* Gets the locations of border blocks for the gate described by this layout
|
|
*
|
|
* <p>A border block is basically any block of the frame. In terms of the nether gate, the border blocks are every
|
|
* block of the gate that's not air when the gate is closed. The sign and button are not border blocks.</p>
|
|
*
|
|
* @return <p>The locations of border blocks for this gate</p>
|
|
*/
|
|
public RelativeBlockVector[] getBorder() {
|
|
return border;
|
|
}
|
|
|
|
/**
|
|
* Gets the exit block defined in the layout
|
|
*
|
|
* @return <p>The exit block defined in the layout</p>
|
|
*/
|
|
public RelativeBlockVector getExit() {
|
|
return exitBlock;
|
|
}
|
|
|
|
/**
|
|
* Gets other possible exits of the gate
|
|
*
|
|
* @return <p>Other possible gate exits</p>
|
|
*/
|
|
public List<RelativeBlockVector> getExits() {
|
|
return exits;
|
|
}
|
|
|
|
/**
|
|
* Gets the locations of the control blocks for this gate
|
|
*
|
|
* <p>The control blocks are the blocks where a sign can be placed to create a portal.</p>
|
|
*
|
|
* @return <p>The locations of the control blocks for this gate</p>
|
|
*/
|
|
public RelativeBlockVector[] getControls() {
|
|
return controls;
|
|
}
|
|
|
|
/**
|
|
* Saves the gate layout using a buffered writer
|
|
*
|
|
* @param bufferedWriter <p>The buffered writer to write to</p>
|
|
* @throws IOException <p>If unable to write to the buffered writer</p>
|
|
*/
|
|
public void save(BufferedWriter bufferedWriter) throws IOException {
|
|
for (Character[] line : this.layout) {
|
|
for (Character symbol : line) {
|
|
bufferedWriter.append(symbol);
|
|
}
|
|
bufferedWriter.newLine();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Reads the gate layout to relative block vectors
|
|
*/
|
|
private void readLayout() {
|
|
List<RelativeBlockVector> entranceList = new ArrayList<>();
|
|
List<RelativeBlockVector> borderList = new ArrayList<>();
|
|
List<RelativeBlockVector> controlList = new ArrayList<>();
|
|
RelativeBlockVector[] relativeExits = new RelativeBlockVector[layout[0].length];
|
|
RelativeBlockVector lastExit = null;
|
|
|
|
int[] exitDepths = readLayout(controlList, entranceList, borderList);
|
|
|
|
//Generate other possible exits
|
|
for (int x = 0; x < exitDepths.length; x++) {
|
|
relativeExits[x] = new RelativeBlockVector(x, exitDepths[x], 0);
|
|
}
|
|
|
|
//Add non-null exits to the exits list
|
|
for (int x = relativeExits.length - 1; x >= 0; x--) {
|
|
if (relativeExits[x] != null) {
|
|
lastExit = relativeExits[x];
|
|
} else {
|
|
relativeExits[x] = lastExit;
|
|
}
|
|
|
|
if (exitDepths[x] > 0) {
|
|
this.exits.add(relativeExits[x]);
|
|
}
|
|
}
|
|
|
|
this.entrances = entranceList.toArray(this.entrances);
|
|
this.border = borderList.toArray(this.border);
|
|
this.controls = controlList.toArray(this.controls);
|
|
}
|
|
|
|
/**
|
|
* Reads the given layout matrix, filling in the given lists of relative block vectors
|
|
*
|
|
* @param controlList <p>The list of control blocks to save to</p>
|
|
* @param entranceList <p>The list of entrances to save to</p>
|
|
* @param borderList <p>The list of border blocks to save to</p>
|
|
* @return <p>A list of depths of possible extra exits</p>
|
|
*/
|
|
private int[] readLayout(List<RelativeBlockVector> controlList, List<RelativeBlockVector> entranceList,
|
|
List<RelativeBlockVector> borderList) {
|
|
//Store the depth/line of each
|
|
int[] exitDepths = new int[layout[0].length];
|
|
|
|
int lineCount = layout.length;
|
|
for (int lineIndex = 0; lineIndex < lineCount; lineIndex++) {
|
|
int rowSize = layout[lineIndex].length;
|
|
for (int rowIndex = 0; rowIndex < rowSize; rowIndex++) {
|
|
Character key = layout[lineIndex][rowIndex];
|
|
parseLayoutCharacter(key, rowIndex, lineIndex, exitDepths, controlList, entranceList, borderList);
|
|
}
|
|
}
|
|
return exitDepths;
|
|
}
|
|
|
|
/**
|
|
* Parses one character of the layout
|
|
*
|
|
* @param key <p>The character read</p>
|
|
* @param rowIndex <p>The row of the read character</p>
|
|
* @param lineIndex <p>The line of the read character</p>
|
|
* @param exitDepths <p>The list of exit depths to save to</p>
|
|
* @param controlList <p>The list of control blocks to save to</p>
|
|
* @param entranceList <p>The list of entrances to save to</p>
|
|
* @param borderList <p>The list of border blocks to save to</p>
|
|
*/
|
|
private void parseLayoutCharacter(Character key, int rowIndex, int lineIndex, int[] exitDepths,
|
|
List<RelativeBlockVector> controlList, List<RelativeBlockVector> entranceList,
|
|
List<RelativeBlockVector> borderList) {
|
|
//Add control blocks
|
|
if (key.equals(GateHandler.getControlBlockCharacter())) {
|
|
controlList.add(new RelativeBlockVector(rowIndex, lineIndex, 0));
|
|
}
|
|
|
|
if (key.equals(GateHandler.getEntranceCharacter()) || key.equals(GateHandler.getExitCharacter())) {
|
|
//Register entrances
|
|
entranceList.add(new RelativeBlockVector(rowIndex, lineIndex, 0));
|
|
//Find the lowest exit block at a given x position
|
|
exitDepths[rowIndex] = lineIndex;
|
|
//Register exit
|
|
if (key.equals(GateHandler.getExitCharacter())) {
|
|
this.exitBlock = new RelativeBlockVector(rowIndex, lineIndex, 0);
|
|
}
|
|
} else if (!key.equals(GateHandler.getAnythingCharacter())) {
|
|
//Add border
|
|
borderList.add(new RelativeBlockVector(rowIndex, lineIndex, 0));
|
|
}
|
|
}
|
|
}
|