mirror of
https://github.com/2OOP/pism.git
synced 2026-02-04 10:54:51 +00:00
Fixed bugs, easy to use host button
This commit is contained in:
@@ -20,15 +20,8 @@ import org.toop.framework.audio.*;
|
|||||||
import org.toop.framework.audio.events.AudioEvents;
|
import org.toop.framework.audio.events.AudioEvents;
|
||||||
import org.toop.framework.eventbus.EventFlow;
|
import org.toop.framework.eventbus.EventFlow;
|
||||||
import org.toop.framework.eventbus.GlobalEventBus;
|
import org.toop.framework.eventbus.GlobalEventBus;
|
||||||
import org.toop.framework.game.BitboardGame;
|
|
||||||
import org.toop.framework.game.games.reversi.BitboardReversi;
|
|
||||||
import org.toop.framework.game.games.tictactoe.BitboardTicTacToe;
|
|
||||||
import org.toop.framework.gameFramework.model.game.TurnBasedGame;
|
|
||||||
import org.toop.framework.networking.connection.NetworkingClientEventListener;
|
import org.toop.framework.networking.connection.NetworkingClientEventListener;
|
||||||
import org.toop.framework.networking.connection.NetworkingClientManager;
|
import org.toop.framework.networking.connection.NetworkingClientManager;
|
||||||
import org.toop.framework.networking.server.GameDefinition;
|
|
||||||
import org.toop.framework.networking.server.MasterServer;
|
|
||||||
import org.toop.framework.networking.server.Server;
|
|
||||||
import org.toop.framework.resource.ResourceLoader;
|
import org.toop.framework.resource.ResourceLoader;
|
||||||
import org.toop.framework.resource.ResourceManager;
|
import org.toop.framework.resource.ResourceManager;
|
||||||
import org.toop.framework.resource.events.AssetLoaderEvents;
|
import org.toop.framework.resource.events.AssetLoaderEvents;
|
||||||
@@ -38,9 +31,7 @@ import org.toop.framework.resource.resources.SoundEffectAsset;
|
|||||||
import org.toop.local.AppContext;
|
import org.toop.local.AppContext;
|
||||||
import org.toop.local.AppSettings;
|
import org.toop.local.AppSettings;
|
||||||
|
|
||||||
import java.time.Duration;
|
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
|
||||||
import java.util.concurrent.CountDownLatch;
|
import java.util.concurrent.CountDownLatch;
|
||||||
import java.util.concurrent.ExecutorService;
|
import java.util.concurrent.ExecutorService;
|
||||||
import java.util.concurrent.Executors;
|
import java.util.concurrent.Executors;
|
||||||
@@ -101,17 +92,6 @@ public final class App extends Application {
|
|||||||
|
|
||||||
WidgetContainer.setCurrentView(loading);
|
WidgetContainer.setCurrentView(loading);
|
||||||
|
|
||||||
var games = new ConcurrentHashMap<String, Class<? extends TurnBasedGame>>();
|
|
||||||
games.put("tictactoe", BitboardTicTacToe.class);
|
|
||||||
games.put("reversi", BitboardReversi.class);
|
|
||||||
|
|
||||||
var a = new MasterServer(6666, games, Duration.ofSeconds(5));
|
|
||||||
try {
|
|
||||||
a.start();
|
|
||||||
} catch (InterruptedException e) {
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
setOnLoadingSuccess(loading);
|
setOnLoadingSuccess(loading);
|
||||||
|
|
||||||
EventFlow loadingFlow = new EventFlow();
|
EventFlow loadingFlow = new EventFlow();
|
||||||
|
|||||||
@@ -263,7 +263,7 @@ public final class Server {
|
|||||||
String gameType = extractQuotedValue(response.gameType());
|
String gameType = extractQuotedValue(response.gameType());
|
||||||
final String finalGameType = gameType;
|
final String finalGameType = gameType;
|
||||||
var a = new ChallengePopup(challengerName, gameType, (playerInformation) -> {
|
var a = new ChallengePopup(challengerName, gameType, (playerInformation) -> {
|
||||||
final int challengeId = Integer.parseInt(response.challengeId().replaceAll("\\D", ""));
|
final long challengeId = Long.parseLong(response.challengeId().replaceAll("\\D", ""));
|
||||||
new EventFlow().addPostEvent(new NetworkEvents.SendAcceptChallenge(clientId, challengeId)).postEvent();
|
new EventFlow().addPostEvent(new NetworkEvents.SendAcceptChallenge(clientId, challengeId)).postEvent();
|
||||||
isSingleGame.set(true);
|
isSingleGame.set(true);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -6,6 +6,13 @@ import org.toop.app.widget.complex.LabeledInputWidget;
|
|||||||
import org.toop.app.widget.complex.ViewWidget;
|
import org.toop.app.widget.complex.ViewWidget;
|
||||||
|
|
||||||
import javafx.geometry.Pos;
|
import javafx.geometry.Pos;
|
||||||
|
import org.toop.framework.game.games.reversi.BitboardReversi;
|
||||||
|
import org.toop.framework.game.games.tictactoe.BitboardTicTacToe;
|
||||||
|
import org.toop.framework.gameFramework.model.game.TurnBasedGame;
|
||||||
|
import org.toop.framework.networking.server.MasterServer;
|
||||||
|
|
||||||
|
import java.time.Duration;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
public class OnlineView extends ViewWidget {
|
public class OnlineView extends ViewWidget {
|
||||||
public OnlineView() {
|
public OnlineView() {
|
||||||
@@ -23,6 +30,28 @@ public class OnlineView extends ViewWidget {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
var localHostButton = Primitive.button("host!", () -> {
|
||||||
|
var games = new ConcurrentHashMap<String, Class<? extends TurnBasedGame>>();
|
||||||
|
games.put("tictactoe", BitboardTicTacToe.class);
|
||||||
|
games.put("reversi", BitboardReversi.class);
|
||||||
|
|
||||||
|
var a = new MasterServer(6666, games, Duration.ofSeconds(10));
|
||||||
|
|
||||||
|
new Thread(() -> {
|
||||||
|
try {
|
||||||
|
a.start();
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}).start();
|
||||||
|
|
||||||
|
new Server(
|
||||||
|
"127.0.0.1",
|
||||||
|
"6666",
|
||||||
|
"host"
|
||||||
|
);
|
||||||
|
}, false);
|
||||||
|
|
||||||
add(Pos.CENTER, Primitive.vbox(
|
add(Pos.CENTER, Primitive.vbox(
|
||||||
serverInformationHeader,
|
serverInformationHeader,
|
||||||
Primitive.separator(),
|
Primitive.separator(),
|
||||||
@@ -32,7 +61,9 @@ public class OnlineView extends ViewWidget {
|
|||||||
playerNameInput.getNode(),
|
playerNameInput.getNode(),
|
||||||
Primitive.separator(),
|
Primitive.separator(),
|
||||||
|
|
||||||
connectButton
|
connectButton,
|
||||||
|
Primitive.separator(),
|
||||||
|
localHostButton
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -102,7 +102,7 @@ public class NetworkEvents extends EventsBase {
|
|||||||
implements GenericEvent {}
|
implements GenericEvent {}
|
||||||
|
|
||||||
/** Requests to accept an existing challenge. */
|
/** Requests to accept an existing challenge. */
|
||||||
public record SendAcceptChallenge(long clientId, int challengeId)
|
public record SendAcceptChallenge(long clientId, long challengeId)
|
||||||
implements GenericEvent {}
|
implements GenericEvent {}
|
||||||
|
|
||||||
/** Requests to forfeit the current game. */
|
/** Requests to forfeit the current game. */
|
||||||
|
|||||||
@@ -5,14 +5,14 @@ import org.toop.framework.SnowflakeGenerator;
|
|||||||
public class GameChallenge {
|
public class GameChallenge {
|
||||||
private final long id = SnowflakeGenerator.nextId(); // I don't need this, but the tournament server uses it...
|
private final long id = SnowflakeGenerator.nextId(); // I don't need this, but the tournament server uses it...
|
||||||
|
|
||||||
private final ServerUser from;
|
private final User from;
|
||||||
private final ServerUser to;
|
private final User to;
|
||||||
private final String gameType;
|
private final String gameType;
|
||||||
private final SimpleTimer timer;
|
private final SimpleTimer timer;
|
||||||
|
|
||||||
private boolean isChallengeAccepted = false;
|
private boolean isChallengeAccepted = false;
|
||||||
|
|
||||||
public GameChallenge(ServerUser from, ServerUser to, String gameType, SimpleTimer timer) {
|
public GameChallenge(User from, User to, String gameType, SimpleTimer timer) {
|
||||||
this.from = from;
|
this.from = from;
|
||||||
this.to = to;
|
this.to = to;
|
||||||
this.gameType = gameType;
|
this.gameType = gameType;
|
||||||
@@ -23,8 +23,8 @@ public class GameChallenge {
|
|||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ServerUser[] getUsers() {
|
public User[] getUsers() {
|
||||||
return new ServerUser[]{from, to};
|
return new User[]{from, to};
|
||||||
}
|
}
|
||||||
|
|
||||||
public void forceExpire() {
|
public void forceExpire() {
|
||||||
@@ -37,6 +37,10 @@ public class GameChallenge {
|
|||||||
return gameType;
|
return gameType;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isChallengeAccepted() {
|
||||||
|
return isChallengeAccepted;
|
||||||
|
}
|
||||||
|
|
||||||
public boolean isExpired() {
|
public boolean isExpired() {
|
||||||
return timer.isExpired();
|
return timer.isExpired();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ import java.time.Duration;
|
|||||||
public class Server implements GameServer {
|
public class Server implements GameServer {
|
||||||
|
|
||||||
final private Map<String, Class<? extends TurnBasedGame>> gameTypes;
|
final private Map<String, Class<? extends TurnBasedGame>> gameTypes;
|
||||||
final private Map<Long, ServerUser> users = new ConcurrentHashMap<>();
|
final private Map<Long, User> users = new ConcurrentHashMap<>();
|
||||||
final private List<GameChallenge> gameChallenges = new CopyOnWriteArrayList<>();
|
final private List<GameChallenge> gameChallenges = new CopyOnWriteArrayList<>();
|
||||||
final private List<OnlineGame<TurnBasedGame>> games = new CopyOnWriteArrayList<>();
|
final private List<OnlineGame<TurnBasedGame>> games = new CopyOnWriteArrayList<>();
|
||||||
|
|
||||||
@@ -32,53 +32,53 @@ public class Server implements GameServer {
|
|||||||
scheduler.schedule(this::serverTask, 500, TimeUnit.MILLISECONDS);
|
scheduler.schedule(this::serverTask, 500, TimeUnit.MILLISECONDS);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addUser(ServerUser user) {
|
public void addUser(User user) {
|
||||||
users.putIfAbsent(user.id(), user);
|
users.putIfAbsent(user.id(), user);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void removeUser(ServerUser user) {
|
public void removeUser(User user) {
|
||||||
users.remove(user.id());
|
users.remove(user.id());
|
||||||
}
|
}
|
||||||
|
|
||||||
public String[] gameTypes() {
|
public List<String> gameTypes() {
|
||||||
return gameTypes.keySet().toArray(new String[0]);
|
return gameTypes.keySet().stream().toList();
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<OnlineGame<TurnBasedGame>> ongoingGames() {
|
public List<OnlineGame<TurnBasedGame>> ongoingGames() {
|
||||||
return games;
|
return games;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ServerUser getUser(String username) {
|
public User getUser(String username) {
|
||||||
return users.values().stream().filter(e -> e.name().equalsIgnoreCase(username)).findFirst().orElse(null);
|
return users.values().stream().filter(e -> e.name().equalsIgnoreCase(username)).findFirst().orElse(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ServerUser getUser(long id) {
|
public User getUser(long id) {
|
||||||
return users.get(id);
|
return users.get(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void challengeUser(String fromUser, String toUser, String gameType) {
|
public void challengeUser(String fromUser, String toUser, String gameType) {
|
||||||
|
|
||||||
ServerUser from = getUser(fromUser);
|
User from = getUser(fromUser);
|
||||||
if (from == null) {
|
if (from == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!gameTypes.containsKey(gameType)) {
|
if (!gameTypes.containsKey(gameType)) {
|
||||||
from.sendMessage("ERR gametype not found");
|
from.sendMessage("ERR gametype not found \n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ServerUser to = getUser(toUser);
|
User to = getUser(toUser);
|
||||||
if (to == null) {
|
if (to == null) {
|
||||||
from.sendMessage("ERR user not found");
|
from.sendMessage("ERR user not found \n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var ch = new GameChallenge(from, to, gameType, new GameChallengeTimer(challengeDuration));
|
var ch = new GameChallenge(from, to, gameType, new GameChallengeTimer(challengeDuration));
|
||||||
|
|
||||||
to.sendMessage(
|
to.sendMessage(
|
||||||
"\"SVR GAME CHALLENGE {CHALLENGER: \"%s\", GAMETYPE: \"%s\", CHALLENGENUMBER: \"%s\"}"
|
"SVR GAME CHALLENGE {CHALLENGER: \"%s\", CHALLENGENUMBER: \"%s\", GAMETYPE: \"%s\"} \n"
|
||||||
.formatted(from.name(), gameType, ch.id())
|
.formatted(from.name(), ch.id(), gameType)
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!isValidChallenge(ch)) {
|
if (!isValidChallenge(ch)) {
|
||||||
@@ -90,8 +90,8 @@ public class Server implements GameServer {
|
|||||||
gameChallenges.addLast(ch);
|
gameChallenges.addLast(ch);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void warnUserExpiredChallenge(ServerUser user, long challengeId) {
|
private void warnUserExpiredChallenge(User user, long challengeId) {
|
||||||
user.sendMessage("SVR GAME CHALLENGE CANCELLED {CHALLENGENUMBER: \"" + challengeId + "\"}");
|
user.sendMessage("SVR GAME CHALLENGE CANCELLED {CHALLENGENUMBER: \"" + challengeId + "\"}" + "\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isValidChallenge(GameChallenge gameChallenge) {
|
private boolean isValidChallenge(GameChallenge gameChallenge) {
|
||||||
@@ -119,7 +119,9 @@ public class Server implements GameServer {
|
|||||||
if (isValidChallenge(challenge)) continue;
|
if (isValidChallenge(challenge)) continue;
|
||||||
|
|
||||||
if (challenge.isExpired()) {
|
if (challenge.isExpired()) {
|
||||||
Arrays.stream(challenge.getUsers()).forEach(user -> warnUserExpiredChallenge(user, challenge.id()));
|
if (!challenge.isChallengeAccepted()) Arrays.stream(challenge.getUsers())
|
||||||
|
.forEach(user -> warnUserExpiredChallenge(user, challenge.id()));
|
||||||
|
|
||||||
gameChallenges.remove(i);
|
gameChallenges.remove(i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -128,7 +130,7 @@ public class Server implements GameServer {
|
|||||||
public void acceptChallenge(long challengeId) {
|
public void acceptChallenge(long challengeId) {
|
||||||
for (var challenge : gameChallenges) {
|
for (var challenge : gameChallenges) {
|
||||||
if (challenge.id() == challengeId) {
|
if (challenge.id() == challengeId) {
|
||||||
startGame(challenge.acceptChallenge(), (User[]) challenge.getUsers());
|
startGame(challenge.acceptChallenge(), challenge.getUsers());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -162,8 +164,8 @@ public class Server implements GameServer {
|
|||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
|
|
||||||
public String[] onlineUsers() {
|
public List<User> onlineUsers() {
|
||||||
return users.values().stream().map(ServerUser::name).toArray(String[]::new);
|
return users.values().stream().toList();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void closeServer() {
|
public void closeServer() {
|
||||||
|
|||||||
@@ -2,8 +2,10 @@ package org.toop.framework.networking.server;
|
|||||||
|
|
||||||
import io.netty.channel.ChannelHandlerContext;
|
import io.netty.channel.ChannelHandlerContext;
|
||||||
import io.netty.channel.SimpleChannelInboundHandler;
|
import io.netty.channel.SimpleChannelInboundHandler;
|
||||||
|
import org.apache.maven.surefire.shared.utils.StringUtils;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
import java.util.Iterator;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@@ -17,6 +19,10 @@ public class ServerHandler extends SimpleChannelInboundHandler<String> {
|
|||||||
this.server = server;
|
this.server = server;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private String returnQuotedString(Iterator<String> strings) { // TODO more places this could be useful
|
||||||
|
return "\"" + StringUtils.join(strings, "\",\"") + "\"";
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void channelActive(ChannelHandlerContext ctx) {
|
public void channelActive(ChannelHandlerContext ctx) {
|
||||||
ctx.writeAndFlush("WELCOME " + user.id() + "\n");
|
ctx.writeAndFlush("WELCOME " + user.id() + "\n");
|
||||||
@@ -27,6 +33,9 @@ public class ServerHandler extends SimpleChannelInboundHandler<String> {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void channelRead0(ChannelHandlerContext ctx, String msg) {
|
protected void channelRead0(ChannelHandlerContext ctx, String msg) {
|
||||||
|
|
||||||
|
IO.println(msg);
|
||||||
|
|
||||||
ParsedMessage p = parse(msg);
|
ParsedMessage p = parse(msg);
|
||||||
if (p == null) return;
|
if (p == null) return;
|
||||||
|
|
||||||
@@ -61,8 +70,14 @@ public class ServerHandler extends SimpleChannelInboundHandler<String> {
|
|||||||
if (!allowedArgs(p.args())) return;
|
if (!allowedArgs(p.args())) return;
|
||||||
|
|
||||||
switch (p.args()[0]) {
|
switch (p.args()[0]) {
|
||||||
case "playerlist" -> user.ctx().writeAndFlush(Arrays.toString(server.onlineUsers()));
|
case "playerlist" -> {
|
||||||
case "gamelist" -> user.ctx().writeAndFlush(Arrays.toString(server.gameTypes()));
|
var names = server.onlineUsers().stream().map(ServerUser::name).iterator();
|
||||||
|
user.ctx().writeAndFlush("SVR PLAYERLIST " + returnQuotedString(names) + "\n");
|
||||||
|
}
|
||||||
|
case "gamelist" -> {
|
||||||
|
var names = server.gameTypes().stream().iterator();
|
||||||
|
user.ctx().writeAndFlush("SVR GAMELIST " + returnQuotedString(names) + "\n");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -87,14 +102,14 @@ public class ServerHandler extends SimpleChannelInboundHandler<String> {
|
|||||||
long id = Long.parseLong(p.args()[1]);
|
long id = Long.parseLong(p.args()[1]);
|
||||||
|
|
||||||
if (id <= 0) {
|
if (id <= 0) {
|
||||||
user.sendMessage("ERR id must be a positive number");
|
user.sendMessage("ERR id must be a positive number \n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
server.acceptChallenge(id);
|
server.acceptChallenge(id);
|
||||||
|
|
||||||
} catch (NumberFormatException e) {
|
} catch (NumberFormatException e) {
|
||||||
user.sendMessage("ERR id is not a valid number or too big");
|
user.sendMessage("ERR id is not a valid number or too big \n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
|
|||||||
Reference in New Issue
Block a user