Skip to content

Commit

Permalink
Add applyGravityTick()-test
Browse files Browse the repository at this point in the history
  • Loading branch information
lscgh committed Feb 7, 2024
1 parent a8f2e0c commit 4f93008
Show file tree
Hide file tree
Showing 6 changed files with 147 additions and 24 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -144,11 +144,6 @@ public List<String> onTabComplete(CommandSender sender, Command command, String

if(!(sender instanceof Player)) return new ArrayList<String>();

ArrayList<String> a = new ArrayList<String>();
for(String arg: args) a.add(arg);

sender.sendMessage("Your original list " + a + " (count=" + a.size() + ")");

ArrayList<String> argList = new ArrayList<String>();
int i = 0;
for(String arg: args) {
Expand All @@ -159,8 +154,6 @@ public List<String> onTabComplete(CommandSender sender, Command command, String
i++;
}

sender.sendMessage("Your list " + argList + " (count=" + argList.size() + ")");

ArrayList<String> completions = new ArrayList<String>();

boolean playerIsCurrentlyInAGame = Game.runningGames.containsKey((Player)sender);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ public List<String> onTabComplete(CommandSender sender, Command command, String

ArrayList<String> argList = new ArrayList<String>();
for(String arg: args) argList.add(arg);
argList.removeIf((arg) -> arg.isEmpty() && !CommandTicTacToeAccept.containsNonEmptyString(argList.subList(0, Math.max(0, argList.indexOf(arg) - 1))));
argList.removeIf((arg) -> arg.isEmpty() && !CommandTicTacToeAccept.listContainsNonEmptyString(argList.subList(0, Math.max(0, argList.indexOf(arg) - 1))));

if(argList.size() >= CommandTicTacToeAccept.ARG_COUNT) return new ArrayList<String>();

Expand All @@ -97,7 +97,7 @@ public List<String> onTabComplete(CommandSender sender, Command command, String
}


public static boolean containsNonEmptyString(List<String> list) {
public static boolean listContainsNonEmptyString(List<String> list) {
for(String string: list) {
if(!string.isEmpty()) return true;
}
Expand Down
9 changes: 7 additions & 2 deletions mavenmcserver/src/main/java/mavenmcserver/game/Game.java
Original file line number Diff line number Diff line change
Expand Up @@ -86,8 +86,13 @@ public Game(GameConfig config, Plugin plugin, boolean isReturnMatch) {

@Override
public void run() {
boolean didApplyAnyChangeInCurrentTick = state.applyGravityTick(location, lastPlacePosition);
if(!didApplyAnyChangeInCurrentTick && !didCompletePlace) {
boolean didApplyAnyChange = state.applyGravityTick(lastPlacePosition);

if(didApplyAnyChange) {
state.applyVisually(location);
}

if(!didApplyAnyChange && !didCompletePlace) {
// Falling is now done
checkForWin();
didCompletePlace = true;
Expand Down
59 changes: 47 additions & 12 deletions mavenmcserver/src/main/java/mavenmcserver/game/GameState.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import java.util.ArrayList;

import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.World;
import org.joml.Vector3i;

Expand Down Expand Up @@ -36,6 +37,16 @@ public boolean equals(Object obj) {
FieldPoint point = (FieldPoint)obj;
return point.x == this.x && point.y == this.y && point.z == this.z;
}

@Override
public int hashCode() {
int result = (this.x ^ (this.x >>> 32));

result = 31 * result + (this.y ^ (this.y >>> 32));
result = 31 * result + (this.z ^ (this.z >>> 32));

return result;
}
}

/**
Expand Down Expand Up @@ -157,8 +168,12 @@ public void setStateAt(int x, int y, int z, FieldState newState) {
this.setStateAt(new FieldPoint(x, y, z), newState);
}


public boolean applyGravityTick(Location gameStartBlock, FieldPoint lastPlacePosition) {
/**
* Advances the physics of this state by one tick. Every marking in air will fall down by a block.
* @param lastPlacePosition The FieldPoint of the last-changed block.
* @return Whether any changes were made.
*/
public boolean applyGravityTick(FieldPoint lastPlacePosition) {
boolean didApplyAnyChange = false;

for(int y = 1; y < this.gameSize.y; y++) {
Expand All @@ -169,16 +184,6 @@ public boolean applyGravityTick(Location gameStartBlock, FieldPoint lastPlacePos
this.setStateAt(x, y - 1, z, this.getStateAt(x, y, z));
this.setStateAt(x, y, z, FieldState.NEUTRAL);

// Update changes visually
World gameWorld = gameStartBlock.getWorld();

Location inWorldLocationOfUnderneathBlock = this.fieldPointToBlockLocation(gameStartBlock, new FieldPoint(x, y - 1, z));
if(this.getStateAt(x, y - 1, z) == FieldState.MAIN) gameWorld.getBlockAt(inWorldLocationOfUnderneathBlock).setType(Game.MAIN_PLAYER_MATERIAL);
else if(this.getStateAt(x, y - 1, z) == FieldState.OPPONENT) gameWorld.getBlockAt(inWorldLocationOfUnderneathBlock).setType(Game.OPPONENT_PLAYER_MATERIAL);

Location inWorldLocationOfCurrentBlock = this.fieldPointToBlockLocation(gameStartBlock, new FieldPoint(x, y, z));
gameWorld.getBlockAt(inWorldLocationOfCurrentBlock).setType(Game.NEUTRAL_MATERIAL);

boolean didModifyBlockAtLastPlacePosition = lastPlacePosition.equals(new FieldPoint(x, y, z));
if(didModifyBlockAtLastPlacePosition) {
lastPlacePosition.y -= 1;
Expand All @@ -194,6 +199,36 @@ public boolean applyGravityTick(Location gameStartBlock, FieldPoint lastPlacePos
return didApplyAnyChange;
}

/**
* Updates any changes made to this state visually by placing the blocks (replaces ALL blocks).
* @param gameStartBlock The location of the target game.
*/
public void applyVisually(Location gameStartBlock) {

World gameWorld = gameStartBlock.getWorld();

for(int y = 0; y < this.gameSize.y; y++) {
for(int x = 0; x < this.gameSize.x; x++) {
for(int z = 0; z < this.gameSize.z; z++) {

FieldState stateOfCurrentField = this.getStateAt(x, y, z);

Material newTypeOfBlock = Game.NEUTRAL_MATERIAL;
if(stateOfCurrentField == FieldState.MAIN) {
newTypeOfBlock = Game.MAIN_PLAYER_MATERIAL;
} else if(stateOfCurrentField == FieldState.OPPONENT) {
newTypeOfBlock = Game.OPPONENT_PLAYER_MATERIAL;
}

Location inWorldLocationOfCurrentBlock = this.fieldPointToBlockLocation(gameStartBlock, new FieldPoint(x, y, z));
gameWorld.getBlockAt(inWorldLocationOfCurrentBlock).setType(newTypeOfBlock);

}
}
}

}

/**
* Checks if a player won the game
* @param lastPlacePosition the field point that was last changed. Checks are done from this point into all possible directions.
Expand Down
3 changes: 2 additions & 1 deletion mavenmcserver/src/main/resources/classes.uml
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,8 @@ class GameState {
+void setStateAt(FieldPoint position, FieldState newState)
+void setStateAt(int x, int y, int z, FieldState newState)

+boolean applyGravityTick(Location gameStartBlock, FieldPoint lastPlacePosition) /' Makes all blocks in air fall by one '/
+boolean applyGravityTick(FieldPoint lastPlacePosition) /' Makes all blocks in air fall by one '/
+void applyVisually(Location gameStartBlock) /' Updates in-world blocks to match the state '/

// Returns NEUTRAL if there is no winner yet
+FieldState getWinnerIfAny(int winRequiredAmount, FieldPoint lastPlacePosition) /' Returns NEUTRAL for no winner yet '/
Expand Down
89 changes: 89 additions & 0 deletions mavenmcserver/src/test/java/mavenmcserver/game/GameStateTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;

import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import static java.util.Map.entry;

import org.joml.Vector3i;
import org.junit.jupiter.api.Test;

Expand Down Expand Up @@ -154,5 +159,89 @@ public void testWinIsPossible() {

}

public boolean stateIsNeutralExceptFor(GameState state, Map<FieldPoint, FieldState> exceptions) {
for(int x = 0; x < state.gameSize.x; x++) {
for(int y = 0; y < state.gameSize.y; y++) {
for(int z = 0; z < state.gameSize.z; z++) {
FieldPoint currentPoint = new FieldPoint(x, y, z);
FieldState expectedState = exceptions.containsKey(currentPoint) ? exceptions.get(currentPoint) : FieldState.NEUTRAL;
if(state.getStateAt(currentPoint) != expectedState) return false;
}
}
}

return true;
}

@Test
public void testApplyGravityTick() {

// 3 x 3 x 3
GameState state = new GameState(new Vector3i(3, 3, 3));
FieldPoint lastPlacePosition = new FieldPoint(0, 2, 0);

state.setStateAt(lastPlacePosition, FieldState.OPPONENT);
assertTrue(this.stateIsNeutralExceptFor(state, Map.ofEntries(entry(new FieldPoint(0, 2, 0), FieldState.OPPONENT))));

assertTrue(state.applyGravityTick(lastPlacePosition));
assertEquals(new FieldPoint(0, 1, 0), lastPlacePosition);
assertTrue(this.stateIsNeutralExceptFor(state, Map.ofEntries(entry(new FieldPoint(0, 1, 0), FieldState.OPPONENT))));

assertTrue(state.applyGravityTick(lastPlacePosition));
assertEquals(new FieldPoint(0, 0, 0), lastPlacePosition);
assertTrue(this.stateIsNeutralExceptFor(state, Map.ofEntries(entry(new FieldPoint(0, 0, 0), FieldState.OPPONENT))));

assertFalse(state.applyGravityTick(lastPlacePosition));
assertFalse(state.applyGravityTick(lastPlacePosition));
assertFalse(state.applyGravityTick(lastPlacePosition));


// 4 x 4 x 4
state = new GameState(new Vector3i(4, 4, 4));
lastPlacePosition = new FieldPoint(0, 3, 0);


state.setStateAt(lastPlacePosition, FieldState.MAIN);
assertTrue(this.stateIsNeutralExceptFor(state, Map.ofEntries(entry(new FieldPoint(0, 3, 0), FieldState.MAIN))));

assertTrue(state.applyGravityTick(lastPlacePosition));
assertEquals(new FieldPoint(0, 2, 0), lastPlacePosition);
assertTrue(this.stateIsNeutralExceptFor(state, Map.ofEntries(entry(new FieldPoint(0, 2, 0), FieldState.MAIN))));

assertTrue(state.applyGravityTick(lastPlacePosition));
assertEquals(new FieldPoint(0, 1, 0), lastPlacePosition);
assertTrue(this.stateIsNeutralExceptFor(state, Map.ofEntries(entry(new FieldPoint(0, 1, 0), FieldState.MAIN))));


assertTrue(state.applyGravityTick(lastPlacePosition));
assertEquals(new FieldPoint(0, 0, 0), lastPlacePosition);
assertTrue(this.stateIsNeutralExceptFor(state, Map.ofEntries(entry(new FieldPoint(0, 0, 0), FieldState.MAIN))));

assertFalse(state.applyGravityTick(lastPlacePosition));
assertFalse(state.applyGravityTick(lastPlacePosition));
assertFalse(state.applyGravityTick(lastPlacePosition));

lastPlacePosition = new FieldPoint(1, 3, 3);
state.setStateAt(lastPlacePosition, FieldState.OPPONENT);
assertTrue(this.stateIsNeutralExceptFor(state, Map.ofEntries(entry(new FieldPoint(0, 0, 0), FieldState.MAIN), entry(new FieldPoint(1, 3, 3), FieldState.OPPONENT))));

assertTrue(state.applyGravityTick(lastPlacePosition));
assertEquals(new FieldPoint(1, 2, 3), lastPlacePosition);
assertTrue(this.stateIsNeutralExceptFor(state, Map.ofEntries(entry(new FieldPoint(0, 0, 0), FieldState.MAIN), entry(new FieldPoint(1, 2, 3), FieldState.OPPONENT))));

assertTrue(state.applyGravityTick(lastPlacePosition));
assertEquals(new FieldPoint(1, 1, 3), lastPlacePosition);
assertTrue(this.stateIsNeutralExceptFor(state, Map.ofEntries(entry(new FieldPoint(0, 0, 0), FieldState.MAIN), entry(new FieldPoint(1, 1, 3), FieldState.OPPONENT))));

assertTrue(state.applyGravityTick(lastPlacePosition));
assertEquals(new FieldPoint(1, 0, 3), lastPlacePosition);
assertTrue(this.stateIsNeutralExceptFor(state, Map.ofEntries(entry(new FieldPoint(0, 0, 0), FieldState.MAIN), entry(new FieldPoint(1, 0, 3), FieldState.OPPONENT))));

assertFalse(state.applyGravityTick(lastPlacePosition));
assertFalse(state.applyGravityTick(lastPlacePosition));
assertFalse(state.applyGravityTick(lastPlacePosition));

}

}

0 comments on commit 4f93008

Please sign in to comment.