barebones quite working but awful multiplayer base. Still no players updating each other. Switching to kryonet from now on

master
EmaMaker 2020-04-19 00:53:39 +02:00
parent 0a85762a93
commit 5565615a8a
5 changed files with 154 additions and 99 deletions

View File

@ -3,13 +3,20 @@ package com.emamaker.amazeing.manager;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.UUID;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Input.Keys;
import com.badlogic.gdx.Net.Protocol;
import com.badlogic.gdx.net.Socket;
import com.badlogic.gdx.net.SocketHints;
import com.emamaker.amazeing.AMazeIng;
import com.emamaker.amazeing.player.MazePlayer;
import com.emamaker.amazeing.player.MazePlayerLocal;
import com.emamaker.amazeing.player.MazePlayerRemote;
public class GameClient {
@ -22,11 +29,18 @@ public class GameClient {
public Socket socket;
volatile String nextMessage = "";
String s = "", s1 = "", rMsg = "";
String map = "", s1 = "", rMsg = "", playerList = "";
UUID uuid;
int connectionStep;
BufferedReader buffer;
// Hashtable of remote players present in the match. This will be used to update
// other players' transform when server reports about it
Hashtable<UUID, MazePlayerRemote> remotePlayers = new Hashtable<>();
ArrayList<MazePlayer> players = new ArrayList<MazePlayer>();
public GameClient(AMazeIng main_) {
main = main_;
}
@ -44,17 +58,17 @@ public class GameClient {
SocketHints socketHints = new SocketHints();
socketHints.connectTimeout = 10000;
socket = Gdx.net.newClientSocket(Protocol.TCP, addr, port, socketHints);
buffer = new BufferedReader(new InputStreamReader(socket.getInputStream()));
sendMessageToSocket(socket, "AO");
connectionStep = 0;
} else {
if (socket.isConnected()) {
rMsg = receiveMessageFromSocket(socket);
rMsg = receiveMessageFromSocket();
if (rMsg.startsWith("UUID")) {
// UUID received from server, go on
//it doesn't matter if this already happened, just start again
//No new UUID will be generated
// it doesn't matter if this already happened, just start again
// No new UUID will be generated
s1 = rMsg.replace("UUID", "");
uuid = UUID.fromString(s1);
connectionStep = 1;
@ -68,7 +82,10 @@ public class GameClient {
System.out.println("Connected with server!");
}
}
if (rMsg.startsWith("Players"))
playerList = rMsg.replace("Players", "");
if (rMsg.startsWith("Map"))
map = rMsg.replace("Map", "");
}
}
}
@ -80,6 +97,29 @@ public class GameClient {
// Update must be called from Main thread and used for applications on main
// thread
public void update() {
if (!playerList.equals("")) {
// Build up player list
String[] uuids = playerList.split("!");
for (String s : uuids) {
// System.out.println(s);
if (!s.equals(uuid.toString()))
remotePlayers.put(UUID.fromString(s), new MazePlayerRemote(main, UUID.fromString(s)));
}
playerList = "";
}
if (!map.equals("")) {
// Build up map
for (UUID u : remotePlayers.keySet()) {
if (!u.equals(uuid))
players.add(remotePlayers.get(u));
}
players.add(new MazePlayerLocal(main, Keys.W, Keys.S, Keys.A, Keys.D));
main.gameManager.generateMaze(new HashSet<MazePlayer>(players),
main.gameManager.mazeGen.runLenghtDecode(map));
main.gameManager.setShowGame(true);
map = "";
}
}
public void sendMessagetoServer(String s) {
@ -103,15 +143,14 @@ public class GameClient {
String tmprs;
String receiveMessageFromSocket(Socket s) {
if (s != null && s.isConnected())
String receiveMessageFromSocket() {
if (socket != null && socket.isConnected())
// Receive messages from the client
try {
if (s.getInputStream().available() > 0) {
BufferedReader buffer = new BufferedReader(new InputStreamReader(s.getInputStream()));
if (socket.getInputStream().available() > 0) {
// Read to the next newline (\n) and display that text on labelMessage
tmprs = buffer.readLine();
System.out.println("Client received message From: " + s + "!\n" + tmprs);
System.out.println("Client received message! " + tmprs);
return tmprs;
}
} catch (IOException e) {

View File

@ -14,14 +14,16 @@ import com.emamaker.voxelengine.player.Player;
public class GameManager {
/* Local manager for local games and server host in multiplayer games */
AMazeIng main;
public MazeGenerator mazeGen;
public boolean gameStarted = false;
Random rand = new Random();
/* Local manager for local games and server host in multiplayer games */
public GameServer server;
public GameClient client;
AMazeIng main;
public boolean gameStarted = false;
public boolean showGame = true;
Random rand = new Random();
ArrayList<MazePlayer> players = new ArrayList<MazePlayer>();
@ -45,12 +47,12 @@ public class GameManager {
mazeGen.h / 2);
main.world.cam.lookAt(MazeSettings.MAZEX / 2, 0, MazeSettings.MAZEX / 2);
main.world.cam.update();
main.world.render();
if(showGame) main.world.render();
main.world.modelBatch.begin(main.world.cam);
if (players != null) {
for (MazePlayer p : players) {
p.render(main.world.modelBatch, main.world.environment);
if(showGame) p.render(main.world.modelBatch, main.world.environment);
anyoneWon = false;
if (checkWin(p)) {
anyoneWon = true;
@ -184,6 +186,14 @@ public class GameManager {
return false;
}
public boolean getShowGame() {
return showGame;
}
public void setShowGame(boolean g) {
showGame = g;
}
public void generateMaze() {
generateMaze(null, null);

View File

@ -5,10 +5,14 @@ import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.LinkedList;
import java.util.Queue;
import java.util.UUID;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Input.Keys;
import com.badlogic.gdx.Net.Protocol;
import com.badlogic.gdx.net.ServerSocket;
import com.badlogic.gdx.net.ServerSocketHints;
@ -17,6 +21,7 @@ import com.badlogic.gdx.net.SocketHints;
import com.badlogic.gdx.utils.GdxRuntimeException;
import com.emamaker.amazeing.AMazeIng;
import com.emamaker.amazeing.player.MazePlayer;
import com.emamaker.amazeing.player.MazePlayerLocal;
import com.emamaker.amazeing.player.MazePlayerRemote;
public class GameServer {
@ -26,9 +31,11 @@ public class GameServer {
volatile boolean serverRunning = false;
volatile String nextMessage = "";
volatile String rMsg;
public ServerSocket serverSocket = null;
public int port;
UUID uuid ;
Socket s;
Thread serverThread;
@ -54,6 +61,7 @@ public class GameServer {
public GameServer(AMazeIng main_) {
main = main_;
uuid = UUID.randomUUID();
}
public void startServer(int port_) {
@ -84,67 +92,67 @@ public class GameServer {
// System.out.println("No new clients connected in the last 1000 milliseconds");
}
System.out.println(Arrays.toString(tmpPlayers.keySet().toArray()));
System.out.println(Arrays.toString(remotePlayers.keySet().toArray()));
if(!main.gameManager.gameStarted) {
for (Socket s : tmpPlayers.keySet()) {
if (s.isConnected()) {
rMsg = receiveMessageFromSocket(s);
System.out.println(rMsg);
if (rMsg.equals("AO")) {
// Step 0
if (tmpPlayers.get(s).step == 0) {
// We're at the right step, send uuid to client
sendMessageToSocket(s, "UUID" + tmpPlayers.get(s).uuid.toString());
} else {
// Wrong step
System.out.println("Client already connected, ignoring request");
// System.out.println(Arrays.toString(tmpPlayers.keySet().toArray()));
// System.out.println(Arrays.toString(remotePlayers.keySet().toArray()));
if (!main.gameManager.gameStarted) {
for (Socket s : tmpPlayers.keySet()) {
if (s.isConnected()) {
rMsg = receiveMessageFromSocket(s);
System.out.println(rMsg);
if (rMsg.equals("AO")) {
// Step 0
if (tmpPlayers.get(s).step == 0) {
// We're at the right step, send uuid to client
sendMessageToSocket(s, "UUID" + tmpPlayers.get(s).uuid.toString());
} else {
// Wrong step
System.out.println("Client already connected, ignoring request");
}
// If receiving multiple AOs, just start back from this point
tmpPlayers.get(s).step = 1;
} else if (rMsg.equals("AO2")) {
if (tmpPlayers.get(s).step == 1) {
System.out.println("Client " + s + " accepted uuid");
sendMessageToSocket(s, "AO3");
tmpPlayers.get(s).step = 2;
}
} else if (rMsg.equals("AO4")) {
if (tmpPlayers.get(s).step == 2) {
// Player can now be added to the remote player list, but this has to be done
// inside the main thread, and this bit of code is executed outside, so pass it
// to another function for use
newPlayers.add(s);
}
}
// If receiving multiple AOs, just start back from this point
tmpPlayers.get(s).step = 1;
} else {
// Cliented timed out, remove it from the list :(
tmpPlayers.remove(s);
}
if (rMsg.equals("AO2")) {
if (tmpPlayers.get(s).step == 1) {
System.out.println("Client " + s + " accepted uuid");
sendMessageToSocket(s, "AO3");
tmpPlayers.get(s).step = 2;
}
}
if (rMsg.equals("AO4")) {
if (tmpPlayers.get(s).step == 2) {
// Player can now be added to the remote player list, but this has to be done
// inside the main thread, and this bit of code is executed outside, so pass it
// to another function for use
newPlayers.add(s);
}
}
} else {
// Cliented timed out, remove it from the list :(
tmpPlayers.remove(s);
}
}
}
for (Socket s : tmpPlayers.keySet()) {
nextMessage = "";
if (!messages.isEmpty())
nextMessage = messages.remove();
for (Socket s : remotePlayers.keySet()) {
if (s.isConnected()) {
if (!nextMessage.equals("")) {
sendMessageToSocket(s, nextMessage);
}
} else {
// Cliented timed out, remove it from the list :(
remotePlayers.remove(s);
}
}
}
}
});
serverThread.start();
}
public void sendMessagetoClients(String s) {
nextMessage += (s + "\n");
//Also start client to play on the local machine
main.gameManager.client.start("localhost", port);
}
// Update must be called from Main thread and used for applications on main
@ -152,7 +160,8 @@ public class GameServer {
public void update() {
// Spawn new players if needed
for (Socket s : newPlayers) {
remotePlayers.put(s, new FullPlayerEntry(s, tmpPlayers.get(s).uuid, new MazePlayerRemote(main, s)));
remotePlayers.put(s,
new FullPlayerEntry(s, tmpPlayers.get(s).uuid, new MazePlayerRemote(main, tmpPlayers.get(s).uuid)));
System.out.println("Accepted new player: " + s.toString() + " " + tmpPlayers.get(s).uuid.toString());
tmpPlayers.remove(s);
}
@ -164,12 +173,25 @@ public class GameServer {
// 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
public void startGame() {
// ArrayList<MazePlayer> players = new ArrayList<>();
// for(MazePlayer p : remotePlayers.values() ) players.add(p);
// players.add(new MazePlayerLocal(main, Keys.W, Keys.S, Keys.A, Keys.D));
// System.out.println(Arrays.toString(players.toArray()));
// main.gameManager.generateMaze(new HashSet<MazePlayer>(players));
// sendMessagetoClients("Map" + main.gameManager.mazeGen.runLenghtEncode());
update();
ArrayList<MazePlayer> players = new ArrayList<>();
for (FullPlayerEntry p : remotePlayers.values())
players.add(p.player);
sendMessagetoClients("Players" + buildUUIDList());
main.gameManager.generateMaze(new HashSet<MazePlayer>(players));
main.gameManager.setShowGame(false);
sendMessagetoClients("Map" + main.gameManager.mazeGen.runLenghtEncode());
}
public String buildUUIDList() {
String s = uuid.toString() + "!";
for (FullPlayerEntry p : remotePlayers.values()) {
s += p.uuid.toString() + "!";
}
System.out.println(s);
return s;
}
public void stop() {
@ -180,6 +202,13 @@ public class GameServer {
serverRunning = false;
}
Queue<String> messages = new LinkedList<>();
public void sendMessagetoClients(String s) {
messages.add(s + "\n");
System.out.println("Sending message to clients: " + nextMessage);
}
void sendMessageToSocket(Socket s, String msg) {
if (s != null && s.isConnected())
if (!msg.equals(""))

View File

@ -178,6 +178,7 @@ public class MazeGenerator {
System.out.println(Arrays.deepToString(rows));
//Mazes are always squares
todraw = new int[rows.length][rows.length];
setMazeSize(rows.length, rows.length);
for(int i = 0; i < rows.length; i++) {
totalcount = 0;

View File

@ -1,15 +1,9 @@
package com.emamaker.amazeing.player;
import java.util.Random;
import java.util.UUID;
import com.badlogic.gdx.Game;
import com.badlogic.gdx.controllers.Controller;
import com.badlogic.gdx.graphics.VertexAttributes;
import com.badlogic.gdx.graphics.g3d.Model;
import com.badlogic.gdx.graphics.g3d.ModelInstance;
import com.badlogic.gdx.graphics.g3d.utils.MeshPartBuilder;
import com.badlogic.gdx.graphics.g3d.utils.ModelBuilder;
import com.badlogic.gdx.net.Socket;
import com.emamaker.amazeing.AMazeIng;
public class MazePlayerRemote extends MazePlayer{
@ -18,26 +12,15 @@ public class MazePlayerRemote extends MazePlayer{
static Random rand = new Random();
// MazePlayer model building stuff
public Model mazePlayerModel;
public ModelInstance instance;
ModelBuilder modelBuilder = new ModelBuilder();
MeshPartBuilder meshBuilder;
static int meshAttr = VertexAttributes.Usage.Position | VertexAttributes.Usage.Normal;
public Controller ctrl;
// Physics using LibGDX's bullet wrapper
public int kup, kdown, ksx, kdx;
float startx, starty, startz;
String name;
AMazeIng main;
Socket socket;
UUID uuid;
boolean disposing = false;
public MazePlayerRemote(Game main_, Socket s) {
public MazePlayerRemote(Game main_, UUID u) {
super(main_);
socket = s;
uuid = u;
}
public void updateRemoteTransform(String s) {
@ -62,11 +45,4 @@ public class MazePlayerRemote extends MazePlayer{
public void update() {
}
@Override
public void dispose() {
disposing = true;
mazePlayerModel.dispose();
disposing = false;
}
}