Continous information between server and client now working correctly

master
EmaMaker 2020-04-17 13:28:25 +02:00
parent 15979d1d5a
commit ab89f9e348
6 changed files with 266 additions and 135 deletions

View File

@ -0,0 +1,63 @@
package com.emamaker.amazeing.manager;
import java.io.IOException;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Net.Protocol;
import com.badlogic.gdx.net.Socket;
import com.badlogic.gdx.net.SocketHints;
import com.emamaker.amazeing.AMazeIng;
public class GameClient {
volatile boolean clientRunning = false;
public Socket socket;
public String addr;
public int port;
Thread clientThread;
public AMazeIng main;
public GameClient(AMazeIng main_) {
main = main_;
}
public void start(String addr_, int port_) {
port = port_;
addr = addr_;
clientThread = new Thread(new Runnable() {
@Override
public void run() {
clientRunning = true;
while (clientRunning) {
/*
* https://www.gamefromscratch.com/post/2014/03/11/LibGDX-Tutorial-10-Basic-
* networking.aspx
*/
if (socket == null) {
SocketHints socketHints = new SocketHints();
socketHints.connectTimeout = 0;
socket = Gdx.net.newClientSocket(Protocol.TCP, addr, port, socketHints);
System.out.println("Connected to server!");
} else {
if (socket.isConnected()) {
// Send messages to the server:
try {
// write our entered message to the stream
socket.getOutputStream().write("AO\n".getBytes());
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
});
clientThread.start();
}
public void stop() {
clientRunning = false;
}
}

View File

@ -5,28 +5,32 @@ import java.util.Random;
import java.util.Set;
import com.badlogic.gdx.Game;
import com.badlogic.gdx.math.Vector3;
import com.emamaker.amazeing.AMazeIng;
import com.emamaker.amazeing.maze.MazeGenerator;
import com.emamaker.amazeing.maze.settings.MazeSettings;
import com.emamaker.amazeing.player.MazePlayer;
import com.emamaker.voxelengine.block.CellId;
import com.emamaker.voxelengine.player.Player;
import com.emamaker.voxelengine.utils.VoxelSettings;
public class GameManager {
/*Local manager for local games and server host in multiplayer games*/
public MazeGenerator mazeGen;
public boolean gameStarted = false;
Random rand = new Random();
public GameServer server;
public GameClient client;
AMazeIng main;
ArrayList<MazePlayer> players = new ArrayList<MazePlayer>();
public GameManager(Game main_) {
main = (AMazeIng) main_;
gameStarted = false;
server = new GameServer(main);
client = new GameClient(main);
// Maze Generation
mazeGen = new MazeGenerator(main, MazeSettings.MAZEX, MazeSettings.MAZEZ);
}
@ -41,13 +45,15 @@ public class GameManager {
main.world.render();
main.world.modelBatch.begin(main.world.cam);
for (MazePlayer p : players) {
p.render(main.world.modelBatch, main.world.environment);
anyoneWon = false;
if (checkWin(p)) {
anyoneWon = true;
gameStarted = false;
break;
if(players != null) {
for (MazePlayer p : players) {
p.render(main.world.modelBatch, main.world.environment);
anyoneWon = false;
if (checkWin(p)) {
anyoneWon = true;
gameStarted = false;
break;
}
}
}
@ -63,21 +69,23 @@ public class GameManager {
// Only add new players and dispose the old ones
//Check if actually there are players to be deleted
for (MazePlayer p : players)
if (!pl.contains(p))
toDelete.add(p);
if(pl != null) {
for (MazePlayer p : players)
if (!pl.contains(p))
toDelete.add(p);
//Check if new players have to be added
for (MazePlayer p : pl)
if (!players.contains(p))
players.add(p);
//Check if new players have to be added
for (MazePlayer p : pl)
if (!players.contains(p))
players.add(p);
//Fianlly delete players. A separated step is needed to remove the risk of a ConcurrentModificationException
for(MazePlayer p : toDelete) {
p.dispose();
players.remove(p);
//Fianlly delete players. A separated step is needed to remove the risk of a ConcurrentModificationException
for(MazePlayer p : toDelete) {
p.dispose();
players.remove(p);
}
toDelete.clear();
}
toDelete.clear();
// destroyPlayers();
// players.addAll(p);
@ -169,6 +177,8 @@ public class GameManager {
}
public void dispose() {
client.stop();
server.stop();
for (MazePlayer p : players)
p.dispose();
}

View File

@ -0,0 +1,98 @@
package com.emamaker.amazeing.manager;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Arrays;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Net.Protocol;
import com.badlogic.gdx.net.ServerSocket;
import com.badlogic.gdx.net.ServerSocketHints;
import com.badlogic.gdx.net.Socket;
import com.badlogic.gdx.net.SocketHints;
import com.badlogic.gdx.utils.GdxRuntimeException;
import com.emamaker.amazeing.AMazeIng;
public class GameServer {
volatile boolean serverRunning = false;
String nextMessage = "oa";
public ServerSocket serverSocket = null;
public int port;
ArrayList<Socket> clientSockets = new ArrayList<Socket>();
Thread serverThread;
public AMazeIng main;
Socket s;
SocketHints socketHints = new SocketHints();
ServerSocketHints serverSocketHint = new ServerSocketHints();
public GameServer(AMazeIng main_) {
main = main_;
}
public void startServer(int port_) {
port = port_;
serverSocketHint.acceptTimeout = 100;
serverThread = new Thread(new Runnable() {
@Override
public void run() {
serverRunning = true;
while (serverRunning) {
if (serverSocket == null) {
serverSocket = Gdx.net.newServerSocket(Protocol.TCP, port, serverSocketHint);
System.out.println("Server started and listening for connections!");
}
try {
Socket socket = serverSocket.accept(null);
if (socket != null && !clientSockets.contains(socket)) {
clientSockets.add(socket);
System.out.println("Accepted new client: " + socket);
}
} catch (GdxRuntimeException se) {
// System.out.println("No new clients connected in the last 100 milliseconds");
}
for (Socket s : clientSockets) {
System.out.println(s);
// Receive messages from the server
try {
BufferedReader buffer = new BufferedReader(new InputStreamReader(s.getInputStream()));
// Read to the next newline (\n) and display that text on labelMessage
System.out.println("Server received message From: " + s + "!\n" + buffer.readLine());
} catch (IOException e) {
// e.printStackTrace();
}
}
}
}
});
serverThread.start();
}
public void startGame() {
// Once the server has started accepting connections from other players, the
// host should decide when to start the gmae
// A proper ui should be added, but for now we can just start the game without
// showing any players and just show the map across all the clients
// To spread the map we can just encode in a string the todraw[][] array in
// MazeGenerator, in future run-lenght encoding should be considered
main.gameManager.generateMaze(null);
nextMessage = "Map" + Arrays.deepToString(main.gameManager.mazeGen.todraw);
}
public void stop() {
if (serverSocket != null) {
serverSocket.dispose();
serverSocket = null;
}
serverRunning = false;
}
}

View File

@ -108,7 +108,7 @@ public class MazeGenerator {
currentCell.current = true;
}
}
prepareShow();
prepareShow(todraw);
}
//Setup end point in a random location. At a distance of EP_DIST from every player
@ -128,7 +128,7 @@ public class MazeGenerator {
main.world.worldManager.setCell(WINX, 0, WINZ, CellId.ID_WOOD);
}
public void prepareShow() {
public void prepareShow(int[][] todraw_) {
for (int i = 0; i < w; i++) {
for (int j = 0; j < h; j++) {
todraw[i][j] = 1;
@ -143,20 +143,20 @@ public class MazeGenerator {
int y = 2 * j + 1;
// current cell
todraw[x][y] = 0;
todraw_[x][y] = 0;
// up wall
if (!cellsGrid[i][j].walls[0])
todraw[x][y - 1] = 0;
todraw_[x][y - 1] = 0;
// down wall
if (!cellsGrid[i][j].walls[2])
todraw[x][y + 1] = 0;
todraw_[x][y + 1] = 0;
// left wall
if (!cellsGrid[i][j].walls[3])
todraw[x - 1][y] = 0;
todraw_[x - 1][y] = 0;
// right all
if (!cellsGrid[i][j].walls[1])
todraw[x + 1][y] = 0;
todraw_[x + 1][y] = 0;
}
}
@ -164,7 +164,7 @@ public class MazeGenerator {
for (int j = 0; j < h; j++) {
for (int i = 0; i < w; i++) {
main.world.worldManager.setCell(i, 0, j, CellId.ID_GRASS);
if (todraw[i][j] == 1)
if (todraw_[i][j] == 1)
main.world.worldManager.setCell(i, 1, j, CellId.ID_LEAVES);
// if (todraw[i][j] == 2)
// main.world.worldManager.setCell(i, 0, j, CellId.ID_WOOD);

View File

@ -1,13 +1,8 @@
package com.emamaker.amazeing.ui.screens;
import java.io.IOException;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Net.Protocol;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.Screen;
import com.badlogic.gdx.net.Socket;
import com.badlogic.gdx.net.SocketHints;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.scenes.scene2d.InputEvent;
import com.badlogic.gdx.scenes.scene2d.InputListener;
import com.badlogic.gdx.scenes.scene2d.Stage;
@ -20,7 +15,7 @@ import com.badlogic.gdx.utils.Align;
import com.badlogic.gdx.utils.viewport.ScreenViewport;
import com.emamaker.amazeing.ui.UIManager;
public class ServerJoinScreen implements Screen{
public class ServerJoinScreen implements Screen {
Stage stage;
UIManager uiManager;
@ -43,14 +38,15 @@ public class ServerJoinScreen implements Screen{
TextButton backBtn = new TextButton("Main menu", uiManager.skin);
TextButton connectBtn = new TextButton("Connect to the server!", uiManager.skin);
TextButton helpBtn = new TextButton("?", uiManager.skin);
final TextArea srvIp = new TextArea("Server IP Address", uiManager.skin);
final TextArea srvPort = new TextArea("Server Port", uiManager.skin);
final TextArea srvIp = new TextArea("localhost", uiManager.skin);
final TextArea srvPort = new TextArea("9999", uiManager.skin);
// Add actions to the buttons
backBtn.addListener(new InputListener() {
@Override
public boolean touchDown(InputEvent event, float x, float y, int pointer, int button) {
hide();
uiManager.main.gameManager.client.stop();
uiManager.main.setScreen(uiManager.titleScreen);
return true;
}
@ -65,28 +61,20 @@ public class ServerJoinScreen implements Screen{
connectBtn.addListener(new InputListener() {
@Override
public boolean touchDown(InputEvent event, float x, float y, int pointer, int button) {
/*https://www.gamefromscratch.com/post/2014/03/11/LibGDX-Tutorial-10-Basic-networking.aspx*/
SocketHints socketHints = new SocketHints();
// Socket will time our in 4 seconds
socketHints.connectTimeout = 4000;
//create the socket and connect to the server entered in the text box ( x.x.x.x format ) on port 9021
Socket socket = Gdx.net.newClientSocket(Protocol.TCP, srvIp.getText(), Integer.valueOf(srvPort.getText()), socketHints);
try {
// write our entered message to the stream
socket.getOutputStream().write("AO\n".getBytes());
} catch (IOException e) {
e.printStackTrace();
}
return true;
try {
uiManager.main.gameManager.client.start(srvIp.getText(), Integer.valueOf(srvPort.getText()));
}catch(Exception e) {
System.out.println("Please input a valid ip address and port");
}
return true;
}
});
Table firstRowTable = new Table();
firstRowTable.add(backBtn).fillX().expandX().space(cw*0.005f);
firstRowTable.add(instLab).height(50).fillX().expandX().space(cw*0.25f);
firstRowTable.add(helpBtn).width(50).height(50).fillX().expandX().space(cw*0.005f);
firstRowTable.add(backBtn).fillX().expandX().space(cw * 0.005f);
firstRowTable.add(instLab).height(50).fillX().expandX().space(cw * 0.25f);
firstRowTable.add(helpBtn).width(50).height(50).fillX().expandX().space(cw * 0.005f);
firstRowTable.setOrigin(Align.center | Align.top);
table.row().colspan(4);
@ -111,10 +99,10 @@ public class ServerJoinScreen implements Screen{
@Override
public void render(float delta) {
Gdx.gl.glClearColor(0,0,0,0);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
stage.act();
stage.draw();
Gdx.gl.glClearColor(0, 0, 0, 0);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
stage.act();
stage.draw();
}
@Override
@ -126,6 +114,7 @@ public class ServerJoinScreen implements Screen{
public void hide() {
uiManager.main.multiplexer.removeProcessor(stage);
}
@Override
public void pause() {
}

View File

@ -1,16 +1,8 @@
package com.emamaker.amazeing.ui.screens;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Net.Protocol;
import com.badlogic.gdx.Screen;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.net.ServerSocket;
import com.badlogic.gdx.net.ServerSocketHints;
import com.badlogic.gdx.net.Socket;
import com.badlogic.gdx.scenes.scene2d.InputEvent;
import com.badlogic.gdx.scenes.scene2d.InputListener;
import com.badlogic.gdx.scenes.scene2d.Stage;
@ -23,7 +15,7 @@ import com.badlogic.gdx.utils.Align;
import com.badlogic.gdx.utils.viewport.ScreenViewport;
import com.emamaker.amazeing.ui.UIManager;
public class ServerLaunchScreen implements Screen{
public class ServerLaunchScreen implements Screen {
Stage stage;
UIManager uiManager;
@ -43,16 +35,18 @@ public class ServerLaunchScreen implements Screen{
tableContainer.setPosition(0, 0);
Label instLab = new Label("Enter the port the server should start on", uiManager.skin);
TextButton backBtn = new TextButton("Main menu", uiManager.skin);
TextButton backBtn = new TextButton("Main menu and quit server", uiManager.skin);
TextButton connectBtn = new TextButton("Launch the server!", uiManager.skin);
TextButton gameBtn = new TextButton("Launch the game!", uiManager.skin);
TextButton helpBtn = new TextButton("?", uiManager.skin);
final TextArea srvPort = new TextArea("Server Port", uiManager.skin);
final TextArea srvPort = new TextArea("9999", uiManager.skin);
// Add actions to the buttons
backBtn.addListener(new InputListener() {
@Override
public boolean touchDown(InputEvent event, float x, float y, int pointer, int button) {
hide();
uiManager.main.gameManager.server.stop();
uiManager.main.setScreen(uiManager.titleScreen);
return true;
}
@ -67,49 +61,22 @@ public class ServerLaunchScreen implements Screen{
connectBtn.addListener(new InputListener() {
@Override
public boolean touchDown(InputEvent event, float x, float y, int pointer, int button) {
/*https://www.gamefromscratch.com/post/2014/03/11/LibGDX-Tutorial-10-Basic-networking.aspx*/
// Now we create a thread that will listen for incoming socket connections
new Thread(new Runnable(){
@Override
public void run() {
ServerSocketHints serverSocketHint = new ServerSocketHints();
// 0 means no timeout. Probably not the greatest idea in production!
serverSocketHint.acceptTimeout = 0;
// Create the socket server using TCP protocol and listening on 9021
// Only one app can listen to a port at a time, keep in mind many ports are reserved
// especially in the lower numbers ( like 21, 80, etc )
ServerSocket serverSocket = Gdx.net.newServerSocket(Protocol.TCP, Integer.valueOf(srvPort.getText()), serverSocketHint);
// Loop forever
while(true){
// Create a socket
Socket socket = serverSocket.accept(null);
// Read data from the socket into a BufferedReader
BufferedReader buffer = new BufferedReader(new InputStreamReader(socket.getInputStream()));
try {
// Read to the next newline (\n) and display that text on labelMessage
System.out.println("Server received message!");
System.out.println(buffer.readLine());
} catch (IOException e) {
e.printStackTrace();
}
}
}
}).start(); // And, start the thread running
return true;
uiManager.main.gameManager.server.startServer(Integer.valueOf(srvPort.getText()));
return true;
}
});
gameBtn.addListener(new InputListener() {
@Override
public boolean touchDown(InputEvent event, float x, float y, int pointer, int button) {
uiManager.main.gameManager.server.startGame();
return true;
}
});
Table firstRowTable = new Table();
firstRowTable.add(backBtn).fillX().expandX().space(cw*0.005f);
firstRowTable.add(instLab).height(50).fillX().expandX().space(cw*0.25f);
firstRowTable.add(helpBtn).width(50).height(50).fillX().expandX().space(cw*0.005f);
firstRowTable.add(backBtn).fillX().expandX().space(cw * 0.005f);
firstRowTable.add(instLab).height(50).fillX().expandX().space(cw * 0.25f);
firstRowTable.add(helpBtn).width(50).height(50).fillX().expandX().space(cw * 0.005f);
firstRowTable.setOrigin(Align.center | Align.top);
table.row().colspan(4);
@ -121,6 +88,9 @@ public class ServerLaunchScreen implements Screen{
table.row().colspan(4);
table.add(connectBtn).fillX().expandX();
table.row().colspan(4);
table.add(gameBtn).fillX().expandX();
tableContainer.setActor(table);
stage.addActor(tableContainer);
}
@ -132,10 +102,10 @@ public class ServerLaunchScreen implements Screen{
@Override
public void render(float delta) {
Gdx.gl.glClearColor(0,0,0,0);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
stage.act();
stage.draw();
Gdx.gl.glClearColor(0, 0, 0, 0);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
stage.act();
stage.draw();
}
@Override
@ -147,6 +117,7 @@ public class ServerLaunchScreen implements Screen{
public void hide() {
uiManager.main.multiplexer.removeProcessor(stage);
}
@Override
public void pause() {
}