mirror of
https://github.com/collinsmith/riiablo.git
synced 2025-02-21 20:18:14 +07:00
Added basic server support (create/join games and chat)
Separated services into ChatServer, DedicatedServer and Sessions Single player uses same code-base as DedicatedServer with a special loopback socket Added SelectCharacterScreen2 copy -- will replace later on with more versatile SelectCharacterScreen impl
This commit is contained in:
parent
a1e735031f
commit
49f1058566
@ -31,6 +31,7 @@ public class Colors {
|
||||
public Color c10 = C10.cpy();
|
||||
public Color purple = PURPLE.cpy();
|
||||
public Color c12 = C12.cpy();
|
||||
public Color modal = black.cpy().sub(0, 0, 0, 0.5f);
|
||||
|
||||
public Colors() {}
|
||||
|
||||
|
@ -0,0 +1,47 @@
|
||||
package gdx.diablo.graphics;
|
||||
|
||||
import com.badlogic.gdx.graphics.Color;
|
||||
import com.badlogic.gdx.graphics.g2d.Batch;
|
||||
import com.badlogic.gdx.scenes.scene2d.utils.TextureRegionDrawable;
|
||||
|
||||
import gdx.diablo.BlendMode;
|
||||
import gdx.diablo.Diablo;
|
||||
|
||||
public class PaletteIndexedColorDrawable extends TextureRegionDrawable {
|
||||
|
||||
public Color tint;
|
||||
|
||||
public PaletteIndexedColorDrawable(Color color) {
|
||||
super(Diablo.textures.white);
|
||||
this.tint = color;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(Batch batch, float x, float y, float width, float height) {
|
||||
if (!(batch instanceof PaletteIndexedBatch)) {
|
||||
// unsupported, will draw white for now
|
||||
super.draw(batch, x, y, width, height);
|
||||
return;
|
||||
}
|
||||
|
||||
PaletteIndexedBatch b = (PaletteIndexedBatch) batch;
|
||||
b.setBlendMode(BlendMode.SOLID, tint);
|
||||
super.draw(batch, x, y, width, height);
|
||||
b.resetBlendMode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(Batch batch, float x, float y, float originX, float originY, float width,
|
||||
float height, float scaleX, float scaleY, float rotation) {
|
||||
if (!(batch instanceof PaletteIndexedBatch)) {
|
||||
// unsupported, will draw white for now
|
||||
super.draw(batch, x, y, originX, originY, width, height, scaleX, scaleY, rotation);
|
||||
return;
|
||||
}
|
||||
|
||||
PaletteIndexedBatch b = (PaletteIndexedBatch) batch;
|
||||
b.setBlendMode(BlendMode.SOLID, tint);
|
||||
super.draw(batch, x, y, originX, originY, width, height, scaleX, scaleY, rotation);
|
||||
b.resetBlendMode();
|
||||
}
|
||||
}
|
@ -46,7 +46,7 @@ public class EscapePanel extends WidgetGroup implements Disposable {
|
||||
exit.addListener(new ClickListener() {
|
||||
@Override
|
||||
public void clicked(InputEvent event, float x, float y) {
|
||||
Diablo.client.setScreen(new MenuScreen());
|
||||
Diablo.client.clearAndSet(new MenuScreen());
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -46,7 +46,7 @@ public class MobilePanel extends Table implements Disposable {
|
||||
} else if (actor == btnMap) {
|
||||
|
||||
} else if (actor == btnMessages) {
|
||||
|
||||
gameScreen.input.setVisible(!gameScreen.input.isVisible());
|
||||
} else if (actor == btnQuests) {
|
||||
|
||||
} else if (actor == btnEscapeMenu) {
|
||||
@ -94,13 +94,13 @@ public class MobilePanel extends Table implements Disposable {
|
||||
down = new TextureRegionDrawable(Diablo.assets.get(minipanelbtnDescriptor).getTexture(15));
|
||||
}});
|
||||
btnEscapeMenu.addListener(clickListener);
|
||||
final float size = 40;
|
||||
final float size = 50;
|
||||
add(btnCharacter).size(size);
|
||||
add(btnInventory).size(size);
|
||||
add(btnSkillTree).size(size);
|
||||
//add(btnParty).size(size);
|
||||
//add(btnMap).size(size);
|
||||
//add(btnMessages).size(size);
|
||||
add(btnMessages).size(size);
|
||||
//add(btnQuests).size(size);
|
||||
add(btnEscapeMenu).size(size);
|
||||
pack();
|
||||
|
@ -13,19 +13,29 @@ import com.badlogic.gdx.graphics.Texture;
|
||||
import com.badlogic.gdx.graphics.glutils.ShapeRenderer;
|
||||
import com.badlogic.gdx.math.GridPoint2;
|
||||
import com.badlogic.gdx.math.MathUtils;
|
||||
import com.badlogic.gdx.net.Socket;
|
||||
import com.badlogic.gdx.scenes.scene2d.Actor;
|
||||
import com.badlogic.gdx.scenes.scene2d.Stage;
|
||||
import com.badlogic.gdx.scenes.scene2d.ui.Touchpad;
|
||||
import com.badlogic.gdx.scenes.scene2d.utils.ChangeListener;
|
||||
import com.badlogic.gdx.scenes.scene2d.utils.TextureRegionDrawable;
|
||||
import com.badlogic.gdx.scenes.scene2d.utils.UIUtils;
|
||||
import com.badlogic.gdx.utils.Align;
|
||||
import com.badlogic.gdx.utils.Array;
|
||||
import com.badlogic.gdx.utils.Timer;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.PrintWriter;
|
||||
|
||||
import gdx.diablo.Diablo;
|
||||
import gdx.diablo.Keys;
|
||||
import gdx.diablo.entity3.Player;
|
||||
import gdx.diablo.graphics.PaletteIndexedBatch;
|
||||
import gdx.diablo.graphics.PaletteIndexedColorDrawable;
|
||||
import gdx.diablo.key.MappedKey;
|
||||
import gdx.diablo.key.MappedKeyStateAdapter;
|
||||
import gdx.diablo.map.Map;
|
||||
@ -37,6 +47,8 @@ import gdx.diablo.panel.EscapePanel;
|
||||
import gdx.diablo.panel.InventoryPanel;
|
||||
import gdx.diablo.panel.MobilePanel;
|
||||
import gdx.diablo.panel.StashPanel;
|
||||
import gdx.diablo.server.PipedSocket;
|
||||
import gdx.diablo.widget.TextArea;
|
||||
|
||||
public class GameScreen extends ScreenAdapter implements LoadingScreen.Loadable {
|
||||
private static final String TAG = "GameScreen";
|
||||
@ -68,12 +80,17 @@ public class GameScreen extends ScreenAdapter implements LoadingScreen.Loadable
|
||||
OrthographicCamera camera;
|
||||
InputProcessor inputProcessorTest;
|
||||
|
||||
//TextArea input;
|
||||
public TextArea input;
|
||||
TextArea output;
|
||||
|
||||
//Char character;
|
||||
public Player player;
|
||||
Timer.Task updateTask;
|
||||
|
||||
Socket socket;
|
||||
PrintWriter out;
|
||||
BufferedReader in;
|
||||
|
||||
@Override
|
||||
public Array<AssetDescriptor> getDependencies() {
|
||||
Array<AssetDescriptor> dependencies = new Array<>();
|
||||
@ -82,22 +99,37 @@ public class GameScreen extends ScreenAdapter implements LoadingScreen.Loadable
|
||||
return dependencies;
|
||||
}
|
||||
|
||||
//public GameScreen(final Char character) {
|
||||
public GameScreen(final Player player) {
|
||||
this.player = player;
|
||||
public GameScreen(Player player) {
|
||||
this(player, new PipedSocket());
|
||||
}
|
||||
|
||||
//public GameScreen(final Char character) {
|
||||
public GameScreen(final Player player, Socket socket) {
|
||||
this.player = player;
|
||||
this.socket = socket;
|
||||
|
||||
/*
|
||||
input = new TextArea("", new TextArea.TextFieldStyle() {{
|
||||
this.font = Diablo.fonts.fontformal12;
|
||||
this.fontColor = Diablo.colors.white;
|
||||
this.background = new TextureRegionDrawable(Diablo.textures.modal);
|
||||
this.background = new PaletteIndexedColorDrawable(Diablo.colors.modal);
|
||||
this.cursor = new TextureRegionDrawable(Diablo.textures.white);
|
||||
}});
|
||||
input.setSize(Diablo.VIRTUAL_WIDTH * 0.75f, Diablo.fonts.fontformal12.getLineHeight() * 3);
|
||||
input.setPosition(Diablo.VIRTUAL_WIDTH_CENTER - input.getWidth() / 2, 100);
|
||||
input.setAlignment(Align.topLeft);
|
||||
input.setVisible(false);
|
||||
*/
|
||||
|
||||
output = new TextArea("", new TextArea.TextFieldStyle() {{
|
||||
this.font = Diablo.fonts.fontformal12;
|
||||
this.fontColor = Diablo.colors.white;
|
||||
this.cursor = new TextureRegionDrawable(Diablo.textures.white);
|
||||
}});
|
||||
output.setDebug(true);
|
||||
output.setSize(Diablo.VIRTUAL_WIDTH * 0.75f, Diablo.fonts.fontformal12.getLineHeight() * 8);
|
||||
output.setPosition(10, Diablo.VIRTUAL_HEIGHT - 10, Align.topLeft);
|
||||
output.setAlignment(Align.topLeft);
|
||||
output.setDisabled(true);
|
||||
output.setVisible(true);
|
||||
|
||||
escapePanel = new EscapePanel();
|
||||
|
||||
@ -130,14 +162,17 @@ public class GameScreen extends ScreenAdapter implements LoadingScreen.Loadable
|
||||
|
||||
stage = new Stage(Diablo.viewport, Diablo.batch);
|
||||
if (mobilePanel != null) stage.addActor(mobilePanel);
|
||||
//stage.addActor(input);
|
||||
stage.addActor(input);
|
||||
stage.addActor(output);
|
||||
stage.addActor(controlPanel);
|
||||
stage.addActor(escapePanel);
|
||||
stage.addActor(inventoryPanel);
|
||||
stage.addActor(characterPanel);
|
||||
stage.addActor(stashPanel);
|
||||
controlPanel.toFront();
|
||||
//input.toFront();
|
||||
if (mobilePanel != null) mobilePanel.toFront();
|
||||
output.toFront();
|
||||
input.toFront();
|
||||
escapePanel.toFront();
|
||||
|
||||
if (Gdx.app.getType() == Application.ApplicationType.Android || DEBUG_TOUCHPAD) {
|
||||
@ -187,12 +222,13 @@ public class GameScreen extends ScreenAdapter implements LoadingScreen.Loadable
|
||||
} else {
|
||||
escapePanel.setVisible(true);
|
||||
}
|
||||
/*} else if (key == Keys.Enter) {
|
||||
} else if (key == Keys.Enter) {
|
||||
boolean visible = !input.isVisible();
|
||||
if (!visible) {
|
||||
String text = input.getText();
|
||||
if (!text.isEmpty()) {
|
||||
Gdx.app.debug(TAG, text);
|
||||
out.println(text);
|
||||
input.setText("");
|
||||
}
|
||||
}
|
||||
@ -200,7 +236,7 @@ public class GameScreen extends ScreenAdapter implements LoadingScreen.Loadable
|
||||
input.setVisible(visible);
|
||||
if (visible) {
|
||||
stage.setKeyboardFocus(input);
|
||||
}*/
|
||||
}
|
||||
} else if (key == Keys.Inventory) {
|
||||
inventoryPanel.setVisible(!inventoryPanel.isVisible());
|
||||
} else if (key == Keys.Character) {
|
||||
@ -263,6 +299,15 @@ public class GameScreen extends ScreenAdapter implements LoadingScreen.Loadable
|
||||
|
||||
@Override
|
||||
public void render(float delta) {
|
||||
try {
|
||||
for (String str; in.ready() && (str = in.readLine()) != null;) {
|
||||
output.appendText(str);
|
||||
output.appendText("\n");
|
||||
}
|
||||
} catch (IOException e) {
|
||||
Gdx.app.error(TAG, e.getMessage());
|
||||
}
|
||||
|
||||
PaletteIndexedBatch b = Diablo.batch;
|
||||
b.setPalette(Diablo.palettes.act1);
|
||||
|
||||
@ -334,10 +379,21 @@ public class GameScreen extends ScreenAdapter implements LoadingScreen.Loadable
|
||||
mapRenderer.setPosition(player.origin());
|
||||
}
|
||||
}, 0, 1 / 25f);
|
||||
|
||||
if (socket != null && socket.isConnected()) {
|
||||
Gdx.app.log(TAG, "connecting to " + socket.getRemoteAddress() + "...");
|
||||
in = IOUtils.buffer(new InputStreamReader(socket.getInputStream()));
|
||||
out = new PrintWriter(socket.getOutputStream(), true);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void hide() {
|
||||
IOUtils.closeQuietly(in);
|
||||
IOUtils.closeQuietly(out);
|
||||
socket.dispose();
|
||||
Gdx.app.log(TAG, "Disposing socket... " + socket.isConnected());
|
||||
|
||||
Keys.Esc.removeStateListener(mappedKeyStateListener);
|
||||
Keys.Inventory.removeStateListener(mappedKeyStateListener);
|
||||
Keys.Character.removeStateListener(mappedKeyStateListener);
|
||||
|
@ -8,6 +8,7 @@ import com.badlogic.gdx.assets.AssetDescriptor;
|
||||
import com.badlogic.gdx.graphics.g2d.TextureRegion;
|
||||
import com.badlogic.gdx.net.HttpRequestBuilder;
|
||||
import com.badlogic.gdx.net.Socket;
|
||||
import com.badlogic.gdx.net.SocketHints;
|
||||
import com.badlogic.gdx.scenes.scene2d.Actor;
|
||||
import com.badlogic.gdx.scenes.scene2d.EventListener;
|
||||
import com.badlogic.gdx.scenes.scene2d.Group;
|
||||
@ -38,6 +39,7 @@ import java.net.SocketTimeoutException;
|
||||
|
||||
import gdx.diablo.Diablo;
|
||||
import gdx.diablo.codec.DC6;
|
||||
import gdx.diablo.entity3.Player;
|
||||
import gdx.diablo.graphics.PaletteIndexedBatch;
|
||||
import gdx.diablo.loader.DC6Loader;
|
||||
import gdx.diablo.server.Account;
|
||||
@ -80,6 +82,9 @@ public class LobbyScreen extends ScreenAdapter {
|
||||
|
||||
private Stage stage;
|
||||
|
||||
private Account account;
|
||||
private Player player;
|
||||
|
||||
private TextArea taChatOutput;
|
||||
private TextField tfChatInput;
|
||||
|
||||
@ -87,7 +92,10 @@ public class LobbyScreen extends ScreenAdapter {
|
||||
private PrintWriter out;
|
||||
private BufferedReader in;
|
||||
|
||||
public LobbyScreen(Account account) {
|
||||
public LobbyScreen(Account account, Player player) {
|
||||
this.account = account;
|
||||
this.player = player;
|
||||
|
||||
Diablo.assets.load(waitingroombkgdDescriptor);
|
||||
Diablo.assets.load(blankbckgDescriptor);
|
||||
Diablo.assets.load(creategamebckgDescriptor);
|
||||
@ -284,16 +292,16 @@ public class LobbyScreen extends ScreenAdapter {
|
||||
public void handleHttpResponse(Net.HttpResponse httpResponse) {
|
||||
String response = httpResponse.getResultAsString();
|
||||
try {
|
||||
Session session = new Json().fromJson(Session.class, response);
|
||||
final Session session = new Json().fromJson(Session.class, response);
|
||||
Gdx.app.log(TAG, "create-session " + response);
|
||||
|
||||
Socket socket = null;
|
||||
try {
|
||||
socket = Gdx.net.newClientSocket(Net.Protocol.TCP, session.host, session.port, null);
|
||||
Gdx.app.log(TAG, "create-session connect " + session.host + ":" + session.port + " " + socket.isConnected());
|
||||
} finally {
|
||||
if (socket != null) socket.dispose();
|
||||
}
|
||||
Gdx.app.postRunnable(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
Socket socket = Gdx.net.newClientSocket(Net.Protocol.TCP, session.host, session.port, null);
|
||||
Gdx.app.log(TAG, "create-session connect " + session.host + ":" + session.port + " " + socket.isConnected());
|
||||
Diablo.client.pushScreen(new LoadingScreen(new GameScreen(player, socket)));
|
||||
}
|
||||
});
|
||||
} catch (SerializationException e) {
|
||||
SessionError error = new Json().fromJson(SessionError.class, response);
|
||||
Gdx.app.log(TAG, "create-session " + error.toString());
|
||||
@ -404,7 +412,24 @@ public class LobbyScreen extends ScreenAdapter {
|
||||
public void changed(ChangeEvent event, Actor actor) {
|
||||
list.getSelection().setRequired(true);
|
||||
btnJoinGame.setDisabled(list.getSelection().isEmpty());
|
||||
tfGameName.setText(list.getSelected().toString());
|
||||
Session selected = list.getSelected();
|
||||
tfGameName.setText(selected != null ? selected.toString() : "");
|
||||
}
|
||||
});
|
||||
btnJoinGame.addListener(new ClickListener() {
|
||||
@Override
|
||||
public void clicked(InputEvent event, float x, float y) {
|
||||
if (btnJoinGame.isDisabled()) return;
|
||||
final Session session = list.getSelected();
|
||||
Gdx.app.log(TAG, "join-session " + session);
|
||||
Gdx.app.postRunnable(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
Socket socket = Gdx.net.newClientSocket(Net.Protocol.TCP, session.host, session.port, null);
|
||||
Gdx.app.log(TAG, "join-session connect " + session.host + ":" + session.port + " " + socket.isConnected());
|
||||
Diablo.client.pushScreen(new LoadingScreen(new GameScreen(player, socket)));
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
@ -499,15 +524,20 @@ public class LobbyScreen extends ScreenAdapter {
|
||||
}
|
||||
|
||||
private void connect() {
|
||||
try {
|
||||
socket = Gdx.net.newClientSocket(Net.Protocol.TCP, "hydra", 6113, null);
|
||||
in = IOUtils.buffer(new InputStreamReader(socket.getInputStream()));
|
||||
out = new PrintWriter(socket.getOutputStream(), true);
|
||||
} catch (Throwable t) {
|
||||
Gdx.app.error(TAG, t.getMessage());
|
||||
taChatOutput.appendText(t.getMessage());
|
||||
taChatOutput.appendText("\n");
|
||||
}
|
||||
new Thread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
socket = Gdx.net.newClientSocket(Net.Protocol.TCP, "hydra", 6113, new SocketHints());
|
||||
in = IOUtils.buffer(new InputStreamReader(socket.getInputStream()));
|
||||
out = new PrintWriter(socket.getOutputStream(), true);
|
||||
} catch (Throwable t) {
|
||||
Gdx.app.error(TAG, t.getMessage());
|
||||
taChatOutput.appendText(t.getMessage());
|
||||
taChatOutput.appendText("\n");
|
||||
}
|
||||
}
|
||||
}).start();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -125,7 +125,7 @@ public class LoginScreen extends ScreenAdapter {
|
||||
Gdx.app.postRunnable(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
Diablo.client.pushScreen(new LobbyScreen(account));
|
||||
Diablo.client.pushScreen(new SelectCharacterScreen2(account));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -60,7 +60,8 @@ public class SelectCharacterScreen extends ScreenAdapter {
|
||||
Diablo.client.popScreen();
|
||||
} else if (actor == btnOK) {
|
||||
assert selected != null;
|
||||
Diablo.client.clearAndSet(new LoadingScreen(new GameScreen(new Player(selected.getD2S()))));
|
||||
GameScreen game = new GameScreen(new Player(selected.getD2S()));
|
||||
Diablo.client.clearAndSet(new LoadingScreen(game));
|
||||
} else if (actor == btnCreateNewCharacter) {
|
||||
Diablo.client.pushScreen(new CreateCharacterScreen());
|
||||
}
|
||||
|
171
core/src/gdx/diablo/screen/SelectCharacterScreen2.java
Normal file
171
core/src/gdx/diablo/screen/SelectCharacterScreen2.java
Normal file
@ -0,0 +1,171 @@
|
||||
package gdx.diablo.screen;
|
||||
|
||||
import com.badlogic.gdx.Gdx;
|
||||
import com.badlogic.gdx.ScreenAdapter;
|
||||
import com.badlogic.gdx.assets.AssetDescriptor;
|
||||
import com.badlogic.gdx.files.FileHandle;
|
||||
import com.badlogic.gdx.graphics.g2d.TextureRegion;
|
||||
import com.badlogic.gdx.scenes.scene2d.Actor;
|
||||
import com.badlogic.gdx.scenes.scene2d.InputEvent;
|
||||
import com.badlogic.gdx.scenes.scene2d.Stage;
|
||||
import com.badlogic.gdx.scenes.scene2d.ui.Button;
|
||||
import com.badlogic.gdx.scenes.scene2d.utils.ChangeListener;
|
||||
import com.badlogic.gdx.scenes.scene2d.utils.ClickListener;
|
||||
import com.badlogic.gdx.scenes.scene2d.utils.TextureRegionDrawable;
|
||||
import com.badlogic.gdx.utils.Array;
|
||||
|
||||
import gdx.diablo.Diablo;
|
||||
import gdx.diablo.codec.D2S;
|
||||
import gdx.diablo.codec.DC6;
|
||||
import gdx.diablo.entity3.Player;
|
||||
import gdx.diablo.graphics.PaletteIndexedBatch;
|
||||
import gdx.diablo.loader.DC6Loader;
|
||||
import gdx.diablo.server.Account;
|
||||
import gdx.diablo.widget.SelectButton;
|
||||
import gdx.diablo.widget.TextButton;
|
||||
|
||||
public class SelectCharacterScreen2 extends ScreenAdapter {
|
||||
private static final String TAG = "SelectCharacterScreen2";
|
||||
|
||||
final AssetDescriptor<DC6> characterselectscreenEXPDescriptor = new AssetDescriptor<>("data\\global\\ui\\CharSelect\\charselectbckg.dc6", DC6.class, DC6Loader.DC6Parameters.COMBINE);
|
||||
TextureRegion characterselectscreenEXP;
|
||||
|
||||
final AssetDescriptor<DC6> MediumButtonBlankDescriptor = new AssetDescriptor<>("data\\global\\ui\\FrontEnd\\MediumButtonBlank.dc6", DC6.class);
|
||||
final AssetDescriptor<DC6> TallButtonBlankDescriptor = new AssetDescriptor<>("data\\global\\ui\\CharSelect\\TallButtonBlank.dc6", DC6.class);
|
||||
|
||||
private Stage stage;
|
||||
private Button btnExit;
|
||||
private Button btnOK;
|
||||
private Button btnCreateNewCharacter;
|
||||
|
||||
private SelectButton selected;
|
||||
private Array<SelectButton> characters;
|
||||
|
||||
private Account account;
|
||||
|
||||
public SelectCharacterScreen2(Account account) {
|
||||
this.account = account;
|
||||
SelectButton.load();
|
||||
Diablo.assets.load(characterselectscreenEXPDescriptor);
|
||||
Diablo.assets.load(MediumButtonBlankDescriptor);
|
||||
Diablo.assets.load(TallButtonBlankDescriptor);
|
||||
stage = new Stage(Diablo.viewport, Diablo.batch);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void show() {
|
||||
Diablo.assets.finishLoadingAsset(characterselectscreenEXPDescriptor);
|
||||
characterselectscreenEXP = Diablo.assets.get(characterselectscreenEXPDescriptor).getTexture();
|
||||
|
||||
ChangeListener clickListener = new ChangeListener() {
|
||||
@Override
|
||||
public void changed(ChangeEvent event, Actor actor) {
|
||||
if (actor == btnExit) {
|
||||
Diablo.client.popScreen();
|
||||
} else if (actor == btnOK) {
|
||||
assert selected != null;
|
||||
Diablo.client.pushScreen(new LobbyScreen(account, new Player(selected.getD2S())));
|
||||
} else if (actor == btnCreateNewCharacter) {
|
||||
//Diablo.client.pushScreen(new CreateCharacterScreen());
|
||||
}
|
||||
}
|
||||
};
|
||||
TextButton.TextButtonStyle tallButtonStyle = new TextButton.TextButtonStyle() {{
|
||||
Diablo.assets.finishLoadingAsset(TallButtonBlankDescriptor);
|
||||
DC6 pages = Diablo.assets.get(TallButtonBlankDescriptor);
|
||||
up = new TextureRegionDrawable(pages.getTexture(0));
|
||||
down = new TextureRegionDrawable(pages.getTexture(1));
|
||||
font = Diablo.fonts.fontexocet10;
|
||||
}};
|
||||
btnCreateNewCharacter = new TextButton(5273, tallButtonStyle);
|
||||
btnCreateNewCharacter.addListener(clickListener);
|
||||
btnCreateNewCharacter.setPosition(Diablo.VIRTUAL_WIDTH - btnCreateNewCharacter.getWidth() - 100, 100);
|
||||
|
||||
TextButton.TextButtonStyle mediumButtonStyle = new TextButton.TextButtonStyle() {{
|
||||
Diablo.assets.finishLoadingAsset(MediumButtonBlankDescriptor);
|
||||
DC6 pages = Diablo.assets.get(MediumButtonBlankDescriptor);
|
||||
up = new TextureRegionDrawable(pages.getTexture(0));
|
||||
down = new TextureRegionDrawable(pages.getTexture(1));
|
||||
font = Diablo.fonts.fontexocet10;
|
||||
}};
|
||||
btnExit = new TextButton(5101, mediumButtonStyle);
|
||||
btnExit.addListener(clickListener);
|
||||
btnExit.setPosition(20, 20);
|
||||
btnOK = new TextButton(5102, mediumButtonStyle);
|
||||
btnOK.addListener(clickListener);
|
||||
btnOK.setPosition(Diablo.VIRTUAL_WIDTH - 20 - btnOK.getWidth(), 20);
|
||||
//btnOK.setVisible(false);
|
||||
btnOK.setDisabled(true);
|
||||
|
||||
FileHandle savesLocation = Diablo.home.child("Save");
|
||||
FileHandle[] saves = savesLocation.list(D2S.EXT);
|
||||
characters = new Array<>();
|
||||
for (FileHandle save : saves) {
|
||||
Gdx.app.debug(TAG, "Loading " + save.toString());
|
||||
D2S d2s = D2S.loadFromFile(save);
|
||||
SelectButton button = new SelectButton(d2s);
|
||||
button.addListener(new ClickListener() {
|
||||
@Override
|
||||
public void clicked(InputEvent event, float x, float y) {
|
||||
if (getTapCount() >= 2) {
|
||||
assert selected == event.getListenerActor();
|
||||
btnOK.toggle();
|
||||
return;
|
||||
}
|
||||
|
||||
if (selected != null) selected.deselect();
|
||||
selected = (SelectButton) event.getListenerActor();
|
||||
selected.select();
|
||||
}
|
||||
});
|
||||
characters.add(button);
|
||||
if (selected == null) {
|
||||
selected = button;
|
||||
selected.select();
|
||||
btnOK.setDisabled(false);
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0, x, y = Diablo.VIRTUAL_HEIGHT - 64 - SelectButton.HEIGHT; i < characters.size; i++) {
|
||||
x = (i & 1) == 0 ? 64 : 64 + SelectButton.WIDTH;
|
||||
SelectButton character = characters.get(i);
|
||||
character.setPosition(x, y);
|
||||
stage.addActor(character);
|
||||
if ((i & 1) == 1) y -= SelectButton.HEIGHT;
|
||||
}
|
||||
|
||||
stage.addActor(btnExit);
|
||||
stage.addActor(btnOK);
|
||||
stage.addActor(btnCreateNewCharacter);
|
||||
Diablo.input.addProcessor(stage);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void hide() {
|
||||
Diablo.input.removeProcessor(stage);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
SelectButton.unload();
|
||||
for (SelectButton selectButton : characters) if (selected != selectButton) selectButton.dispose();
|
||||
Diablo.assets.unload(characterselectscreenEXPDescriptor.fileName);
|
||||
Diablo.assets.unload(MediumButtonBlankDescriptor.fileName);
|
||||
Diablo.assets.unload(TallButtonBlankDescriptor.fileName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render(float delta) {
|
||||
PaletteIndexedBatch b = Diablo.batch;
|
||||
b.begin(Diablo.palettes.units);
|
||||
int x = Diablo.VIRTUAL_WIDTH_CENTER;
|
||||
int y = Diablo.VIRTUAL_HEIGHT_CENTER;
|
||||
int xOff = (characterselectscreenEXP.getRegionWidth() / 2);
|
||||
int yOff = (characterselectscreenEXP.getRegionHeight() / 2);
|
||||
b.draw(characterselectscreenEXP, x - xOff, Diablo.VIRTUAL_HEIGHT - characterselectscreenEXP.getRegionHeight());
|
||||
b.end();
|
||||
|
||||
stage.act(delta);
|
||||
stage.draw();
|
||||
}
|
||||
}
|
52
core/src/gdx/diablo/server/PipedSocket.java
Normal file
52
core/src/gdx/diablo/server/PipedSocket.java
Normal file
@ -0,0 +1,52 @@
|
||||
package gdx.diablo.server;
|
||||
|
||||
import com.badlogic.gdx.net.Socket;
|
||||
import com.badlogic.gdx.utils.GdxRuntimeException;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.io.PipedInputStream;
|
||||
import java.io.PipedOutputStream;
|
||||
|
||||
public class PipedSocket implements Socket {
|
||||
PipedInputStream in;
|
||||
PipedOutputStream out;
|
||||
|
||||
public PipedSocket() {
|
||||
try {
|
||||
in = new PipedInputStream();
|
||||
out = new PipedOutputStream(in);
|
||||
} catch (IOException e) {
|
||||
throw new GdxRuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isConnected() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public InputStream getInputStream() {
|
||||
return in;
|
||||
}
|
||||
|
||||
@Override
|
||||
public OutputStream getOutputStream() {
|
||||
return out;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRemoteAddress() {
|
||||
return "localhost";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
IOUtils.closeQuietly(in);
|
||||
IOUtils.closeQuietly(out);
|
||||
}
|
||||
}
|
166
core/src/gdx/diablo/server/Server.java
Normal file
166
core/src/gdx/diablo/server/Server.java
Normal file
@ -0,0 +1,166 @@
|
||||
package gdx.diablo.server;
|
||||
|
||||
import com.badlogic.gdx.Gdx;
|
||||
import com.badlogic.gdx.Net;
|
||||
import com.badlogic.gdx.math.MathUtils;
|
||||
import com.badlogic.gdx.net.ServerSocket;
|
||||
import com.badlogic.gdx.net.Socket;
|
||||
import com.badlogic.gdx.utils.Disposable;
|
||||
import com.badlogic.gdx.utils.Json;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.PrintWriter;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
public class Server implements Disposable, Runnable {
|
||||
private static final String TAG = "Server";
|
||||
|
||||
private final Json json = new Json();
|
||||
private List<Client> clients = new CopyOnWriteArrayList<>();
|
||||
|
||||
ThreadGroup clientThreads;
|
||||
ServerSocket server;
|
||||
AtomicBoolean kill;
|
||||
Thread connectionListener;
|
||||
int port;
|
||||
String name;
|
||||
|
||||
public Server(int port) {
|
||||
this(port, "");
|
||||
}
|
||||
|
||||
public Server(int port, String name) {
|
||||
this.port = port;
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
clientThreads = new ThreadGroup(name + "-Clients");
|
||||
server = Gdx.net.newServerSocket(Net.Protocol.TCP, port, null);
|
||||
kill = new AtomicBoolean(false);
|
||||
connectionListener = new Thread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
Gdx.app.log(name, "listening on " + port);
|
||||
while (!kill.get()) {
|
||||
try {
|
||||
Socket socket = server.accept(null);
|
||||
new Client(socket).start();
|
||||
Gdx.app.log(name, "connection from " + socket.getRemoteAddress());
|
||||
} catch (Throwable t) {
|
||||
Gdx.app.log(name, t.getMessage(), t);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
connectionListener.setName("ConnectionListener");
|
||||
connectionListener.start();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
for (Client client : clients) {
|
||||
try {
|
||||
client.socket.dispose();
|
||||
} catch (Throwable t) {
|
||||
Gdx.app.error(name, t.getMessage(), t);
|
||||
}
|
||||
}
|
||||
|
||||
kill.set(true);
|
||||
//try {
|
||||
// connectionListener.join();
|
||||
//} catch (InterruptedException ignored) {}
|
||||
server.dispose();
|
||||
}
|
||||
|
||||
public void update() {
|
||||
/*
|
||||
Socket socket;
|
||||
BufferedReader in;
|
||||
PrintWriter out;
|
||||
for (ImmutableTriple<Socket, BufferedReader, PrintWriter> client : clients) {
|
||||
//System.out.println("client " + (client != null ? client.isConnected() : "false") + " " + client);
|
||||
socket = client.left;
|
||||
in = client.middle;
|
||||
try {
|
||||
if (!in.ready()) {
|
||||
Gdx.app.log(name, socket.getRemoteAddress() + " disconnected");
|
||||
clients.remove(client);
|
||||
socket.dispose();
|
||||
}
|
||||
} catch (IOException e) {
|
||||
Gdx.app.error(name, e.getMessage());
|
||||
}
|
||||
|
||||
try {
|
||||
for (String input; in.ready() && (input = in.readLine()) != null; ) {
|
||||
Gdx.app.log(name, socket.getRemoteAddress() + ": " + input);
|
||||
for (ImmutableTriple<Socket, BufferedReader, PrintWriter> broadcast : clients) {
|
||||
Gdx.app.log(name, "broadcast " + broadcast.left.getRemoteAddress() + ": " + input);
|
||||
out = broadcast.right;
|
||||
out.println(input);
|
||||
if (out.checkError()) {
|
||||
Gdx.app.log(name, "error at " + broadcast.left.getRemoteAddress());
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
Gdx.app.error(name, e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
private class Client extends Thread {
|
||||
Socket socket;
|
||||
BufferedReader in;
|
||||
PrintWriter out;
|
||||
|
||||
public Client(Socket socket) {
|
||||
super(clientThreads, "Client-" + String.format("%08X", MathUtils.random(1, Integer.MAX_VALUE - 1)));
|
||||
this.socket = socket;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
in = IOUtils.buffer(new InputStreamReader(socket.getInputStream()));
|
||||
out = new PrintWriter(socket.getOutputStream(), true);
|
||||
|
||||
for (Client client : clients) {
|
||||
client.out.println("CONNECT " + socket.getRemoteAddress());
|
||||
}
|
||||
|
||||
clients.add(this);
|
||||
|
||||
for (String input; (input = in.readLine()) != null; ) {
|
||||
String message = "MESSAGE " + socket.getRemoteAddress() + ": " + input;
|
||||
Gdx.app.log(getName(), message);
|
||||
for (Client client : clients) {
|
||||
client.out.println(message);
|
||||
}
|
||||
}
|
||||
|
||||
} catch (Throwable t) {
|
||||
Gdx.app.log(getName(), "ERROR " + socket.getRemoteAddress() + ": " + t.getMessage());
|
||||
} finally {
|
||||
clients.remove(this);
|
||||
String message = "DISCONNECT " + socket.getRemoteAddress();
|
||||
Gdx.app.log(getName(), message);
|
||||
for (Client client : clients) {
|
||||
client.out.println(message);
|
||||
}
|
||||
//IOUtils.closeQuietly(in);
|
||||
IOUtils.closeQuietly(out);
|
||||
if (socket != null) socket.dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -94,7 +94,7 @@ public class ChatServer extends ApplicationAdapter {
|
||||
PrintWriter out;
|
||||
|
||||
public Client(Socket socket) {
|
||||
super(clientThreads, "Client-" + String.format("%08X", MathUtils.random(1, Integer.MAX_VALUE)));
|
||||
super(clientThreads, "Client-" + String.format("%08X", MathUtils.random(1, Integer.MAX_VALUE - 1)));
|
||||
this.socket = socket;
|
||||
}
|
||||
|
||||
@ -103,6 +103,14 @@ public class ChatServer extends ApplicationAdapter {
|
||||
try {
|
||||
in = IOUtils.buffer(new InputStreamReader(socket.getInputStream()));
|
||||
out = new PrintWriter(socket.getOutputStream(), true);
|
||||
|
||||
final Calendar calendar = Calendar.getInstance();
|
||||
DateFormat format = DateFormat.getDateTimeInstance();
|
||||
out.println("BNET " + format.format(calendar.getTime()));
|
||||
for (PrintWriter client : clients) {
|
||||
client.println("CONNECT " + socket.getRemoteAddress());
|
||||
}
|
||||
|
||||
clients.add(out);
|
||||
|
||||
for (String input; (input = in.readLine()) != null; ) {
|
||||
|
43
server/src/gdx/diablo/server/DedicatedServer.java
Normal file
43
server/src/gdx/diablo/server/DedicatedServer.java
Normal file
@ -0,0 +1,43 @@
|
||||
package gdx.diablo.server;
|
||||
|
||||
import com.badlogic.gdx.utils.Disposable;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
public class DedicatedServer extends Thread implements Disposable {
|
||||
private static final String TAG = "DedicatedServer";
|
||||
|
||||
Server server;
|
||||
AtomicBoolean kill;
|
||||
|
||||
DedicatedServer(ThreadGroup group, String name, Server target) {
|
||||
super(group, target, name);
|
||||
server = target;
|
||||
kill = new AtomicBoolean(false);
|
||||
}
|
||||
|
||||
public static DedicatedServer newDedicatedServer(ThreadGroup group, String name, int port) {
|
||||
Server server = new Server(port, name);
|
||||
return new DedicatedServer(group, name, server);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
super.run();
|
||||
while (!kill.get()) {
|
||||
try {
|
||||
Thread.sleep(100);
|
||||
} catch (InterruptedException ignored) {}
|
||||
server.update();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
kill.set(true);
|
||||
//try {
|
||||
// join();
|
||||
//} catch (InterruptedException ignored) {}
|
||||
server.dispose();
|
||||
}
|
||||
}
|
@ -1,39 +0,0 @@
|
||||
package gdx.diablo.server;
|
||||
|
||||
import com.badlogic.gdx.Gdx;
|
||||
import com.badlogic.gdx.Net;
|
||||
import com.badlogic.gdx.net.ServerSocket;
|
||||
import com.badlogic.gdx.net.Socket;
|
||||
import com.badlogic.gdx.utils.Json;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
public class Server extends Thread {
|
||||
private static final String TAG = "Server";
|
||||
|
||||
private final Json json = new Json();
|
||||
|
||||
ServerSocket server;
|
||||
AtomicBoolean kill;
|
||||
int port;
|
||||
|
||||
Server(ThreadGroup group, String name, int port) {
|
||||
super(group, name);
|
||||
this.port = port;
|
||||
kill = new AtomicBoolean(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
server = Gdx.net.newServerSocket(Net.Protocol.TCP, port, null);
|
||||
while (!kill.get()) {
|
||||
Socket client = null;
|
||||
try {
|
||||
client = server.accept(null);
|
||||
Gdx.app.log(getName(), "connection from " + client.getRemoteAddress());
|
||||
} finally {
|
||||
if (client != null) client.dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -147,8 +147,8 @@ public class ServerBrowser extends ApplicationAdapter {
|
||||
session.port = 6114 + sessions.size();
|
||||
sessions.put(session.getName(), session);
|
||||
|
||||
String id = String.format("%08x", MathUtils.random(Integer.MAX_VALUE - 1));
|
||||
Server server = new Server(sessionGroup, "Session-" + id, session.port);
|
||||
String id = String.format("%08X", MathUtils.random(1, Integer.MAX_VALUE - 1));
|
||||
DedicatedServer server = DedicatedServer.newDedicatedServer(sessionGroup, "Session-" + id, session.port);
|
||||
server.start();
|
||||
servers.put(session.getName(), server);
|
||||
|
||||
|
@ -5,12 +5,16 @@ import com.badlogic.gdx.Net;
|
||||
import com.badlogic.gdx.backends.headless.HeadlessApplication;
|
||||
import com.badlogic.gdx.backends.headless.HeadlessApplicationConfiguration;
|
||||
import com.badlogic.gdx.net.HttpRequestBuilder;
|
||||
import com.badlogic.gdx.net.Socket;
|
||||
import com.badlogic.gdx.utils.Json;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.apache.commons.lang3.ObjectUtils;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
public class ServerTest {
|
||||
@ -19,7 +23,7 @@ public class ServerTest {
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
HeadlessApplicationConfiguration config = new HeadlessApplicationConfiguration();
|
||||
new HeadlessApplication(new Server(), config);
|
||||
new HeadlessApplication(new ServerBrowser(), config);
|
||||
}
|
||||
|
||||
@After
|
||||
@ -122,4 +126,103 @@ public class ServerTest {
|
||||
});
|
||||
while (!done.get()) ;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConnect() {
|
||||
final AtomicBoolean done = new AtomicBoolean();
|
||||
Net.HttpRequest request = new HttpRequestBuilder()
|
||||
.newRequest()
|
||||
.method(Net.HttpMethods.POST)
|
||||
.url("http://hydra:6112/create-session")
|
||||
.jsonContent(new Session.Builder() {{
|
||||
name = "test game";
|
||||
password = "1111";
|
||||
desc = "test desc";
|
||||
}})
|
||||
.build();
|
||||
Gdx.net.sendHttpRequest(request, new Net.HttpResponseListener() {
|
||||
@Override
|
||||
public void handleHttpResponse(Net.HttpResponse httpResponse) {
|
||||
Session session = new Json().fromJson(Session.class, httpResponse.getResultAsString());
|
||||
Gdx.app.log(TAG, httpResponse.getResultAsString());
|
||||
Socket socket = null;
|
||||
try {
|
||||
socket = Gdx.net.newClientSocket(Net.Protocol.TCP, session.host, session.port, null);
|
||||
} finally {
|
||||
if (socket != null) socket.dispose();
|
||||
}
|
||||
|
||||
done.set(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void failed(Throwable t) {
|
||||
Gdx.app.log(TAG, ObjectUtils.toString(t));
|
||||
done.set(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cancelled() {
|
||||
Gdx.app.log(TAG, "cancelled");
|
||||
done.set(true);
|
||||
}
|
||||
});
|
||||
while (!done.get());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDisconnect() {
|
||||
final AtomicBoolean done = new AtomicBoolean();
|
||||
Net.HttpRequest request = new HttpRequestBuilder()
|
||||
.newRequest()
|
||||
.method(Net.HttpMethods.POST)
|
||||
.url("http://hydra:6112/create-session")
|
||||
.jsonContent(new Session.Builder() {{
|
||||
name = "test game";
|
||||
password = "1111";
|
||||
desc = "test desc";
|
||||
}})
|
||||
.build();
|
||||
Gdx.net.sendHttpRequest(request, new Net.HttpResponseListener() {
|
||||
@Override
|
||||
public void handleHttpResponse(Net.HttpResponse httpResponse) {
|
||||
Session session = new Json().fromJson(Session.class, httpResponse.getResultAsString());
|
||||
Socket socket = null;
|
||||
try {
|
||||
socket = Gdx.net.newClientSocket(Net.Protocol.TCP, session.host, session.port, null);
|
||||
Gdx.app.log(TAG, "Connected: " + socket.isConnected());
|
||||
new PrintWriter(socket.getOutputStream(), true).println("test");
|
||||
try {
|
||||
Thread.sleep(500);
|
||||
} catch (InterruptedException ignored) {}
|
||||
} finally {
|
||||
Gdx.app.log(TAG, "disconnecting...");
|
||||
if (socket != null) {
|
||||
//IOUtils.closeQuietly(socket.getInputStream());
|
||||
IOUtils.closeQuietly(socket.getOutputStream());
|
||||
socket.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
Thread.sleep(500);
|
||||
} catch (InterruptedException ignored) {}
|
||||
|
||||
done.set(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void failed(Throwable t) {
|
||||
Gdx.app.log(TAG, ObjectUtils.toString(t));
|
||||
done.set(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cancelled() {
|
||||
Gdx.app.log(TAG, "cancelled");
|
||||
done.set(true);
|
||||
}
|
||||
});
|
||||
while (!done.get()) ;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user