diff --git a/src/main/java/net/knarcraft/stargate/portal/Gate.java b/src/main/java/net/knarcraft/stargate/portal/Gate.java index 1a7b6d6..9fdc3d8 100644 --- a/src/main/java/net/knarcraft/stargate/portal/Gate.java +++ b/src/main/java/net/knarcraft/stargate/portal/Gate.java @@ -265,7 +265,7 @@ public class Gate { bufferedWriter.newLine(); //Save the gate layout - layout.save(bufferedWriter); + layout.saveLayout(bufferedWriter); bufferedWriter.close(); } catch (IOException ex) { diff --git a/src/main/java/net/knarcraft/stargate/portal/GateLayout.java b/src/main/java/net/knarcraft/stargate/portal/GateLayout.java index 38e121a..00d3278 100644 --- a/src/main/java/net/knarcraft/stargate/portal/GateLayout.java +++ b/src/main/java/net/knarcraft/stargate/portal/GateLayout.java @@ -5,6 +5,7 @@ import net.knarcraft.stargate.container.RelativeBlockVector; import java.io.BufferedWriter; import java.io.IOException; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; /** @@ -12,7 +13,7 @@ import java.util.List; * *

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)

+ * (the side with the sign). The origin of the relative vectors can also be seen as 0,0 in the character matrix.

*/ public class GateLayout { @@ -26,7 +27,7 @@ public class GateLayout { /** * Instantiates a new gate layout * - * @param layout

A character array describing the layout

+ * @param layout

A character matrix describing the layout

*/ public GateLayout(Character[][] layout) { this.layout = layout; @@ -43,7 +44,9 @@ public class GateLayout { } /** - * Gets the locations of entrances for this gate + * Gets the locations of all entrances for this gate + * + *

Entrances contain both the portal entrance blocks and the portal exit blocks.

* * @return

The locations of entrances for this gate

*/ @@ -73,9 +76,12 @@ public class GateLayout { } /** - * Gets other possible exits of the gate + * Gets all possible exit locations defined in the layout * - * @return

Other possible gate exits

+ *

This returns all blocks usable as exits. This basically means it returns the lowest block in each opening of + * the gate layout.

+ * + * @return

All possible exits

*/ public List getExits() { return exits; @@ -84,7 +90,8 @@ public class GateLayout { /** * Gets the locations of the control blocks for this gate * - *

The control blocks are the blocks where a sign can be placed to create a portal.

+ *

The control blocks are the blocks where a sign can be placed to create a portal. The control block without a + * sign will be used for the button if necessary. There will always be exactly two control blocks.

* * @return

The locations of the control blocks for this gate

*/ @@ -98,44 +105,24 @@ public class GateLayout { * @param bufferedWriter

The buffered writer to write to

* @throws IOException

If unable to write to the buffered writer

*/ - public void save(BufferedWriter bufferedWriter) throws IOException { + public void saveLayout(BufferedWriter bufferedWriter) throws IOException { for (Character[] line : this.layout) { - for (Character symbol : line) { - bufferedWriter.append(symbol); - } + bufferedWriter.append(Arrays.toString(line)); bufferedWriter.newLine(); } } /** - * Reads the gate layout to relative block vectors + * Reads the layout and stores key information + * + *

This methods reads the layout and stores exits, entrances, border blocks and control blocks.

*/ private void readLayout() { List entranceList = new ArrayList<>(); List borderList = new ArrayList<>(); List 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]); - } - } + readLayout(controlList, entranceList, borderList); this.entrances = entranceList.toArray(this.entrances); this.border = borderList.toArray(this.border); @@ -148,55 +135,74 @@ public class GateLayout { * @param controlList

The list of control blocks to save to

* @param entranceList

The list of entrances to save to

* @param borderList

The list of border blocks to save to

- * @return

A list of depths of possible extra exits

*/ - private int[] readLayout(List controlList, List entranceList, - List borderList) { - //Store the depth/line of each + private void readLayout(List controlList, List entranceList, + List borderList) { + //Store the lowest opening for each column int[] exitDepths = new int[layout[0].length]; + //A row is the same as one line in the gate file 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); + for (int rowIndex = 0; rowIndex < lineCount; rowIndex++) { + Character[] row = layout[rowIndex]; + int rowSize = row.length; + for (int columnIndex = 0; columnIndex < rowSize; columnIndex++) { + Character key = row[columnIndex]; + parseLayoutCharacter(key, columnIndex, rowIndex, exitDepths, controlList, entranceList, borderList); + } + } + + //Generate all possible exits + for (int x = 0; x < exitDepths.length; x++) { + //Ignore invalid exits + if (exitDepths[x] > 0) { + this.exits.add(new RelativeBlockVector(x, exitDepths[x], 0)); } } - return exitDepths; } /** * Parses one character of the layout * - * @param key

The character read

- * @param rowIndex

The row of the read character

- * @param lineIndex

The line of the read character

+ * @param key

The read character

+ * @param columnIndex

The column containing the read character

+ * @param rowIndex

The row containing the read character

* @param exitDepths

The list of exit depths to save to

* @param controlList

The list of control blocks to save to

* @param entranceList

The list of entrances to save to

* @param borderList

The list of border blocks to save to

*/ - private void parseLayoutCharacter(Character key, int rowIndex, int lineIndex, int[] exitDepths, + private void parseLayoutCharacter(Character key, int columnIndex, int rowIndex, int[] exitDepths, List controlList, List entranceList, List borderList) { - //Add control blocks + //Add control blocks to the control block list if (key.equals(GateHandler.getControlBlockCharacter())) { - controlList.add(new RelativeBlockVector(rowIndex, lineIndex, 0)); + controlList.add(new RelativeBlockVector(columnIndex, rowIndex, 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 (isOpening(key)) { + //Register entrance + entranceList.add(new RelativeBlockVector(columnIndex, rowIndex, 0)); + //Overwrite the lowest exit location for this column/x-coordinate + exitDepths[columnIndex] = rowIndex; + //Register exit if found if (key.equals(GateHandler.getExitCharacter())) { - this.exitBlock = new RelativeBlockVector(rowIndex, lineIndex, 0); + this.exitBlock = new RelativeBlockVector(columnIndex, rowIndex, 0); } } else if (!key.equals(GateHandler.getAnythingCharacter())) { - //Add border - borderList.add(new RelativeBlockVector(rowIndex, lineIndex, 0)); + //Register border block + borderList.add(new RelativeBlockVector(columnIndex, rowIndex, 0)); } } + + /** + * Checks whether the given character represents a gate opening + * + * @param character

The character to check

+ * @return

True if the character represents an opening

+ */ + private boolean isOpening(Character character) { + return character.equals(GateHandler.getEntranceCharacter()) || character.equals(GateHandler.getExitCharacter()); + } + }