Server-client connection protocol using UUIDs
parent
8f02390188
commit
0a85762a93
|
@ -46,13 +46,13 @@ public class AMazeIng extends Game {
|
|||
}
|
||||
|
||||
public void setupGUI() {
|
||||
uiManager = new UIManager(this);
|
||||
System.out.println("Setup UI Manager");
|
||||
uiManager = new UIManager(this);
|
||||
}
|
||||
|
||||
public void setupGameManager() {
|
||||
gameManager = new GameManager(this);
|
||||
System.out.println("Setup Game Manager");
|
||||
gameManager = new GameManager(this);
|
||||
}
|
||||
|
||||
float delta;
|
||||
|
|
|
@ -3,6 +3,7 @@ package com.emamaker.amazeing.manager;
|
|||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.util.UUID;
|
||||
|
||||
import com.badlogic.gdx.Gdx;
|
||||
import com.badlogic.gdx.Net.Protocol;
|
||||
|
@ -12,14 +13,19 @@ import com.emamaker.amazeing.AMazeIng;
|
|||
|
||||
public class GameClient {
|
||||
|
||||
public AMazeIng main;
|
||||
Thread clientThread;
|
||||
volatile boolean clientRunning = false;
|
||||
volatile String nextMessage = "";
|
||||
public Socket socket;
|
||||
String s = "", s1 = "";
|
||||
|
||||
public String addr;
|
||||
public int port;
|
||||
Thread clientThread;
|
||||
public AMazeIng main;
|
||||
public Socket socket;
|
||||
|
||||
volatile String nextMessage = "";
|
||||
String s = "", s1 = "", rMsg = "";
|
||||
|
||||
UUID uuid;
|
||||
int connectionStep;
|
||||
|
||||
public GameClient(AMazeIng main_) {
|
||||
main = main_;
|
||||
|
@ -36,40 +42,34 @@ public class GameClient {
|
|||
while (clientRunning) {
|
||||
if (socket == null) {
|
||||
SocketHints socketHints = new SocketHints();
|
||||
socketHints.connectTimeout = 0;
|
||||
socketHints.connectTimeout = 10000;
|
||||
socket = Gdx.net.newClientSocket(Protocol.TCP, addr, port, socketHints);
|
||||
System.out.println("Connected to server!");
|
||||
sendMessagetoClients("AO");
|
||||
|
||||
sendMessageToSocket(socket, "AO");
|
||||
connectionStep = 0;
|
||||
} else {
|
||||
if (socket.isConnected()) {
|
||||
// Receive messages from the server
|
||||
try {
|
||||
if (socket.getInputStream().available() > 0) {
|
||||
BufferedReader buffer = new BufferedReader(
|
||||
new InputStreamReader(socket.getInputStream()));
|
||||
rMsg = receiveMessageFromSocket(socket);
|
||||
|
||||
// Read to the next newline (\n) and display that text on labelMessage
|
||||
s = buffer.readLine().toString();
|
||||
System.out.println("Received message from server: " + socket + "!\n" + s);
|
||||
if(s.startsWith("Map")) {
|
||||
s1 = s.replace("Map", "");
|
||||
main.gameManager.generateMaze(main.gameManager.mazeGen.runLenghtDecode(s1));
|
||||
//System.out.println(s1);
|
||||
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
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
|
||||
s1 = rMsg.replace("UUID", "");
|
||||
uuid = UUID.fromString(s1);
|
||||
connectionStep = 1;
|
||||
System.out.println("Got UUID from server: " + uuid.toString());
|
||||
sendMessageToSocket(socket, "AO2");
|
||||
}
|
||||
// Send messages to the client
|
||||
if (!nextMessage.equals(""))
|
||||
try {
|
||||
// write our entered message to the stream
|
||||
socket.getOutputStream().write((nextMessage + "\n").getBytes());
|
||||
} catch (IOException e) {
|
||||
// e.printStackTrace();
|
||||
if (rMsg.equals("AO3")) {
|
||||
if (connectionStep == 1) {
|
||||
connectionStep = 2;
|
||||
sendMessageToSocket(socket, "AO4");
|
||||
System.out.println("Connected with server!");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
nextMessage = "";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -77,11 +77,71 @@ public class GameClient {
|
|||
clientThread.start();
|
||||
}
|
||||
|
||||
public void sendMessagetoClients(String s) {
|
||||
// Update must be called from Main thread and used for applications on main
|
||||
// thread
|
||||
public void update() {
|
||||
}
|
||||
|
||||
public void sendMessagetoServer(String s) {
|
||||
nextMessage += (s + "\n");
|
||||
}
|
||||
|
||||
public void stop() {
|
||||
clientRunning = false;
|
||||
}
|
||||
|
||||
void sendMessageToSocket(Socket s, String msg) {
|
||||
if (s != null && s.isConnected())
|
||||
try {
|
||||
// write our entered message to the stream
|
||||
System.out.println("Client sending msg: " + msg + " to " + s);
|
||||
s.getOutputStream().write((msg + "\n").getBytes());
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
String tmprs;
|
||||
|
||||
String receiveMessageFromSocket(Socket s) {
|
||||
if (s != null && s.isConnected())
|
||||
// Receive messages from the client
|
||||
try {
|
||||
if (s.getInputStream().available() > 0) {
|
||||
BufferedReader buffer = new BufferedReader(new InputStreamReader(s.getInputStream()));
|
||||
// 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);
|
||||
return tmprs;
|
||||
}
|
||||
} catch (IOException e) {
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
// // Receive messages from the server
|
||||
// try {
|
||||
// if (socket.getInputStream().available() > 0) {
|
||||
// BufferedReader buffer = new BufferedReader(
|
||||
// new InputStreamReader(socket.getInputStream()));
|
||||
//
|
||||
// // Read to the next newline (\n) and display that text on labelMessage
|
||||
// s = buffer.readLine().toString();
|
||||
// //System.out.println("Received message from server: " + socket + "!\n" + s);
|
||||
// if(s.startsWith("Map")) {
|
||||
// s1 = s.replace("Map", "");
|
||||
// main.gameManager.generateMaze(main.gameManager.mazeGen.runLenghtDecode(s1));
|
||||
//
|
||||
// }
|
||||
// }
|
||||
// } catch (IOException e) {
|
||||
// }
|
||||
// // Send messages to the client
|
||||
// if (!nextMessage.equals(""))
|
||||
// try {
|
||||
// // write our entered message to the stream
|
||||
// socket.getOutputStream().write((nextMessage + "\n").getBytes());
|
||||
// } catch (IOException e) {
|
||||
//// e.printStackTrace();
|
||||
// }
|
||||
}
|
||||
|
|
|
@ -37,6 +37,9 @@ public class GameManager {
|
|||
boolean anyoneWon = false;
|
||||
|
||||
public void update() {
|
||||
server.update();
|
||||
client.update();
|
||||
|
||||
if (gameStarted) {
|
||||
main.world.cam.position.set(mazeGen.w / 2, (MazeSettings.MAZEX + MazeSettings.MAZEZ) * 0.45f,
|
||||
mazeGen.h / 2);
|
||||
|
@ -189,6 +192,7 @@ public class GameManager {
|
|||
public void generateMaze(int todraw[][]) {
|
||||
generateMaze(null, todraw);
|
||||
}
|
||||
|
||||
public void generateMaze(Set<MazePlayer> pl) {
|
||||
generateMaze(pl, null);
|
||||
}
|
||||
|
|
|
@ -4,6 +4,9 @@ import java.io.BufferedReader;
|
|||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Hashtable;
|
||||
import java.util.UUID;
|
||||
|
||||
import com.badlogic.gdx.Gdx;
|
||||
import com.badlogic.gdx.Net.Protocol;
|
||||
|
@ -13,18 +16,38 @@ import com.badlogic.gdx.net.Socket;
|
|||
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.MazePlayerRemote;
|
||||
|
||||
public class GameServer {
|
||||
|
||||
public AMazeIng main;
|
||||
|
||||
volatile boolean serverRunning = false;
|
||||
volatile String nextMessage = "";
|
||||
volatile String rMsg;
|
||||
|
||||
public ServerSocket serverSocket = null;
|
||||
public int port;
|
||||
ArrayList<Socket> clientSockets = new ArrayList<Socket>();
|
||||
Thread serverThread;
|
||||
public AMazeIng main;
|
||||
Socket s;
|
||||
Thread serverThread;
|
||||
|
||||
// An HashTable that stores remote players, starting from a UUID and the
|
||||
// relative socket
|
||||
// Player must be added here only once received the last acknowledgment message
|
||||
// from client
|
||||
volatile Hashtable<Socket, FullPlayerEntry> remotePlayers = new Hashtable<>();
|
||||
// An HashTable that stores remote players waiting to be accepted, starting from
|
||||
// a UUID and the
|
||||
// relative socket. The integer is needed to store the current phase the
|
||||
// acknowledgment is at (Starting from 0), if it's not equals to the expected
|
||||
// one the connectiond gets dropped and socket removed from here
|
||||
volatile Hashtable<Socket, TmpPlayerEntry> tmpPlayers = new Hashtable<>();
|
||||
// New players to be added into remotePlayers in the main thread, holds Sockets
|
||||
// used to get player info from tmpPlayers
|
||||
volatile ArrayList<Socket> newPlayers = new ArrayList<>();
|
||||
|
||||
volatile TmpPlayerEntry currentTmpEntry;
|
||||
|
||||
SocketHints socketHints = new SocketHints();
|
||||
ServerSocketHints serverSocketHint = new ServerSocketHints();
|
||||
|
@ -35,7 +58,8 @@ public class GameServer {
|
|||
|
||||
public void startServer(int port_) {
|
||||
port = port_;
|
||||
serverSocketHint.acceptTimeout = 100;
|
||||
serverSocketHint.acceptTimeout = 1000;
|
||||
socketHints.connectTimeout = 10000;
|
||||
serverThread = new Thread(new Runnable() {
|
||||
|
||||
@Override
|
||||
|
@ -43,46 +67,75 @@ public class GameServer {
|
|||
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);
|
||||
Socket socket = serverSocket.accept(socketHints);
|
||||
if (socket != null && !tmpPlayers.contains(socket)
|
||||
&& !remotePlayers.keySet().contains(socket)) {
|
||||
tmpPlayers.put(socket, new TmpPlayerEntry(socket, UUID.randomUUID(), 0));
|
||||
System.out.println(
|
||||
"Accepted new tmp client: " + socket + " with ip " + socket.getRemoteAddress());
|
||||
}
|
||||
|
||||
} catch (GdxRuntimeException se) {
|
||||
// System.out.println("No new clients connected in the last 100 milliseconds");
|
||||
// System.out.println("No new clients connected in the last 1000 milliseconds");
|
||||
}
|
||||
|
||||
for (Socket s : clientSockets) {
|
||||
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()) {
|
||||
// Receive messages from the client
|
||||
try {
|
||||
if (s.getInputStream().available() > 0) {
|
||||
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());
|
||||
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");
|
||||
}
|
||||
} catch (IOException e) {
|
||||
// If receiving multiple AOs, just start back from this point
|
||||
tmpPlayers.get(s).step = 1;
|
||||
}
|
||||
// Send messages to the client
|
||||
if (!nextMessage.equals(""))
|
||||
try {
|
||||
// write our entered message to the stream
|
||||
s.getOutputStream().write((nextMessage + "\n").getBytes());
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
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);
|
||||
}
|
||||
}
|
||||
nextMessage = "";
|
||||
}
|
||||
|
||||
for (Socket s : tmpPlayers.keySet()) {
|
||||
|
||||
if (s.isConnected()) {
|
||||
|
||||
} else {
|
||||
// Cliented timed out, remove it from the list :(
|
||||
remotePlayers.remove(s);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -94,13 +147,29 @@ public class GameServer {
|
|||
nextMessage += (s + "\n");
|
||||
}
|
||||
|
||||
// Update must be called from Main thread and used for applications on main
|
||||
// thread, such as spawning new players
|
||||
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)));
|
||||
System.out.println("Accepted new player: " + s.toString() + " " + tmpPlayers.get(s).uuid.toString());
|
||||
tmpPlayers.remove(s);
|
||||
}
|
||||
newPlayers.clear();
|
||||
}
|
||||
|
||||
// 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
|
||||
public void startGame() {
|
||||
main.gameManager.generateMaze();
|
||||
sendMessagetoClients("Map" + main.gameManager.mazeGen.runLenghtEncode());
|
||||
// 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());
|
||||
}
|
||||
|
||||
public void stop() {
|
||||
|
@ -110,4 +179,66 @@ public class GameServer {
|
|||
}
|
||||
serverRunning = false;
|
||||
}
|
||||
|
||||
void sendMessageToSocket(Socket s, String msg) {
|
||||
if (s != null && s.isConnected())
|
||||
if (!msg.equals(""))
|
||||
try {
|
||||
// write our entered message to the stream
|
||||
System.out.println("Server sending msg: " + msg + " to " + s);
|
||||
s.getOutputStream().write((msg + "\n").getBytes());
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
String tmprs;
|
||||
|
||||
String receiveMessageFromSocket(Socket s) {
|
||||
if (s != null && s.isConnected()) {
|
||||
// Receive messages from the client
|
||||
try {
|
||||
if (s.getInputStream().available() > 0) {
|
||||
BufferedReader buffer = new BufferedReader(new InputStreamReader(s.getInputStream()));
|
||||
// Read to the next newline (\n) and display that text on labelMessage
|
||||
tmprs = buffer.readLine();
|
||||
System.out.println("Server received message From: " + s + "! " + tmprs);
|
||||
return tmprs;
|
||||
}
|
||||
} catch (IOException e) {
|
||||
}
|
||||
}
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
class TmpPlayerEntry {
|
||||
public UUID uuid;
|
||||
public Socket socket;
|
||||
public int step = 0;
|
||||
public long lastTimeHeard;
|
||||
/*
|
||||
* (Look at the notes) Step 0: AO client->server first request Step 1: UUID
|
||||
* server->client response with uuid Step 2: AO2 client->server client accepted
|
||||
* uuid Step 3: AO3 server->client server accepted client
|
||||
*/
|
||||
|
||||
public TmpPlayerEntry(Socket s, UUID u, int t) {
|
||||
uuid = u;
|
||||
socket = s;
|
||||
step = t;
|
||||
lastTimeHeard = System.currentTimeMillis();
|
||||
}
|
||||
}
|
||||
|
||||
class FullPlayerEntry {
|
||||
public UUID uuid;
|
||||
public Socket socket;
|
||||
public MazePlayer player;
|
||||
|
||||
public FullPlayerEntry(Socket s, UUID u, MazePlayer p) {
|
||||
uuid = u;
|
||||
socket = s;
|
||||
player = p;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,8 +3,6 @@ package com.emamaker.amazeing.player;
|
|||
import java.util.Random;
|
||||
|
||||
import com.badlogic.gdx.Game;
|
||||
import com.badlogic.gdx.Gdx;
|
||||
import com.badlogic.gdx.controllers.Controller;
|
||||
import com.badlogic.gdx.graphics.GL20;
|
||||
import com.badlogic.gdx.graphics.VertexAttributes;
|
||||
import com.badlogic.gdx.graphics.g3d.Environment;
|
||||
|
@ -15,206 +13,59 @@ import com.badlogic.gdx.graphics.g3d.ModelInstance;
|
|||
import com.badlogic.gdx.graphics.g3d.model.Node;
|
||||
import com.badlogic.gdx.graphics.g3d.utils.MeshPartBuilder;
|
||||
import com.badlogic.gdx.graphics.g3d.utils.ModelBuilder;
|
||||
import com.badlogic.gdx.math.Matrix4;
|
||||
import com.badlogic.gdx.math.Vector3;
|
||||
import com.badlogic.gdx.physics.bullet.collision.btBoxShape;
|
||||
import com.badlogic.gdx.physics.bullet.collision.btBroadphaseProxy;
|
||||
import com.badlogic.gdx.physics.bullet.collision.btCollisionObject;
|
||||
import com.badlogic.gdx.physics.bullet.collision.btConvexShape;
|
||||
import com.badlogic.gdx.physics.bullet.collision.btPairCachingGhostObject;
|
||||
import com.badlogic.gdx.physics.bullet.dynamics.btDiscreteDynamicsWorld;
|
||||
import com.badlogic.gdx.physics.bullet.dynamics.btKinematicCharacterController;
|
||||
import com.emamaker.amazeing.AMazeIng;
|
||||
import com.emamaker.voxelengine.physics.GameObject;
|
||||
|
||||
public class MazePlayer {
|
||||
public abstract class MazePlayer {
|
||||
|
||||
AMazeIng main;
|
||||
|
||||
static Random rand = new Random();
|
||||
|
||||
// MazePlayer model building stuff
|
||||
public Model MazePlayerModel;
|
||||
public Model mazePlayerModel;
|
||||
public ModelInstance instance;
|
||||
ModelBuilder modelBuilder = new ModelBuilder();
|
||||
MeshPartBuilder meshBuilder;
|
||||
static int meshAttr = VertexAttributes.Usage.Position | VertexAttributes.Usage.Normal;
|
||||
public GameObject obj;
|
||||
|
||||
btConvexShape ghostShape;
|
||||
public btPairCachingGhostObject ghostObject;
|
||||
public btKinematicCharacterController characterController;
|
||||
Matrix4 characterTransform;
|
||||
Vector3 characterDirection = new Vector3();
|
||||
Vector3 walkDirection = new Vector3();
|
||||
public Controller ctrl;
|
||||
|
||||
// Physics using LibGDX's bullet wrapper
|
||||
public int kup, kdown, ksx, kdx;
|
||||
float startx, starty, startz;
|
||||
String name;
|
||||
AMazeIng main;
|
||||
|
||||
boolean disposing = false;
|
||||
|
||||
public MazePlayer(Game main_, int up_, int down_, int sx_, int dx_) {
|
||||
this(main_, up_, down_, sx_, dx_, 0, 0, 0);
|
||||
MazePlayer(Game main_) {
|
||||
this(main_, String.valueOf((char) (65 + rand.nextInt(26))));
|
||||
disposing = false;
|
||||
}
|
||||
|
||||
public MazePlayer(Game main_, int up_, int down_, int sx_, int dx_, String name) {
|
||||
this(main_, up_, down_, sx_, dx_, 0, 0, 0, name);
|
||||
}
|
||||
|
||||
public MazePlayer(Game main_, int up_, int down_, int sx_, int dx_, float startx, float starty, float startz) {
|
||||
this(main_, up_, down_, sx_, dx_, startx, starty, startz, String.valueOf((char) (65 + rand.nextInt(26))));
|
||||
}
|
||||
|
||||
public MazePlayer(Game main_, int up_, int down_, int sx_, int dx_, float startx, float starty, float startz,
|
||||
String name) {
|
||||
this.kup = up_;
|
||||
this.kdown = down_;
|
||||
this.ksx = sx_;
|
||||
this.kdx = dx_;
|
||||
|
||||
this.startx = startx;
|
||||
this.starty = starty;
|
||||
this.startz = startz;
|
||||
|
||||
this.main = (AMazeIng) main_;
|
||||
MazePlayer(Game main_, String name) {
|
||||
main = (AMazeIng) main_;
|
||||
|
||||
setName(name);
|
||||
buildModel();
|
||||
initPhysics();
|
||||
}
|
||||
|
||||
public MazePlayer(Game main_, Controller ctrl_) {
|
||||
this(main_, ctrl_, 0, 0, 0);
|
||||
}
|
||||
|
||||
public MazePlayer(Game main_, Controller ctrl_, String name) {
|
||||
this(main_, ctrl_, 0, 0, 0, name);
|
||||
}
|
||||
|
||||
public MazePlayer(Game main_, Controller crtl_, float startx, float starty, float startz) {
|
||||
this(main_, crtl_, startx, starty, startz, String.valueOf((char) (65 + rand.nextInt(26))));
|
||||
}
|
||||
|
||||
public MazePlayer(Game main_, Controller ctrl_, float startx, float starty, float startz, String name) {
|
||||
this.ctrl = ctrl_;
|
||||
|
||||
this.startx = startx;
|
||||
this.starty = starty;
|
||||
this.startz = startz;
|
||||
|
||||
setName(name);
|
||||
buildModel();
|
||||
initPhysics();
|
||||
}
|
||||
|
||||
// public void buildModel() {
|
||||
// modelBuilder.begin();
|
||||
// Node n = modelBuilder.node();
|
||||
// n.id = "MazePlayer";
|
||||
// modelBuilder.part("MazePlayer", GL20.GL_TRIANGLES, meshAttr, new Material()).cone(1, 1, 1, 20);
|
||||
// MazePlayerModel = modelBuilder.end();
|
||||
// }
|
||||
//
|
||||
// public void initPhysics() {
|
||||
// GameObject.Constructor construct = new GameObject.Constructor(MazePlayerModel, "MazePlayer", new btConeShape(1,1),
|
||||
// 30f);
|
||||
// obj = construct.construct();
|
||||
// obj.transform.trn(VoxelSettings.chunkSize/2, VoxelSettings.chunkSize/2, VoxelSettings.chunkSize/2);
|
||||
// obj.body.proceedToTransform(obj.transform);
|
||||
// obj.body.setCollisionFlags(
|
||||
// obj.body.getCollisionFlags() | btCollisionObject.CollisionFlags.CF_CUSTOM_MATERIAL_CALLBACK);
|
||||
// VoxelSettings.voxelWorld.dynamicsWorld.addRigidBody(obj.body);
|
||||
//// obj.body.setContactCallbackFlag(VoxelSettings.OBJECT_FLAG);
|
||||
//// obj.body.setContactCallbackFilter(VoxelSettings.GROUND_FLAG);
|
||||
// }
|
||||
//
|
||||
// public void render(ModelBatch b, Environment e) {
|
||||
// b.render(obj, e);
|
||||
// }
|
||||
|
||||
public void buildModel() {
|
||||
modelBuilder.begin();
|
||||
Node n = modelBuilder.node();
|
||||
n.id = "MazePlayer";
|
||||
modelBuilder.part("MazePlayer", GL20.GL_TRIANGLES, meshAttr, new Material()).box(0.6f, 0.6f, 0.6f);
|
||||
MazePlayerModel = modelBuilder.end();
|
||||
instance = new ModelInstance(MazePlayerModel);
|
||||
}
|
||||
|
||||
public void initPhysics() {
|
||||
characterTransform = instance.transform; // Set by reference
|
||||
characterTransform.set(startx, starty, startz, 0, 0, 0, 0);
|
||||
|
||||
// Create the physics representation of the character
|
||||
ghostObject = new btPairCachingGhostObject();
|
||||
ghostObject.setWorldTransform(characterTransform);
|
||||
ghostShape = new btBoxShape(new Vector3(0.3f, 0.3f, 0.3f));
|
||||
ghostObject.setCollisionShape(ghostShape);
|
||||
ghostObject.setCollisionFlags(btCollisionObject.CollisionFlags.CF_CHARACTER_OBJECT);
|
||||
characterController = new btKinematicCharacterController(ghostObject, ghostShape, .05f, Vector3.Y);
|
||||
|
||||
// And add it to the physics world
|
||||
main.world.dynamicsWorld.addCollisionObject(ghostObject,
|
||||
(short) btBroadphaseProxy.CollisionFilterGroups.CharacterFilter,
|
||||
(short) (btBroadphaseProxy.CollisionFilterGroups.StaticFilter
|
||||
| btBroadphaseProxy.CollisionFilterGroups.DefaultFilter));
|
||||
((btDiscreteDynamicsWorld) (main.world.dynamicsWorld)).addAction(characterController);
|
||||
}
|
||||
|
||||
public void render(ModelBatch b, Environment e) {
|
||||
if (!disposing) {
|
||||
inputs();
|
||||
b.render(instance, e);
|
||||
}
|
||||
}
|
||||
|
||||
public void inputs() {
|
||||
// If the left or right key is pressed, rotate the character and update its
|
||||
// physics update accordingly.
|
||||
if (Gdx.input.isKeyPressed(ksx)) {
|
||||
characterTransform.rotate(0, 1, 0, 2.5f);
|
||||
ghostObject.setWorldTransform(characterTransform);
|
||||
}
|
||||
if (Gdx.input.isKeyPressed(kdx)) {
|
||||
characterTransform.rotate(0, 1, 0, -2.5f);
|
||||
ghostObject.setWorldTransform(characterTransform);
|
||||
}
|
||||
// Fetch which direction the character is facing now
|
||||
characterDirection.set(-1, 0, 0).rot(characterTransform).nor();
|
||||
// Set the walking direction accordingly (either forward or backward)
|
||||
walkDirection.set(0, 0, 0);
|
||||
|
||||
if (Gdx.input.isKeyPressed(kup))
|
||||
walkDirection.add(characterDirection);
|
||||
if (Gdx.input.isKeyPressed(kdown))
|
||||
walkDirection.add(-characterDirection.x, -characterDirection.y, -characterDirection.z);
|
||||
walkDirection.scl(3f * Gdx.graphics.getDeltaTime());
|
||||
// And update the character controller
|
||||
characterController.setWalkDirection(walkDirection);
|
||||
// Now we can update the world as normally
|
||||
// And fetch the new transformation of the character (this will make the model
|
||||
// be rendered correctly)
|
||||
ghostObject.getWorldTransform(characterTransform);
|
||||
}
|
||||
|
||||
public Vector3 getPos() {
|
||||
return instance.transform.getTranslation(new Vector3());
|
||||
}
|
||||
|
||||
public void setPlaying() {
|
||||
disposing = false;
|
||||
}
|
||||
|
||||
public void setPos(Vector3 v) {
|
||||
if (!disposing) {
|
||||
characterTransform.set(v.x, v.y, v.z, 0, 0, 0, 0);
|
||||
ghostObject.setWorldTransform(characterTransform);
|
||||
}
|
||||
if (!disposing)
|
||||
setPos(v.x, v.y, v.z);
|
||||
}
|
||||
|
||||
public void setPos(float x, float y, float z) {
|
||||
if (!disposing) {
|
||||
characterTransform.set(x, y, z, 0, 0, 0, 0);
|
||||
ghostObject.setWorldTransform(characterTransform);
|
||||
}
|
||||
if (!disposing)
|
||||
setTransform(x, y, z, 0, 0, 0, 0);
|
||||
}
|
||||
|
||||
public void setTransform(float x, float y, float z, float i, float j, float k, float l) {
|
||||
if (!disposing)
|
||||
instance.transform.set(x, y, z, i, j, k, l);
|
||||
}
|
||||
|
||||
public void setName(String name_) {
|
||||
|
@ -225,19 +76,26 @@ public class MazePlayer {
|
|||
return name;
|
||||
}
|
||||
|
||||
public void setPlaying() {
|
||||
disposing = false;
|
||||
public void render(ModelBatch b, Environment e) {
|
||||
if (!disposing) {
|
||||
update();
|
||||
b.render(instance, e);
|
||||
}
|
||||
}
|
||||
|
||||
public void buildModel() {
|
||||
modelBuilder.begin();
|
||||
Node n = modelBuilder.node();
|
||||
n.id = "MazePlayer";
|
||||
modelBuilder.part("MazePlayer", GL20.GL_TRIANGLES, meshAttr, new Material()).box(0.6f, 0.6f, 0.6f);
|
||||
mazePlayerModel = modelBuilder.end();
|
||||
instance = new ModelInstance(mazePlayerModel);
|
||||
}
|
||||
|
||||
public void update() {
|
||||
}
|
||||
|
||||
public void dispose() {
|
||||
disposing = true;
|
||||
main.world.dynamicsWorld.removeAction(characterController);
|
||||
main.world.dynamicsWorld.removeCollisionObject(ghostObject);
|
||||
characterController.dispose();
|
||||
ghostObject.dispose();
|
||||
ghostShape.dispose();
|
||||
MazePlayerModel.dispose();
|
||||
disposing = false;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,170 @@
|
|||
package com.emamaker.amazeing.player;
|
||||
|
||||
import com.badlogic.gdx.Game;
|
||||
import com.badlogic.gdx.Gdx;
|
||||
import com.badlogic.gdx.controllers.Controller;
|
||||
import com.badlogic.gdx.math.Matrix4;
|
||||
import com.badlogic.gdx.math.Vector3;
|
||||
import com.badlogic.gdx.physics.bullet.collision.btBoxShape;
|
||||
import com.badlogic.gdx.physics.bullet.collision.btBroadphaseProxy;
|
||||
import com.badlogic.gdx.physics.bullet.collision.btCollisionObject;
|
||||
import com.badlogic.gdx.physics.bullet.collision.btConvexShape;
|
||||
import com.badlogic.gdx.physics.bullet.collision.btPairCachingGhostObject;
|
||||
import com.badlogic.gdx.physics.bullet.dynamics.btDiscreteDynamicsWorld;
|
||||
import com.badlogic.gdx.physics.bullet.dynamics.btKinematicCharacterController;
|
||||
|
||||
public class MazePlayerLocal extends MazePlayer {
|
||||
|
||||
/*
|
||||
* Player controlled on local machine with mouse and kbd, touch or controller
|
||||
* (in a remote future=
|
||||
*/
|
||||
|
||||
btConvexShape ghostShape;
|
||||
public btPairCachingGhostObject ghostObject;
|
||||
public btKinematicCharacterController characterController;
|
||||
Matrix4 characterTransform;
|
||||
Vector3 characterDirection = new Vector3();
|
||||
Vector3 walkDirection = new Vector3();
|
||||
public Controller ctrl;
|
||||
|
||||
// Physics using LibGDX's bullet wrapper
|
||||
public int kup, kdown, ksx, kdx;
|
||||
float startx, starty, startz;
|
||||
|
||||
public MazePlayerLocal(Game main_, int up_, int down_, int sx_, int dx_) {
|
||||
this(main_, up_, down_, sx_, dx_, 0, 0, 0);
|
||||
}
|
||||
|
||||
public MazePlayerLocal(Game main_, int up_, int down_, int sx_, int dx_, String name) {
|
||||
this(main_, up_, down_, sx_, dx_, 0, 0, 0, name);
|
||||
}
|
||||
|
||||
public MazePlayerLocal(Game main_, int up_, int down_, int sx_, int dx_, float startx, float starty, float startz) {
|
||||
this(main_, up_, down_, sx_, dx_, startx, starty, startz, String.valueOf((char) (65 + rand.nextInt(26))));
|
||||
}
|
||||
|
||||
public MazePlayerLocal(Game main_, int up_, int down_, int sx_, int dx_, float startx, float starty, float startz,
|
||||
String name) {
|
||||
super(main_, name);
|
||||
this.kup = up_;
|
||||
this.kdown = down_;
|
||||
this.ksx = sx_;
|
||||
this.kdx = dx_;
|
||||
|
||||
this.startx = startx;
|
||||
this.starty = starty;
|
||||
this.startz = startz;
|
||||
|
||||
initPhysics();
|
||||
}
|
||||
|
||||
public MazePlayerLocal(Game main_, Controller ctrl_) {
|
||||
this(main_, ctrl_, 0, 0, 0);
|
||||
}
|
||||
|
||||
public MazePlayerLocal(Game main_, Controller ctrl_, String name) {
|
||||
this(main_, ctrl_, 0, 0, 0, name);
|
||||
}
|
||||
|
||||
public MazePlayerLocal(Game main_, Controller crtl_, float startx, float starty, float startz) {
|
||||
this(main_, crtl_, startx, starty, startz, String.valueOf((char) (65 + rand.nextInt(26))));
|
||||
}
|
||||
|
||||
public MazePlayerLocal(Game main_, Controller ctrl_, float startx, float starty, float startz, String name) {
|
||||
super(main_);
|
||||
this.ctrl = ctrl_;
|
||||
|
||||
this.startx = startx;
|
||||
this.starty = starty;
|
||||
this.startz = startz;
|
||||
|
||||
initPhysics();
|
||||
}
|
||||
|
||||
public void initPhysics() {
|
||||
characterTransform = instance.transform; // Set by reference
|
||||
characterTransform.set(startx, starty, startz, 0, 0, 0, 0);
|
||||
|
||||
// Create the physics representation of the character
|
||||
ghostObject = new btPairCachingGhostObject();
|
||||
ghostObject.setWorldTransform(characterTransform);
|
||||
ghostShape = new btBoxShape(new Vector3(0.3f, 0.3f, 0.3f));
|
||||
ghostObject.setCollisionShape(ghostShape);
|
||||
ghostObject.setCollisionFlags(btCollisionObject.CollisionFlags.CF_CHARACTER_OBJECT);
|
||||
characterController = new btKinematicCharacterController(ghostObject, ghostShape, .05f, Vector3.Y);
|
||||
|
||||
// And add it to the physics world
|
||||
main.world.dynamicsWorld.addCollisionObject(ghostObject,
|
||||
(short) btBroadphaseProxy.CollisionFilterGroups.CharacterFilter,
|
||||
(short) (btBroadphaseProxy.CollisionFilterGroups.StaticFilter
|
||||
| btBroadphaseProxy.CollisionFilterGroups.DefaultFilter));
|
||||
((btDiscreteDynamicsWorld) (main.world.dynamicsWorld)).addAction(characterController);
|
||||
}
|
||||
|
||||
public void inputs() {
|
||||
// If the left or right key is pressed, rotate the character and update its
|
||||
// physics update accordingly.
|
||||
if (Gdx.input.isKeyPressed(ksx)) {
|
||||
characterTransform.rotate(0, 1, 0, 2.5f);
|
||||
ghostObject.setWorldTransform(characterTransform);
|
||||
}
|
||||
if (Gdx.input.isKeyPressed(kdx)) {
|
||||
characterTransform.rotate(0, 1, 0, -2.5f);
|
||||
ghostObject.setWorldTransform(characterTransform);
|
||||
}
|
||||
// Fetch which direction the character is facing now
|
||||
characterDirection.set(-1, 0, 0).rot(characterTransform).nor();
|
||||
// Set the walking direction accordingly (either forward or backward)
|
||||
walkDirection.set(0, 0, 0);
|
||||
|
||||
if (Gdx.input.isKeyPressed(kup))
|
||||
walkDirection.add(characterDirection);
|
||||
if (Gdx.input.isKeyPressed(kdown))
|
||||
walkDirection.add(-characterDirection.x, -characterDirection.y, -characterDirection.z);
|
||||
walkDirection.scl(3f * Gdx.graphics.getDeltaTime());
|
||||
// And update the character controller
|
||||
characterController.setWalkDirection(walkDirection);
|
||||
// Now we can update the world as normally
|
||||
// And fetch the new transformation of the character (this will make the model
|
||||
// be rendered correctly)
|
||||
ghostObject.getWorldTransform(characterTransform);
|
||||
|
||||
if (main.gameManager.client.socket != null && main.gameManager.client.socket.isConnected()) {
|
||||
main.gameManager.client.sendMessagetoServer(characterTransform.toString());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update() {
|
||||
inputs();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPos(Vector3 v) {
|
||||
if (!disposing)
|
||||
this.setPos(v.x, v.y, v.z);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPos(float x, float y, float z) {
|
||||
if (!disposing) {
|
||||
characterTransform.set(x, y, z, 0, 0, 0, 0);
|
||||
ghostObject.setWorldTransform(characterTransform);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
disposing = true;
|
||||
main.world.dynamicsWorld.removeAction(characterController);
|
||||
main.world.dynamicsWorld.removeCollisionObject(ghostObject);
|
||||
characterController.dispose();
|
||||
ghostObject.dispose();
|
||||
ghostShape.dispose();
|
||||
mazePlayerModel.dispose();
|
||||
disposing = false;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,72 @@
|
|||
package com.emamaker.amazeing.player;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
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{
|
||||
|
||||
/*Remote controlled player to show other players on the server*/
|
||||
|
||||
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;
|
||||
|
||||
boolean disposing = false;
|
||||
|
||||
public MazePlayerRemote(Game main_, Socket s) {
|
||||
super(main_);
|
||||
socket = s;
|
||||
}
|
||||
|
||||
public void updateRemoteTransform(String s) {
|
||||
float x = 0, y = 0, z = 0, i = 0, j = 0, k = 0, l = 0;
|
||||
setTransform(x, y, z, i, j, k, l);
|
||||
}
|
||||
|
||||
public void setName(String name_) {
|
||||
this.name = name_;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setPlaying() {
|
||||
disposing = false;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void update() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
disposing = true;
|
||||
mazePlayerModel.dispose();
|
||||
disposing = false;
|
||||
}
|
||||
|
||||
}
|
|
@ -6,8 +6,6 @@ import com.badlogic.gdx.Gdx;
|
|||
import com.badlogic.gdx.Input.Keys;
|
||||
import com.badlogic.gdx.Screen;
|
||||
import com.badlogic.gdx.controllers.Controller;
|
||||
import com.badlogic.gdx.controllers.Controllers;
|
||||
import com.badlogic.gdx.controllers.mappings.Xbox;
|
||||
import com.badlogic.gdx.graphics.GL20;
|
||||
import com.badlogic.gdx.scenes.scene2d.InputEvent;
|
||||
import com.badlogic.gdx.scenes.scene2d.InputListener;
|
||||
|
@ -20,6 +18,7 @@ import com.badlogic.gdx.utils.Align;
|
|||
import com.badlogic.gdx.utils.viewport.ScreenViewport;
|
||||
import com.emamaker.amazeing.maze.settings.MazeSettings;
|
||||
import com.emamaker.amazeing.player.MazePlayer;
|
||||
import com.emamaker.amazeing.player.MazePlayerLocal;
|
||||
import com.emamaker.amazeing.ui.UIManager;
|
||||
|
||||
public class PlayerChooseScreen implements Screen {
|
||||
|
@ -31,7 +30,7 @@ public class PlayerChooseScreen implements Screen {
|
|||
Label[] labels;
|
||||
int currentLabel = 0;
|
||||
HashMap<MazePlayer, Label> players = new HashMap<MazePlayer, Label>();
|
||||
|
||||
|
||||
Screen thisScreen;
|
||||
|
||||
public PlayerChooseScreen(UIManager uiManager_) {
|
||||
|
@ -110,7 +109,7 @@ public class PlayerChooseScreen implements Screen {
|
|||
@Override
|
||||
public void show() {
|
||||
thisScreen = this;
|
||||
|
||||
|
||||
labels = new Label[MazeSettings.MAXPLAYERS];
|
||||
stage = new Stage(new ScreenViewport());
|
||||
Container<Table> tableContainer = new Container<Table>();
|
||||
|
@ -201,7 +200,7 @@ public class PlayerChooseScreen implements Screen {
|
|||
uiManager.main.multiplexer.removeProcessor(stage);
|
||||
}
|
||||
|
||||
MazePlayer p;
|
||||
MazePlayerLocal p;
|
||||
|
||||
@Override
|
||||
public void render(float delta) {
|
||||
|
@ -216,27 +215,27 @@ public class PlayerChooseScreen implements Screen {
|
|||
|| Gdx.input.isKeyJustPressed(Keys.S) || Gdx.input.isKeyJustPressed(Keys.D)) {
|
||||
p = getPlayerWithKeys(Keys.W, Keys.S, Keys.A, Keys.D);
|
||||
if (p == null)
|
||||
p = new MazePlayer(uiManager.main, Keys.W, Keys.S, Keys.A, Keys.D);
|
||||
p = new MazePlayerLocal(uiManager.main, Keys.W, Keys.S, Keys.A, Keys.D);
|
||||
togglePlayer(p);
|
||||
}
|
||||
if (Gdx.input.isKeyJustPressed(Keys.UP) || Gdx.input.isKeyJustPressed(Keys.LEFT)
|
||||
|| Gdx.input.isKeyJustPressed(Keys.DOWN) || Gdx.input.isKeyJustPressed(Keys.RIGHT)) {
|
||||
p = getPlayerWithKeys(Keys.UP, Keys.DOWN, Keys.LEFT, Keys.RIGHT);
|
||||
if (p == null)
|
||||
p = new MazePlayer(uiManager.main, Keys.UP, Keys.DOWN, Keys.LEFT, Keys.RIGHT);
|
||||
p = new MazePlayerLocal(uiManager.main, Keys.UP, Keys.DOWN, Keys.LEFT, Keys.RIGHT);
|
||||
togglePlayer(p);
|
||||
}
|
||||
for (Controller c : Controllers.getControllers()) {
|
||||
if (c.getButton(Xbox.Y)) {
|
||||
p = getPlayerWithCtrl(c);
|
||||
if (p == null)
|
||||
p = new MazePlayer(uiManager.main, c);
|
||||
togglePlayer(p);
|
||||
}
|
||||
}
|
||||
// for (Controller c : Controllers.getControllers()) {
|
||||
// if (c.getButton(Xbox.Y)) {
|
||||
// p = getPlayerWithCtrl(c);
|
||||
// if (p == null)
|
||||
// p = new MazePlayerLocal(uiManager.main, c);
|
||||
// togglePlayer(p);
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
public void togglePlayer(MazePlayer p) {
|
||||
public void togglePlayer(MazePlayerLocal p) {
|
||||
try {
|
||||
if (alreadyAddedPlayer(p)) {
|
||||
players.get(p).setText("Not Joined Yet");
|
||||
|
@ -254,15 +253,17 @@ public class PlayerChooseScreen implements Screen {
|
|||
return getPlayerWithKeys(keys) != null;
|
||||
}
|
||||
|
||||
public boolean alreadyAddedPlayer(MazePlayer p) {
|
||||
public boolean alreadyAddedPlayer(MazePlayerLocal p) {
|
||||
return players.containsKey(p);
|
||||
}
|
||||
|
||||
public MazePlayer getPlayerWithKeys(int... keys) {
|
||||
public MazePlayerLocal getPlayerWithKeys(int... keys) {
|
||||
for (MazePlayer p : players.keySet()) {
|
||||
if(p instanceof MazePlayerLocal) {
|
||||
for (int k : keys) {
|
||||
if (p.kup == k || p.kdown == k || p.ksx == k || p.kdx == k)
|
||||
return p;
|
||||
if (((MazePlayerLocal)p).kup == k || ((MazePlayerLocal)p).kdown == k || ((MazePlayerLocal)p).ksx == k || ((MazePlayerLocal)p).kdx == k)
|
||||
return (MazePlayerLocal)p;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
|
@ -272,10 +273,12 @@ public class PlayerChooseScreen implements Screen {
|
|||
return getPlayerWithCtrl(ctrl) != null;
|
||||
}
|
||||
|
||||
public MazePlayer getPlayerWithCtrl(Controller ctrl) {
|
||||
public MazePlayerLocal getPlayerWithCtrl(Controller ctrl) {
|
||||
for (MazePlayer p : players.keySet()) {
|
||||
if (p.ctrl == ctrl)
|
||||
return p;
|
||||
if (p instanceof MazePlayerLocal) {
|
||||
if (((MazePlayerLocal)p).ctrl == ctrl)
|
||||
return (MazePlayerLocal) p;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue