Skip to content

Commit 54553fe

Browse files
committed
refactor(plugin): convert more interfaces / abstract classes to kt
1 parent 51d93d4 commit 54553fe

File tree

7 files changed

+350
-458
lines changed

7 files changed

+350
-458
lines changed

plugin/src/server/sc/plugin2020/Game.java

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import com.thoughtworks.xstream.annotations.XStreamAlias;
44
import com.thoughtworks.xstream.annotations.XStreamOmitField;
5+
import org.jetbrains.annotations.NotNull;
56
import org.slf4j.Logger;
67
import org.slf4j.LoggerFactory;
78
import sc.api.plugins.IGameState;
@@ -22,9 +23,12 @@
2223

2324
/** Minimales Spiel als Basis für neue Plugins. */
2425
@XStreamAlias(value = "game")
25-
public class Game extends RoundBasedGameInstance<Player> {
26+
public class Game extends RoundBasedGameInstance {
2627
private static final Logger logger = LoggerFactory.getLogger(Game.class);
2728

29+
@XStreamOmitField
30+
private String pluginUUID;
31+
2832
@XStreamOmitField
2933
private List<Team> availableColors = new ArrayList<>();
3034

@@ -51,7 +55,7 @@ protected IGameState getCurrentState() {
5155

5256
/** Jemand hat etwas gesendet -> testen was es war (wenn es ein Zug war, dann validieren) */
5357
@Override
54-
protected void onRoundBasedAction(Player fromPlayer, ProtocolMessage data) throws InvalidGameStateException, InvalidMoveException {
58+
protected void onRoundBasedAction(Player fromPlayer, ProtocolMessage data) throws InvalidGameStateException {
5559
// NOTE: Checking if right player sent move was already done by onAction(Player, ProtocolMove)}.
5660
// There is no need to do it here again.
5761
try {
@@ -61,7 +65,7 @@ protected void onRoundBasedAction(Player fromPlayer, ProtocolMessage data) throw
6165
logger.debug("Performing Move " + move.toString());
6266
logger.debug("Current Board: " + this.gameState.getBoard().toString());
6367
GameRuleLogic.performMove(this.gameState, move);
64-
next(this.gameState.getCurrentPlayer());
68+
next(this.gameState.getCurrentPlayer(), false);
6569
} catch(InvalidMoveException e) {
6670
super.catchInvalidMove(e, fromPlayer);
6771
}
@@ -80,7 +84,7 @@ public Player onPlayerJoined() {
8084
player = new Player(team);
8185
}
8286

83-
this.players.add(player);
87+
addPlayer(player);
8488
this.gameState.addPlayer(player);
8589

8690
return player;
@@ -89,7 +93,7 @@ public Player onPlayerJoined() {
8993
/** Sends welcomeMessage to all listeners and notify player on new gameStates or MoveRequests */
9094
@Override
9195
public void start() {
92-
for(final Player p : this.players) {
96+
for(final Player p : getPlayers()) {
9397
p.notifyListeners(new WelcomeMessage(p.getColor()));
9498
}
9599
super.start();
@@ -263,7 +267,7 @@ public List<Player> getWinners() {
263267
WinCondition winCondition = checkWinCondition();
264268
List<Player> winners = new ArrayList<>();
265269
if(winCondition != null) {
266-
for(Player player : this.players) {
270+
for(Player player : getPlayers()) {
267271
if(player.getColor() == winCondition.getWinner()) {
268272
winners.add(player);
269273
break;
@@ -274,7 +278,7 @@ public List<Player> getWinners() {
274278
// determined by matchpoints ("Siegpunkte"). The winning player has 2
275279
// matchpoints. Find this player. If no player has 2 matchpoints, it is a
276280
// draw.
277-
for(Player player : this.players) {
281+
for(Player player : getPlayers()) {
278282
if(getScoreFor(player).getValues().get(0).intValueExact() == Constants.WIN_SCORE) {
279283
winners.add(player);
280284
break;
@@ -284,10 +288,11 @@ public List<Player> getWinners() {
284288
return winners;
285289
}
286290

287-
/** Liste der Spieler. Reihenfolge: RED, BLUE */
291+
/** Liste der Spieler. Reihenfolge: RED, BLUE
292+
* @return*/
288293
@Override
289-
public List<Player> getPlayers() {
290-
return gameState.getPlayers();
294+
public ArrayList<Player> getPlayers() {
295+
return new ArrayList<Player>(gameState.getPlayers());
291296
}
292297

293298
/** Liste der playerScores für jeden Spieler. Reihenfolge: RED, BLUE */
@@ -298,4 +303,9 @@ public List<PlayerScore> getPlayerScores() {
298303
return playerScores;
299304
}
300305

306+
@NotNull
307+
@Override
308+
public String getPluginUUID() {
309+
return pluginUUID;
310+
}
301311
}

plugin/src/server/sc/plugin2021/Game.kt

Lines changed: 19 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -15,17 +15,15 @@ import kotlin.math.log
1515

1616

1717
@XStreamAlias(value = "game")
18-
class Game(UUID: String = GamePlugin.PLUGIN_UUID): RoundBasedGameInstance<Player>() {
18+
class Game(UUID: String = GamePlugin.PLUGIN_UUID): RoundBasedGameInstance() {
1919
companion object {
2020
val logger = LoggerFactory.getLogger(Game::class.java)
2121
}
2222

2323
private val availableTeams = mutableListOf(Team.ONE, Team.TWO)
2424
val gameState = GameState()
2525

26-
init {
27-
pluginUUID = UUID
28-
}
26+
override val pluginUUID: String = UUID
2927

3028
override fun start() {
3129
players.forEach {it.notifyListeners(WelcomeMessage(it.color)) }
@@ -42,21 +40,20 @@ class Game(UUID: String = GamePlugin.PLUGIN_UUID): RoundBasedGameInstance<Player
4240
return player
4341
}
4442

45-
override fun getWinners(): MutableList<Player> {
46-
val winCondition = checkWinCondition()
47-
if (winCondition != null)
48-
return winCondition.winner.let{players}
49-
50-
// If no win condition is met, the player with highest score wins.
51-
return listOfNotNull(players.maxBy {
52-
gameState.getPointsForPlayer(it.color)
53-
}).toMutableList()
54-
}
55-
56-
override fun getPlayerScores(): MutableList<PlayerScore> =
57-
getPlayers().map { getScoreFor(it) }.toMutableList()
43+
override val winners: List<Player>
44+
get() {
45+
val winCondition = checkWinCondition()
46+
if (winCondition != null)
47+
return winCondition.winner.let{players}
48+
49+
// If no win condition is met, the player with highest score wins.
50+
return listOfNotNull(players.maxBy {
51+
gameState.getPointsForPlayer(it.color)
52+
}).toMutableList()
53+
}
5854

59-
override fun getPlayers(): MutableList<Player> = players
55+
override val playerScores: List<PlayerScore>
56+
get() = players.map { getScoreFor(it) }.toMutableList()
6057

6158
private val playerMap = mutableMapOf<Team, Player>()
6259

@@ -80,15 +77,15 @@ class Game(UUID: String = GamePlugin.PLUGIN_UUID): RoundBasedGameInstance<Player
8077
return WinCondition(null, WinReason.EQUAL_SCORE)
8178
}
8279

83-
override fun loadGameInfo(gameInfo: Any?) {
80+
override fun loadGameInfo(gameInfo: Any) {
8481
TODO("Not yet implemented")
8582
}
8683

87-
override fun loadFromFile(file: String?) {
84+
override fun loadFromFile(file: String) {
8885
TODO("Not yet implemented")
8986
}
9087

91-
override fun loadFromFile(file: String?, turn: Int) {
88+
override fun loadFromFile(file: String, turn: Int) {
9289
TODO("Not yet implemented")
9390
}
9491

@@ -145,7 +142,7 @@ class Game(UUID: String = GamePlugin.PLUGIN_UUID): RoundBasedGameInstance<Player
145142
ActionTimeout(true, Constants.HARD_TIMEOUT, Constants.SOFT_TIMEOUT)
146143

147144
@Throws(InvalidMoveException::class, InvalidGameStateException::class)
148-
override fun onRoundBasedAction(fromPlayer: Player, data: ProtocolMessage?) {
145+
override fun onRoundBasedAction(fromPlayer: Player, data: ProtocolMessage) {
149146
// This check is already done by super.onAction()
150147
assert(fromPlayer == activePlayer)
151148

plugin/src/test/sc/plugin2021/ManualGameTest.kts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ fun loop() {
4242
println("$input -> $move")
4343

4444
try {
45-
game.onAction(game.gameState.getPlayer(move.color.team), move)
45+
game.onAction(game.gameState.getPlayer(move.color.team)!!, move)
4646
current = game.gameState.getOpponent(current)!!
4747
} catch (e: Exception) {
4848
println(e)

socha-sdk/src/server-api/sc/api/plugins/IGameInstance.java

Lines changed: 0 additions & 99 deletions
This file was deleted.
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
package sc.api.plugins
2+
3+
import sc.api.plugins.exceptions.GameLogicException
4+
import sc.api.plugins.exceptions.TooManyPlayersException
5+
import sc.api.plugins.host.IGameListener
6+
import sc.framework.plugins.Player
7+
import sc.protocol.responses.ProtocolMessage
8+
import sc.shared.InvalidGameStateException
9+
import sc.shared.InvalidMoveException
10+
import sc.shared.PlayerScore
11+
import sc.shared.ScoreCause
12+
13+
interface IGameInstance {
14+
/**
15+
* @return the player that joined
16+
*
17+
* @throws TooManyPlayersException thrown when a player can't join
18+
*/
19+
@Throws(TooManyPlayersException::class)
20+
fun onPlayerJoined(): Player
21+
fun onPlayerLeft(player: Player, cause: ScoreCause? = null)
22+
23+
/**
24+
* Called by the Server once an action was received.
25+
*
26+
* @param fromPlayer The player who invoked this action.
27+
* @param data The plugin-secific data.
28+
*
29+
* @throws GameLogicException if any invalid action is done
30+
* @throws InvalidMoveException if the received move violates the rules
31+
*/
32+
@Throws(GameLogicException::class, InvalidGameStateException::class, InvalidMoveException::class)
33+
fun onAction(fromPlayer: Player, data: ProtocolMessage)
34+
35+
/**
36+
* Extends the set of listeners.
37+
*
38+
* @param listener GameListener to be added
39+
*/
40+
fun addGameListener(listener: IGameListener)
41+
fun removeGameListener(listener: IGameListener)
42+
43+
/** Server or an administrator requests the game to start now. */
44+
fun start()
45+
46+
/**
47+
* Destroys the Game.
48+
* Might be invoked by the server at any time. Any open handles should be removed.
49+
* No events should be sent out (GameOver etc) after this method has been called.
50+
*/
51+
fun destroy()
52+
53+
/**
54+
* The game is requested to load itself from a file (the board i.e.). This is
55+
* like a replay but with actual clients.
56+
*
57+
* @param file File where the game should be loaded from
58+
*/
59+
fun loadFromFile(file: String)
60+
61+
/**
62+
* The game is requested to load itself from a file (the board i.e.). This is
63+
* like a replay but with actual clients. Turn is used to specify the turn to
64+
* load from replay (e.g. if more than one gameState in replay)
65+
*
66+
* @param file File where the game should be loaded from
67+
* @param turn The turn to load
68+
*/
69+
fun loadFromFile(file: String, turn: Int)
70+
71+
/**
72+
* The game is requested to load itself from a given game information object (could be a board instance for example)
73+
*
74+
* @param gameInfo the stored gameInformation
75+
*/
76+
fun loadGameInfo(gameInfo: Any)
77+
78+
/**
79+
* Returns the players that have won the game, empty if the game has no winners,
80+
* or null if the game has not finished.
81+
*/
82+
val winners: List<Player>
83+
84+
/** Used for generating replay name. */
85+
val pluginUUID: String
86+
87+
/** @return the two players, the startplayer will be first in the List
88+
*/
89+
val players: MutableList<Player>
90+
91+
/** @return the PlayerScores for both players
92+
*/
93+
val playerScores: List<PlayerScore>
94+
}

0 commit comments

Comments
 (0)