mirror of
https://github.com/Retera/WarsmashModEngine.git
synced 2022-07-31 17:38:59 +02:00
Commit of updates for server from last weekend
This commit is contained in:
parent
ccacf2cb57
commit
9becca479e
@ -21,7 +21,7 @@ allprojects {
|
||||
appName = "warsmash"
|
||||
gdxVersion = '1.9.8'
|
||||
antlrVersion = '4.7'
|
||||
xstreamVersion = '1.4.9'
|
||||
xstreamVersion = '1.4.19'
|
||||
}
|
||||
|
||||
repositories {
|
||||
|
@ -24,6 +24,7 @@ import com.badlogic.gdx.utils.viewport.ExtendViewport;
|
||||
import com.badlogic.gdx.utils.viewport.FitViewport;
|
||||
import com.badlogic.gdx.utils.viewport.Viewport;
|
||||
import com.etheller.warsmash.datasources.DataSource;
|
||||
import com.etheller.warsmash.networking.uberserver.GamingNetworkConnectionImpl;
|
||||
import com.etheller.warsmash.parsers.fdf.GameUI;
|
||||
import com.etheller.warsmash.parsers.jass.Jass2.RootFrameListener;
|
||||
import com.etheller.warsmash.units.DataTable;
|
||||
@ -210,7 +211,7 @@ public class WarsmashGdxMenuScreen implements InputProcessor, Screen, SingleMode
|
||||
WarsmashGdxMenuScreen.this.mainInstance.setScene(WarsmashGdxMenuScreen.this.uiScene);
|
||||
}
|
||||
}
|
||||
});
|
||||
}, new GamingNetworkConnectionImpl("localhost"));
|
||||
|
||||
final ModelInstance libgdxContentInstance = new LibGDXContentLayerModel(null, this.viewer, "",
|
||||
PathSolver.DEFAULT, "").addInstance();
|
||||
|
@ -0,0 +1,122 @@
|
||||
package com.etheller.warsmash.networking.uberserver;
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
import java.nio.ByteOrder;
|
||||
|
||||
import net.warsmash.nio.channels.SelectableChannelOpener;
|
||||
import net.warsmash.nio.channels.WritableOutput;
|
||||
import net.warsmash.nio.util.ExceptionListener;
|
||||
import net.warsmash.uberserver.GamingNetwork;
|
||||
import net.warsmash.uberserver.GamingNetworkClientToServerWriter;
|
||||
import net.warsmash.uberserver.GamingNetworkConnection;
|
||||
import net.warsmash.uberserver.GamingNetworkServerToClientListener;
|
||||
import net.warsmash.uberserver.GamingNetworkServerToClientListener.GamingNetworkServerToClientNotifier;
|
||||
import net.warsmash.uberserver.TCPGamingNetworkServerToClientParser;
|
||||
|
||||
public class GamingNetworkConnectionImpl implements GamingNetworkConnection {
|
||||
private WritableOutput tcpChannel = null;
|
||||
private final SelectableChannelOpener selectableChannelOpener;
|
||||
private Thread networkThread;
|
||||
private final GamingNetworkServerToClientNotifier notifier;
|
||||
private GamingNetworkClientToServerWriter gamingNetworkClientToServerWriter;
|
||||
private final String gateway;
|
||||
|
||||
public GamingNetworkConnectionImpl(final String gateway) {
|
||||
this.gateway = gateway;
|
||||
this.selectableChannelOpener = new SelectableChannelOpener();
|
||||
this.notifier = new GamingNetworkServerToClientNotifier();
|
||||
}
|
||||
|
||||
public void start() {
|
||||
this.tcpChannel = this.selectableChannelOpener.openTCPClientChannel(
|
||||
new InetSocketAddress("localhost", GamingNetwork.PORT),
|
||||
new TCPGamingNetworkServerToClientParser(this.notifier), ExceptionListener.THROW_RUNTIME,
|
||||
8 * 1024 * 1024, ByteOrder.LITTLE_ENDIAN);
|
||||
this.gamingNetworkClientToServerWriter = new GamingNetworkClientToServerWriter(this.tcpChannel);
|
||||
this.networkThread = new Thread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
while (true) {
|
||||
GamingNetworkConnectionImpl.this.selectableChannelOpener.select(0);
|
||||
}
|
||||
}
|
||||
});
|
||||
this.networkThread.start();
|
||||
}
|
||||
|
||||
public void stop() {
|
||||
if (this.tcpChannel != null) {
|
||||
this.tcpChannel.close();
|
||||
this.tcpChannel = null;
|
||||
this.gamingNetworkClientToServerWriter = null;
|
||||
}
|
||||
if (this.networkThread != null) {
|
||||
this.networkThread.interrupt();
|
||||
this.networkThread = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handshake(final String gameId, final int version) {
|
||||
this.gamingNetworkClientToServerWriter.handshake(gameId, version);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void createAccount(final String username, final char[] passwordHash) {
|
||||
this.gamingNetworkClientToServerWriter.createAccount(username, passwordHash);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void login(final String username, final char[] passwordHash) {
|
||||
this.gamingNetworkClientToServerWriter.login(username, passwordHash);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void joinChannel(final long sessionToken, final String channelName) {
|
||||
this.gamingNetworkClientToServerWriter.joinChannel(sessionToken, channelName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void chatMessage(final long sessionToken, final String text) {
|
||||
this.gamingNetworkClientToServerWriter.chatMessage(sessionToken, text);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void emoteMessage(final long sessionToken, final String text) {
|
||||
this.gamingNetworkClientToServerWriter.emoteMessage(sessionToken, text);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void disconnected() {
|
||||
stop();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addListener(final GamingNetworkServerToClientListener listener) {
|
||||
this.notifier.addSubscriber(listener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void userRequestDisconnect() {
|
||||
stop();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean userRequestConnect() {
|
||||
stop();
|
||||
try {
|
||||
start();
|
||||
return true;
|
||||
}
|
||||
catch (final Exception exc) {
|
||||
exc.printStackTrace();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getGatewayString() {
|
||||
return this.gateway;
|
||||
}
|
||||
|
||||
}
|
@ -42,6 +42,7 @@ import com.etheller.warsmash.parsers.fdf.datamodel.fields.StringPairFrameDefinit
|
||||
import com.etheller.warsmash.parsers.fdf.datamodel.fields.visitor.GetMenuItemFieldVisitor;
|
||||
import com.etheller.warsmash.parsers.fdf.frames.AbstractUIFrame;
|
||||
import com.etheller.warsmash.parsers.fdf.frames.BackdropFrame;
|
||||
import com.etheller.warsmash.parsers.fdf.frames.ClickConsumingTextureFrame;
|
||||
import com.etheller.warsmash.parsers.fdf.frames.ControlFrame;
|
||||
import com.etheller.warsmash.parsers.fdf.frames.EditBoxFrame;
|
||||
import com.etheller.warsmash.parsers.fdf.frames.FilterModeTextureFrame;
|
||||
@ -58,6 +59,7 @@ import com.etheller.warsmash.parsers.fdf.frames.SimpleFrame;
|
||||
import com.etheller.warsmash.parsers.fdf.frames.SimpleStatusBarFrame;
|
||||
import com.etheller.warsmash.parsers.fdf.frames.SpriteFrame;
|
||||
import com.etheller.warsmash.parsers.fdf.frames.StringFrame;
|
||||
import com.etheller.warsmash.parsers.fdf.frames.TextAreaFrame;
|
||||
import com.etheller.warsmash.parsers.fdf.frames.TextButtonFrame;
|
||||
import com.etheller.warsmash.parsers.fdf.frames.TextureFrame;
|
||||
import com.etheller.warsmash.parsers.fdf.frames.UIFrame;
|
||||
@ -74,6 +76,7 @@ import com.etheller.warsmash.viewer5.handlers.w3x.ui.command.FocusableFrame;
|
||||
import com.hiveworkshop.rms.parsers.mdlx.MdlxLayer.FilterMode;
|
||||
|
||||
public final class GameUI extends AbstractUIFrame implements UIFrame {
|
||||
private static final boolean SHOW_BLACKNESS_BEHIND_DIALOGS = false;
|
||||
public static final boolean DEBUG = false;
|
||||
private static final boolean PIN_FAIL_IS_FATAL = false;
|
||||
private final DataSource dataSource;
|
||||
@ -96,6 +99,7 @@ public final class GameUI extends AbstractUIFrame implements UIFrame {
|
||||
private final BitmapFont font;
|
||||
private final BitmapFont font20;
|
||||
private final DynamicFontGeneratorHolder dynamicFontGeneratorHolder;
|
||||
private final List<FocusableFrame> focusableFrames = new ArrayList<>();
|
||||
|
||||
public GameUI(final DataSource dataSource, final GameSkin skin, final Viewport viewport, final Scene uiScene,
|
||||
final AbstractMdxModelViewer modelViewer, final int racialCommandIndex, final WTS mapStrings) {
|
||||
@ -436,8 +440,7 @@ public final class GameUI extends AbstractUIFrame implements UIFrame {
|
||||
}
|
||||
inflatedFrame = spriteFrame;
|
||||
}
|
||||
else if ("FRAME".equals(frameDefinition.getFrameType())
|
||||
|| "DIALOG".equals(frameDefinition.getFrameType())) {
|
||||
else if ("FRAME".equals(frameDefinition.getFrameType())) {
|
||||
final SimpleFrame simpleFrame = new SimpleFrame(frameDefinition.getName(), parent);
|
||||
// TODO: we should not need to put ourselves in this map 2x, but we do
|
||||
// since there are nested inflate calls happening before the general case
|
||||
@ -449,6 +452,36 @@ public final class GameUI extends AbstractUIFrame implements UIFrame {
|
||||
}
|
||||
inflatedFrame = simpleFrame;
|
||||
}
|
||||
else if ("DIALOG".equals(frameDefinition.getFrameType())) {
|
||||
final SimpleFrame simpleFrame = new SimpleFrame(frameDefinition.getName(), parent);
|
||||
// TODO: we should not need to put ourselves in this map 2x, but we do
|
||||
// since there are nested inflate calls happening before the general case
|
||||
// mapping
|
||||
final String dialogBackdropKey = frameDefinition.getString("DialogBackdrop");
|
||||
this.nameToFrame.put(frameDefinition.getName(), simpleFrame);
|
||||
|
||||
if (SHOW_BLACKNESS_BEHIND_DIALOGS) {
|
||||
final TextureFrame modalDialogBlacknessScreenCover = new ClickConsumingTextureFrame(null, parent,
|
||||
false, null);
|
||||
modalDialogBlacknessScreenCover.setTexture("Textures\\Black32.blp", this);
|
||||
modalDialogBlacknessScreenCover.setColor(1.0f, 1.0f, 1.0f, 0.5f);
|
||||
modalDialogBlacknessScreenCover.setSetAllPoints(true);
|
||||
simpleFrame.add(modalDialogBlacknessScreenCover);
|
||||
}
|
||||
for (final FrameDefinition childDefinition : frameDefinition.getInnerFrames()) {
|
||||
if (childDefinition.getName().equals(dialogBackdropKey)) {
|
||||
final UIFrame inflatedChild = inflate(childDefinition, simpleFrame, frameDefinition,
|
||||
inDecorateFileNames || childDefinition.has("DecorateFileNames"));
|
||||
inflatedChild.setSetAllPoints(true);
|
||||
simpleFrame.add(inflatedChild);
|
||||
}
|
||||
else {
|
||||
simpleFrame.add(inflate(childDefinition, simpleFrame, frameDefinition,
|
||||
inDecorateFileNames || childDefinition.has("DecorateFileNames")));
|
||||
}
|
||||
}
|
||||
inflatedFrame = simpleFrame;
|
||||
}
|
||||
else if ("TEXT".equals(frameDefinition.getFrameType())) {
|
||||
final Float textLength = frameDefinition.getFloat("TextLength");
|
||||
TextJustify justifyH = frameDefinition.getTextJustify("FontJustificationH");
|
||||
@ -996,6 +1029,71 @@ public final class GameUI extends AbstractUIFrame implements UIFrame {
|
||||
}
|
||||
inflatedFrame = controlFrame;
|
||||
}
|
||||
else if (false && "TEXTAREA".equals(frameDefinition.getFrameType())) {
|
||||
// TODO advanced components here
|
||||
final TextAreaFrame controlFrame = new TextAreaFrame(frameDefinition.getName(), parent, viewport2);
|
||||
// TODO: we should not need to put ourselves in this map 2x, but we do
|
||||
// since there are nested inflate calls happening before the general case
|
||||
// mapping
|
||||
this.nameToFrame.put(frameDefinition.getName(), controlFrame);
|
||||
final String controlBackdropKey = frameDefinition.getString("ControlBackdrop");
|
||||
final String listBoxScrollBarKey = frameDefinition.getString("TextAreaScrollBar");
|
||||
final Float textAreaLineHeight = frameDefinition.getFloat("TextAreaLineHeight");
|
||||
if (textAreaLineHeight != null) {
|
||||
controlFrame.setLineHeight(convertY(viewport2, textAreaLineHeight));
|
||||
}
|
||||
final Float textAreaLineGap = frameDefinition.getFloat("TextAreaLineGap");
|
||||
if (textAreaLineGap != null) {
|
||||
controlFrame.setLineGap(convertY(viewport2, textAreaLineGap));
|
||||
}
|
||||
final Float textAreaInset = frameDefinition.getFloat("TextAreaInset");
|
||||
if (textAreaInset != null) {
|
||||
controlFrame.setInset(convertY(viewport2, textAreaInset));
|
||||
}
|
||||
final Float textAreaMaxLines = frameDefinition.getFloat("TextAreaMaxLines");
|
||||
if (textAreaMaxLines != null) {
|
||||
controlFrame.setMaxLines(textAreaMaxLines.intValue());
|
||||
}
|
||||
|
||||
FontDefinition font = frameDefinition.getFont("FrameFont");
|
||||
if ((font == null) && (parentDefinitionIfAvailable != null)) {
|
||||
font = parentDefinitionIfAvailable.getFont("FrameFont");
|
||||
}
|
||||
this.fontParam.size = (int) convertY(viewport2,
|
||||
(font == null ? (textAreaLineHeight == null ? 0.06f : textAreaLineHeight)
|
||||
: font.getFontSize()));
|
||||
if (this.fontParam.size == 0) {
|
||||
this.fontParam.size = 24;
|
||||
}
|
||||
frameFont = this.dynamicFontGeneratorHolder
|
||||
.getFontGenerator(font == null ? "MasterFont" : font.getFontName())
|
||||
.generateFont(this.fontParam);
|
||||
controlFrame.setFrameFont(frameFont);
|
||||
for (final FrameDefinition childDefinition : frameDefinition.getInnerFrames()) {
|
||||
if (childDefinition.getName().equals(controlBackdropKey)) {
|
||||
final UIFrame inflatedChild = inflate(childDefinition, controlFrame, frameDefinition,
|
||||
inDecorateFileNames || childDefinition.has("DecorateFileNames"));
|
||||
inflatedChild.setSetAllPoints(true);
|
||||
controlFrame.setControlBackdrop(inflatedChild);
|
||||
}
|
||||
else if (childDefinition.getName().equals(listBoxScrollBarKey)) {
|
||||
final UIFrame inflatedChild = inflate(childDefinition, controlFrame, frameDefinition,
|
||||
inDecorateFileNames || childDefinition.has("DecorateFileNames"));
|
||||
controlFrame.setScrollBarFrame((ScrollBarFrame) inflatedChild);
|
||||
}
|
||||
}
|
||||
if (controlFrame.getScrollBarFrame() == null) {
|
||||
// TODO this is probably not how this should work
|
||||
for (final FrameDefinition childDefinition : frameDefinition.getInnerFrames()) {
|
||||
if (childDefinition.getFrameType().equals("SCROLLBAR")) {
|
||||
final UIFrame inflatedChild = inflate(childDefinition, controlFrame, frameDefinition,
|
||||
inDecorateFileNames || childDefinition.has("DecorateFileNames"));
|
||||
controlFrame.setScrollBarFrame((ScrollBarFrame) inflatedChild);
|
||||
}
|
||||
}
|
||||
}
|
||||
inflatedFrame = controlFrame;
|
||||
}
|
||||
else if ("MENU".equals(frameDefinition.getFrameType())) {
|
||||
// TODO advanced components here
|
||||
final MenuFrame controlFrame = new MenuFrame(frameDefinition.getName(), parent);
|
||||
@ -1216,6 +1314,9 @@ public final class GameUI extends AbstractUIFrame implements UIFrame {
|
||||
if (frameDefinition.has("SetAllPoints")) {
|
||||
inflatedFrame.setSetAllPoints(true);
|
||||
}
|
||||
if ((inflatedFrame instanceof FocusableFrame) && (frameDefinition.get("TabFocusNext") != null)) {
|
||||
this.focusableFrames.add((FocusableFrame) inflatedFrame);
|
||||
}
|
||||
Float width = frameDefinition.getFloat("Width");
|
||||
if (width != null) {
|
||||
inflatedFrame.setWidth(convertX(viewport2, width));
|
||||
@ -1412,4 +1513,8 @@ public final class GameUI extends AbstractUIFrame implements UIFrame {
|
||||
public void setMapStrings(final WTS mapStrings) {
|
||||
this.mapStrings = mapStrings;
|
||||
}
|
||||
|
||||
public List<FocusableFrame> getFocusableFrames() {
|
||||
return this.focusableFrames;
|
||||
}
|
||||
}
|
||||
|
@ -20,6 +20,13 @@ public abstract class AbstractUIFrame extends AbstractRenderableFrame implements
|
||||
this.childFrames.add(childFrame);
|
||||
}
|
||||
|
||||
public void add(final int index, final UIFrame childFrame) {
|
||||
if (childFrame == null) {
|
||||
return;
|
||||
}
|
||||
this.childFrames.add(index, childFrame);
|
||||
}
|
||||
|
||||
public void remove(final UIFrame childFrame) {
|
||||
if (childFrame == null) {
|
||||
return;
|
||||
|
@ -0,0 +1,35 @@
|
||||
package com.etheller.warsmash.parsers.fdf.frames;
|
||||
|
||||
import com.etheller.warsmash.parsers.fdf.datamodel.Vector4Definition;
|
||||
|
||||
public class ClickConsumingTextureFrame extends TextureFrame {
|
||||
|
||||
public ClickConsumingTextureFrame(final String name, final UIFrame parent, final boolean decorateFileNames,
|
||||
final Vector4Definition texCoord) {
|
||||
super(name, parent, decorateFileNames, texCoord);
|
||||
}
|
||||
|
||||
@Override
|
||||
public UIFrame touchUp(final float screenX, final float screenY, final int button) {
|
||||
if (isVisible() && this.renderBounds.contains(screenX, screenY)) {
|
||||
return this;
|
||||
}
|
||||
return super.touchUp(screenX, screenY, button);
|
||||
}
|
||||
|
||||
@Override
|
||||
public UIFrame touchDown(final float screenX, final float screenY, final int button) {
|
||||
if (isVisible() && this.renderBounds.contains(screenX, screenY)) {
|
||||
return this;
|
||||
}
|
||||
return super.touchDown(screenX, screenY, button);
|
||||
}
|
||||
|
||||
@Override
|
||||
public UIFrame getFrameChildUnderMouse(final float screenX, final float screenY) {
|
||||
if (isVisible() && this.renderBounds.contains(screenX, screenY)) {
|
||||
return this;
|
||||
}
|
||||
return super.getFrameChildUnderMouse(screenX, screenY);
|
||||
}
|
||||
}
|
@ -24,12 +24,16 @@ public class ControlFrame extends AbstractRenderableFrame {
|
||||
|
||||
@Override
|
||||
protected void innerPositionBounds(final GameUI gameUI, final Viewport viewport) {
|
||||
this.controlBackdrop.positionBounds(gameUI, viewport);
|
||||
if (this.controlBackdrop != null) {
|
||||
this.controlBackdrop.positionBounds(gameUI, viewport);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void internalRender(final SpriteBatch batch, final BitmapFont baseFont, final GlyphLayout glyphLayout) {
|
||||
this.controlBackdrop.render(batch, baseFont, glyphLayout);
|
||||
if (this.controlBackdrop != null) {
|
||||
this.controlBackdrop.render(batch, baseFont, glyphLayout);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -26,6 +26,8 @@ public class EditBoxFrame extends AbstractRenderableFrame implements FocusableFr
|
||||
private Viewport viewport;
|
||||
private GlyphLayout glyphLayout;
|
||||
private Runnable onChange;
|
||||
private Runnable onEnter;
|
||||
private CharacterFilter filter = CharacterFilter.DEFAULT;
|
||||
|
||||
public EditBoxFrame(final String name, final UIFrame parent, final float editBorderSize,
|
||||
final Color editCursorColor) {
|
||||
@ -115,6 +117,12 @@ public class EditBoxFrame extends AbstractRenderableFrame implements FocusableFr
|
||||
}
|
||||
break;
|
||||
}
|
||||
case Input.Keys.ENTER: {
|
||||
if (this.onEnter != null) {
|
||||
this.onEnter.run();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@ -126,7 +134,7 @@ public class EditBoxFrame extends AbstractRenderableFrame implements FocusableFr
|
||||
|
||||
@Override
|
||||
public boolean keyTyped(final char character) {
|
||||
if (Character.isAlphabetic(character) || Character.isDigit(character) || (character == ' ')) {
|
||||
if (this.filter.allow(character)) {
|
||||
final String prevText = this.editTextFrame.getText();
|
||||
final int prevTextLength = prevText.length();
|
||||
final int cursorIndex = Math.min(this.cursorIndex, prevTextLength);
|
||||
@ -173,8 +181,47 @@ public class EditBoxFrame extends AbstractRenderableFrame implements FocusableFr
|
||||
return this.editTextFrame.getText();
|
||||
}
|
||||
|
||||
public void setText(final String text, final GameUI gameUI, final Viewport uiViewport) {
|
||||
this.editTextFrame.setText(text, gameUI, uiViewport);
|
||||
}
|
||||
|
||||
public void setOnChange(final Runnable onChange) {
|
||||
this.onChange = onChange;
|
||||
}
|
||||
|
||||
public void setOnEnter(final Runnable onEnter) {
|
||||
this.onEnter = onEnter;
|
||||
}
|
||||
|
||||
public void setFilter(final CharacterFilter filter) {
|
||||
this.filter = filter;
|
||||
}
|
||||
|
||||
public void setFilterAllowAny() {
|
||||
this.filter = new CharacterFilter() {
|
||||
@Override
|
||||
public boolean allow(final char character) {
|
||||
return EditBoxFrame.this.editTextFrame.getFrameFont().getData().hasGlyph(character)
|
||||
&& (character >= 32);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public static interface CharacterFilter {
|
||||
boolean allow(char character);
|
||||
|
||||
CharacterFilter DEFAULT = new CharacterFilter() {
|
||||
@Override
|
||||
public boolean allow(final char character) {
|
||||
return Character.isAlphabetic(character) || Character.isDigit(character) || (character == ' ');
|
||||
}
|
||||
};
|
||||
|
||||
CharacterFilter ACCOUNT = new CharacterFilter() {
|
||||
@Override
|
||||
public boolean allow(final char character) {
|
||||
return Character.isAlphabetic(character) || Character.isDigit(character);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -9,253 +9,262 @@ import com.etheller.warsmash.parsers.fdf.datamodel.FramePoint;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.ui.command.ClickableFrame;
|
||||
|
||||
public class ScrollBarFrame extends AbstractRenderableFrame implements ClickableFrame {
|
||||
private UIFrame controlBackdrop;
|
||||
private UIFrame incButtonFrame;
|
||||
private UIFrame decButtonFrame;
|
||||
private UIFrame thumbButtonFrame;
|
||||
private int scrollValuePercent = 50;
|
||||
private ScrollBarChangeListener changeListener = ScrollBarChangeListener.DO_NOTHING;
|
||||
private UIFrame controlBackdrop;
|
||||
private UIFrame incButtonFrame;
|
||||
private UIFrame decButtonFrame;
|
||||
private UIFrame thumbButtonFrame;
|
||||
private int scrollValuePercent = 50;
|
||||
private ScrollBarChangeListener changeListener = ScrollBarChangeListener.DO_NOTHING;
|
||||
|
||||
public ScrollBarFrame(final String name, final UIFrame parent, boolean vertical) {
|
||||
super(name, parent);
|
||||
}
|
||||
public ScrollBarFrame(final String name, final UIFrame parent, final boolean vertical) {
|
||||
super(name, parent);
|
||||
}
|
||||
|
||||
public void setControlBackdrop(final UIFrame controlBackdrop) {
|
||||
this.controlBackdrop = controlBackdrop;
|
||||
}
|
||||
public void setControlBackdrop(final UIFrame controlBackdrop) {
|
||||
this.controlBackdrop = controlBackdrop;
|
||||
}
|
||||
|
||||
public void setIncButtonFrame(UIFrame incButtonFrame) {
|
||||
this.incButtonFrame = incButtonFrame;
|
||||
((GlueButtonFrame)incButtonFrame).setButtonListener(new GlueButtonFrame.ButtonListener() {
|
||||
@Override
|
||||
public void mouseDown(GameUI gameUI, Viewport uiViewport) {
|
||||
public void setIncButtonFrame(final UIFrame incButtonFrame) {
|
||||
this.incButtonFrame = incButtonFrame;
|
||||
((GlueButtonFrame) incButtonFrame).setButtonListener(new GlueButtonFrame.ButtonListener() {
|
||||
@Override
|
||||
public void mouseDown(final GameUI gameUI, final Viewport uiViewport) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseUp(GameUI gameUI, Viewport uiViewport) {
|
||||
setValue(gameUI, uiViewport, scrollValuePercent+10);
|
||||
}
|
||||
@Override
|
||||
public void mouseUp(final GameUI gameUI, final Viewport uiViewport) {
|
||||
setValue(gameUI, uiViewport, ScrollBarFrame.this.scrollValuePercent + 10);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseDragged(GameUI rootFrame, Viewport uiViewport, float x, float y) {
|
||||
@Override
|
||||
public void mouseDragged(final GameUI rootFrame, final Viewport uiViewport, final float x, final float y) {
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void setDecButtonFrame(UIFrame decButtonFrame) {
|
||||
this.decButtonFrame = decButtonFrame;
|
||||
((GlueButtonFrame)decButtonFrame).setButtonListener(new GlueButtonFrame.ButtonListener() {
|
||||
@Override
|
||||
public void mouseDown(GameUI gameUI, Viewport uiViewport) {
|
||||
public void setDecButtonFrame(final UIFrame decButtonFrame) {
|
||||
this.decButtonFrame = decButtonFrame;
|
||||
((GlueButtonFrame) decButtonFrame).setButtonListener(new GlueButtonFrame.ButtonListener() {
|
||||
@Override
|
||||
public void mouseDown(final GameUI gameUI, final Viewport uiViewport) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseUp(GameUI gameUI, Viewport uiViewport) {
|
||||
setValue(gameUI, uiViewport, scrollValuePercent-10);
|
||||
}
|
||||
@Override
|
||||
public void mouseUp(final GameUI gameUI, final Viewport uiViewport) {
|
||||
setValue(gameUI, uiViewport, ScrollBarFrame.this.scrollValuePercent - 10);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseDragged(GameUI rootFrame, Viewport uiViewport, float x, float y) {
|
||||
@Override
|
||||
public void mouseDragged(final GameUI rootFrame, final Viewport uiViewport, final float x, final float y) {
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void setThumbButtonFrame(UIFrame thumbButtonFrame) {
|
||||
if (this.thumbButtonFrame instanceof GlueButtonFrame) {
|
||||
((GlueButtonFrame) this.thumbButtonFrame).setButtonListener(GlueButtonFrame.ButtonListener.DO_NOTHING);
|
||||
}
|
||||
this.thumbButtonFrame = thumbButtonFrame;
|
||||
if (thumbButtonFrame instanceof GlueButtonFrame) {
|
||||
GlueButtonFrame frame = (GlueButtonFrame) thumbButtonFrame;
|
||||
frame.setButtonListener(new GlueButtonFrame.ButtonListener() {
|
||||
@Override
|
||||
public void mouseDown(GameUI gameUI, Viewport uiViewport) {
|
||||
}
|
||||
public void setThumbButtonFrame(final UIFrame thumbButtonFrame) {
|
||||
if (this.thumbButtonFrame instanceof GlueButtonFrame) {
|
||||
((GlueButtonFrame) this.thumbButtonFrame).setButtonListener(GlueButtonFrame.ButtonListener.DO_NOTHING);
|
||||
}
|
||||
this.thumbButtonFrame = thumbButtonFrame;
|
||||
if (thumbButtonFrame instanceof GlueButtonFrame) {
|
||||
final GlueButtonFrame frame = (GlueButtonFrame) thumbButtonFrame;
|
||||
frame.setButtonListener(new GlueButtonFrame.ButtonListener() {
|
||||
@Override
|
||||
public void mouseDown(final GameUI gameUI, final Viewport uiViewport) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseUp(GameUI gameUI, Viewport uiViewport) {
|
||||
}
|
||||
@Override
|
||||
public void mouseUp(final GameUI gameUI, final Viewport uiViewport) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseDragged(GameUI rootFrame, Viewport uiViewport, float x, float y) {
|
||||
ScrollBarFrame.this.mouseDragged(rootFrame, uiViewport, x, y);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public void mouseDragged(final GameUI rootFrame, final Viewport uiViewport, final float x,
|
||||
final float y) {
|
||||
ScrollBarFrame.this.mouseDragged(rootFrame, uiViewport, x, y);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private float getMaxThumbButtonTravelDistance() {
|
||||
return renderBounds.height - thumbButtonFrame.getAssignedHeight() - incButtonFrame.getAssignedHeight() - decButtonFrame.getAssignedHeight();
|
||||
}
|
||||
private float getMaxThumbButtonTravelDistance() {
|
||||
final float incButtonFrameHeight = this.incButtonFrame == null ? 0 : this.incButtonFrame.getAssignedHeight();
|
||||
final float decButtonFrameHeight = this.decButtonFrame == null ? 0 : this.decButtonFrame.getAssignedHeight();
|
||||
return this.renderBounds.height - this.thumbButtonFrame.getAssignedHeight() - incButtonFrameHeight
|
||||
- decButtonFrameHeight;
|
||||
}
|
||||
|
||||
public void setValue(GameUI gameUI, Viewport uiViewport, int percent) {
|
||||
this.scrollValuePercent = Math.min(100,Math.max(0,percent));
|
||||
updateThumbButtonPoint();
|
||||
changeListener.onChange(gameUI, uiViewport, this.scrollValuePercent);
|
||||
positionBounds(gameUI, uiViewport);
|
||||
}
|
||||
public void setValue(final GameUI gameUI, final Viewport uiViewport, final int percent) {
|
||||
this.scrollValuePercent = Math.min(100, Math.max(0, percent));
|
||||
updateThumbButtonPoint();
|
||||
this.changeListener.onChange(gameUI, uiViewport, this.scrollValuePercent);
|
||||
positionBounds(gameUI, uiViewport);
|
||||
}
|
||||
|
||||
public int getValue() {
|
||||
return scrollValuePercent;
|
||||
}
|
||||
public int getValue() {
|
||||
return this.scrollValuePercent;
|
||||
}
|
||||
|
||||
public void updateThumbButtonPoint() {
|
||||
float newYValue = scrollValuePercent / 100f * getMaxThumbButtonTravelDistance();
|
||||
thumbButtonFrame.addSetPoint(new SetPoint(FramePoint.BOTTOM, decButtonFrame, FramePoint.TOP, 0, newYValue));
|
||||
}
|
||||
public void updateThumbButtonPoint() {
|
||||
final float newYValue = (this.scrollValuePercent / 100f) * getMaxThumbButtonTravelDistance();
|
||||
this.thumbButtonFrame
|
||||
.addSetPoint(new SetPoint(FramePoint.BOTTOM, this.decButtonFrame, FramePoint.TOP, 0, newYValue));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void innerPositionBounds(final GameUI gameUI, final Viewport viewport) {
|
||||
if (this.controlBackdrop != null) {
|
||||
this.controlBackdrop.positionBounds(gameUI, viewport);
|
||||
}
|
||||
if (this.incButtonFrame != null) {
|
||||
this.incButtonFrame.positionBounds(gameUI, viewport);
|
||||
}
|
||||
if (this.decButtonFrame != null) {
|
||||
this.decButtonFrame.positionBounds(gameUI, viewport);
|
||||
}
|
||||
updateThumbButtonPoint();
|
||||
if (this.thumbButtonFrame != null) {
|
||||
this.thumbButtonFrame.positionBounds(gameUI, viewport);
|
||||
}
|
||||
}
|
||||
@Override
|
||||
protected void innerPositionBounds(final GameUI gameUI, final Viewport viewport) {
|
||||
if (this.controlBackdrop != null) {
|
||||
this.controlBackdrop.positionBounds(gameUI, viewport);
|
||||
}
|
||||
if (this.incButtonFrame != null) {
|
||||
this.incButtonFrame.positionBounds(gameUI, viewport);
|
||||
}
|
||||
if (this.decButtonFrame != null) {
|
||||
this.decButtonFrame.positionBounds(gameUI, viewport);
|
||||
}
|
||||
updateThumbButtonPoint();
|
||||
if (this.thumbButtonFrame != null) {
|
||||
this.thumbButtonFrame.positionBounds(gameUI, viewport);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void internalRender(final SpriteBatch batch, final BitmapFont baseFont, final GlyphLayout glyphLayout) {
|
||||
if (this.controlBackdrop != null) {
|
||||
controlBackdrop.render(batch, baseFont, glyphLayout);
|
||||
}
|
||||
if (this.incButtonFrame != null) {
|
||||
this.incButtonFrame.render(batch, baseFont, glyphLayout);
|
||||
}
|
||||
if (this.decButtonFrame != null) {
|
||||
this.decButtonFrame.render(batch, baseFont, glyphLayout);
|
||||
}
|
||||
if (this.thumbButtonFrame != null) {
|
||||
this.thumbButtonFrame.render(batch, baseFont, glyphLayout);
|
||||
}
|
||||
}
|
||||
@Override
|
||||
protected void internalRender(final SpriteBatch batch, final BitmapFont baseFont, final GlyphLayout glyphLayout) {
|
||||
if (this.controlBackdrop != null) {
|
||||
this.controlBackdrop.render(batch, baseFont, glyphLayout);
|
||||
}
|
||||
if (this.incButtonFrame != null) {
|
||||
this.incButtonFrame.render(batch, baseFont, glyphLayout);
|
||||
}
|
||||
if (this.decButtonFrame != null) {
|
||||
this.decButtonFrame.render(batch, baseFont, glyphLayout);
|
||||
}
|
||||
if (this.thumbButtonFrame != null) {
|
||||
this.thumbButtonFrame.render(batch, baseFont, glyphLayout);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseDown(final GameUI gameUI, final Viewport uiViewport) {
|
||||
}
|
||||
@Override
|
||||
public void mouseDown(final GameUI gameUI, final Viewport uiViewport) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseUp(final GameUI gameUI, final Viewport uiViewport) {
|
||||
}
|
||||
@Override
|
||||
public void mouseUp(final GameUI gameUI, final Viewport uiViewport) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseEnter(final GameUI gameUI, final Viewport uiViewport) {
|
||||
}
|
||||
@Override
|
||||
public void mouseEnter(final GameUI gameUI, final Viewport uiViewport) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseExit(final GameUI gameUI, final Viewport uiViewport) {
|
||||
}
|
||||
@Override
|
||||
public void mouseExit(final GameUI gameUI, final Viewport uiViewport) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(final int button) {
|
||||
}
|
||||
@Override
|
||||
public void onClick(final int button) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseDragged(GameUI rootFrame, Viewport uiViewport, float x, float y) {
|
||||
float maxThumbButtonTravelDistance = getMaxThumbButtonTravelDistance();
|
||||
int newScrollValuePercent = Math.min(100,Math.max(0,(int)((y - renderBounds.y - decButtonFrame.getAssignedHeight() - thumbButtonFrame.getAssignedHeight()/2) / maxThumbButtonTravelDistance * 100)));
|
||||
if(newScrollValuePercent != scrollValuePercent) {
|
||||
setValue(rootFrame, uiViewport, newScrollValuePercent);
|
||||
positionBounds(rootFrame, uiViewport);
|
||||
}
|
||||
@Override
|
||||
public void mouseDragged(final GameUI rootFrame, final Viewport uiViewport, final float x, final float y) {
|
||||
final float maxThumbButtonTravelDistance = getMaxThumbButtonTravelDistance();
|
||||
final int newScrollValuePercent = Math.min(100,
|
||||
Math.max(0,
|
||||
(int) (((y - this.renderBounds.y - this.decButtonFrame.getAssignedHeight()
|
||||
- (this.thumbButtonFrame.getAssignedHeight() / 2)) / maxThumbButtonTravelDistance)
|
||||
* 100)));
|
||||
if (newScrollValuePercent != this.scrollValuePercent) {
|
||||
setValue(rootFrame, uiViewport, newScrollValuePercent);
|
||||
positionBounds(rootFrame, uiViewport);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public UIFrame touchUp(final float screenX, final float screenY, final int button) {
|
||||
if (isVisible() && this.renderBounds.contains(screenX, screenY)) {
|
||||
UIFrame frameChildUnderMouse = thumbButtonFrame.touchUp(screenX, screenY, button);
|
||||
if (frameChildUnderMouse != null) {
|
||||
return frameChildUnderMouse;
|
||||
}
|
||||
frameChildUnderMouse = incButtonFrame.touchUp(screenX, screenY, button);
|
||||
if (frameChildUnderMouse != null) {
|
||||
return frameChildUnderMouse;
|
||||
}
|
||||
frameChildUnderMouse = decButtonFrame.touchUp(screenX, screenY, button);
|
||||
if (frameChildUnderMouse != null) {
|
||||
return frameChildUnderMouse;
|
||||
}
|
||||
frameChildUnderMouse = controlBackdrop.touchUp(screenX, screenY, button);
|
||||
if (frameChildUnderMouse != null) {
|
||||
return frameChildUnderMouse;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
return super.touchUp(screenX, screenY, button);
|
||||
}
|
||||
@Override
|
||||
public UIFrame touchUp(final float screenX, final float screenY, final int button) {
|
||||
if (isVisible() && this.renderBounds.contains(screenX, screenY)) {
|
||||
UIFrame frameChildUnderMouse = this.thumbButtonFrame.touchUp(screenX, screenY, button);
|
||||
if (frameChildUnderMouse != null) {
|
||||
return frameChildUnderMouse;
|
||||
}
|
||||
frameChildUnderMouse = this.incButtonFrame.touchUp(screenX, screenY, button);
|
||||
if (frameChildUnderMouse != null) {
|
||||
return frameChildUnderMouse;
|
||||
}
|
||||
frameChildUnderMouse = this.decButtonFrame.touchUp(screenX, screenY, button);
|
||||
if (frameChildUnderMouse != null) {
|
||||
return frameChildUnderMouse;
|
||||
}
|
||||
frameChildUnderMouse = this.controlBackdrop.touchUp(screenX, screenY, button);
|
||||
if (frameChildUnderMouse != null) {
|
||||
return frameChildUnderMouse;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
return super.touchUp(screenX, screenY, button);
|
||||
}
|
||||
|
||||
@Override
|
||||
public UIFrame touchDown(final float screenX, final float screenY, final int button) {
|
||||
if (isVisible() && this.renderBounds.contains(screenX, screenY)) {
|
||||
UIFrame frameChildUnderMouse = thumbButtonFrame.touchDown(screenX, screenY, button);
|
||||
if (frameChildUnderMouse != null) {
|
||||
return frameChildUnderMouse;
|
||||
}
|
||||
frameChildUnderMouse = incButtonFrame.touchDown(screenX, screenY, button);
|
||||
if (frameChildUnderMouse != null) {
|
||||
return frameChildUnderMouse;
|
||||
}
|
||||
frameChildUnderMouse = decButtonFrame.touchDown(screenX, screenY, button);
|
||||
if (frameChildUnderMouse != null) {
|
||||
return frameChildUnderMouse;
|
||||
}
|
||||
frameChildUnderMouse = controlBackdrop.touchDown(screenX, screenY, button);
|
||||
if (frameChildUnderMouse != null) {
|
||||
return frameChildUnderMouse;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
return super.touchDown(screenX, screenY, button);
|
||||
}
|
||||
@Override
|
||||
public UIFrame touchDown(final float screenX, final float screenY, final int button) {
|
||||
if (isVisible() && this.renderBounds.contains(screenX, screenY)) {
|
||||
UIFrame frameChildUnderMouse = this.thumbButtonFrame.touchDown(screenX, screenY, button);
|
||||
if (frameChildUnderMouse != null) {
|
||||
return frameChildUnderMouse;
|
||||
}
|
||||
frameChildUnderMouse = this.incButtonFrame.touchDown(screenX, screenY, button);
|
||||
if (frameChildUnderMouse != null) {
|
||||
return frameChildUnderMouse;
|
||||
}
|
||||
frameChildUnderMouse = this.decButtonFrame.touchDown(screenX, screenY, button);
|
||||
if (frameChildUnderMouse != null) {
|
||||
return frameChildUnderMouse;
|
||||
}
|
||||
frameChildUnderMouse = this.controlBackdrop.touchDown(screenX, screenY, button);
|
||||
if (frameChildUnderMouse != null) {
|
||||
return frameChildUnderMouse;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
return super.touchDown(screenX, screenY, button);
|
||||
}
|
||||
|
||||
@Override
|
||||
public UIFrame getFrameChildUnderMouse(final float screenX, final float screenY) {
|
||||
if (isVisible() && this.renderBounds.contains(screenX, screenY)) {
|
||||
UIFrame frameChildUnderMouse = thumbButtonFrame.getFrameChildUnderMouse(screenX, screenY);
|
||||
if (frameChildUnderMouse != null) {
|
||||
return frameChildUnderMouse;
|
||||
}
|
||||
frameChildUnderMouse = incButtonFrame.getFrameChildUnderMouse(screenX, screenY);
|
||||
if (frameChildUnderMouse != null) {
|
||||
return frameChildUnderMouse;
|
||||
}
|
||||
frameChildUnderMouse = decButtonFrame.getFrameChildUnderMouse(screenX, screenY);
|
||||
if (frameChildUnderMouse != null) {
|
||||
return frameChildUnderMouse;
|
||||
}
|
||||
frameChildUnderMouse = controlBackdrop.getFrameChildUnderMouse(screenX, screenY);
|
||||
if (frameChildUnderMouse != null) {
|
||||
return frameChildUnderMouse;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
return super.getFrameChildUnderMouse(screenX, screenY);
|
||||
}
|
||||
@Override
|
||||
public UIFrame getFrameChildUnderMouse(final float screenX, final float screenY) {
|
||||
if (isVisible() && this.renderBounds.contains(screenX, screenY)) {
|
||||
UIFrame frameChildUnderMouse = this.thumbButtonFrame.getFrameChildUnderMouse(screenX, screenY);
|
||||
if (frameChildUnderMouse != null) {
|
||||
return frameChildUnderMouse;
|
||||
}
|
||||
frameChildUnderMouse = this.incButtonFrame.getFrameChildUnderMouse(screenX, screenY);
|
||||
if (frameChildUnderMouse != null) {
|
||||
return frameChildUnderMouse;
|
||||
}
|
||||
frameChildUnderMouse = this.decButtonFrame.getFrameChildUnderMouse(screenX, screenY);
|
||||
if (frameChildUnderMouse != null) {
|
||||
return frameChildUnderMouse;
|
||||
}
|
||||
frameChildUnderMouse = this.controlBackdrop.getFrameChildUnderMouse(screenX, screenY);
|
||||
if (frameChildUnderMouse != null) {
|
||||
return frameChildUnderMouse;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
return super.getFrameChildUnderMouse(screenX, screenY);
|
||||
}
|
||||
|
||||
public void setChangeListener(ScrollBarChangeListener changeListener) {
|
||||
this.changeListener = changeListener;
|
||||
}
|
||||
public void setChangeListener(final ScrollBarChangeListener changeListener) {
|
||||
this.changeListener = changeListener;
|
||||
}
|
||||
|
||||
public interface ScrollBarChangeListener {
|
||||
void onChange(GameUI gameUI, Viewport uiViewport, int newValue);
|
||||
public interface ScrollBarChangeListener {
|
||||
void onChange(GameUI gameUI, Viewport uiViewport, int newValue);
|
||||
|
||||
ScrollBarChangeListener DO_NOTHING = new ScrollBarChangeListener() {
|
||||
@Override
|
||||
public void onChange(GameUI gameUI, Viewport uiViewport, int newValue) {
|
||||
ScrollBarChangeListener DO_NOTHING = new ScrollBarChangeListener() {
|
||||
@Override
|
||||
public void onChange(final GameUI gameUI, final Viewport uiViewport, final int newValue) {
|
||||
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,224 @@
|
||||
package com.etheller.warsmash.parsers.fdf.frames;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import com.badlogic.gdx.graphics.Color;
|
||||
import com.badlogic.gdx.graphics.g2d.BitmapFont;
|
||||
import com.badlogic.gdx.graphics.g2d.GlyphLayout;
|
||||
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
|
||||
import com.badlogic.gdx.utils.viewport.Viewport;
|
||||
import com.etheller.warsmash.parsers.fdf.GameUI;
|
||||
import com.etheller.warsmash.parsers.fdf.datamodel.FramePoint;
|
||||
import com.etheller.warsmash.parsers.fdf.datamodel.TextJustify;
|
||||
|
||||
public class TextAreaFrame extends ControlFrame implements ScrollBarFrame.ScrollBarChangeListener {
|
||||
// TODO where are these colors in the UI definition files?
|
||||
private final List<String> listItems = new ArrayList<>();
|
||||
private final List<StringFrame> stringFrames = new ArrayList<>();
|
||||
private BitmapFont frameFont;
|
||||
private float lineHeight;
|
||||
private float lineGap;
|
||||
private float inset;
|
||||
private int maxLines;
|
||||
|
||||
private GameUI gameUI;
|
||||
private Viewport viewport;
|
||||
private ScrollBarFrame scrollBarFrame;
|
||||
|
||||
public TextAreaFrame(final String name, final UIFrame parent, final Viewport viewport) {
|
||||
super(name, parent);
|
||||
}
|
||||
|
||||
public void setLineGap(final float lineGap) {
|
||||
this.lineGap = lineGap;
|
||||
}
|
||||
|
||||
public void setLineHeight(final float lineHeight) {
|
||||
this.lineHeight = lineHeight;
|
||||
}
|
||||
|
||||
public void setInset(final float inset) {
|
||||
this.inset = inset;
|
||||
}
|
||||
|
||||
public void setMaxLines(final int maxLines) {
|
||||
this.maxLines = maxLines;
|
||||
}
|
||||
|
||||
public void setScrollBarFrame(final ScrollBarFrame scrollBarFrame) {
|
||||
this.scrollBarFrame = scrollBarFrame;
|
||||
// TODO might be a better place to add these set points, but we definitely need
|
||||
// them
|
||||
scrollBarFrame
|
||||
.addSetPoint(new SetPoint(FramePoint.TOPRIGHT, this, FramePoint.TOPRIGHT, -this.inset, -this.inset));
|
||||
scrollBarFrame.addSetPoint(
|
||||
new SetPoint(FramePoint.BOTTOMRIGHT, this, FramePoint.BOTTOMRIGHT, -this.inset, this.inset));
|
||||
scrollBarFrame.setChangeListener(this);
|
||||
}
|
||||
|
||||
public ScrollBarFrame getScrollBarFrame() {
|
||||
return this.scrollBarFrame;
|
||||
}
|
||||
|
||||
public void setFrameFont(final BitmapFont frameFont) {
|
||||
this.frameFont = frameFont;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void innerPositionBounds(final GameUI gameUI, final Viewport viewport) {
|
||||
this.gameUI = gameUI;
|
||||
this.viewport = viewport;
|
||||
super.innerPositionBounds(gameUI, viewport);
|
||||
updateUI(gameUI, viewport);
|
||||
}
|
||||
|
||||
private void positionChildren(final GameUI gameUI, final Viewport viewport) {
|
||||
for (final StringFrame frame : this.stringFrames) {
|
||||
frame.positionBounds(gameUI, viewport);
|
||||
}
|
||||
if (this.scrollBarFrame != null) {
|
||||
this.scrollBarFrame.positionBounds(gameUI, viewport);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void internalRender(final SpriteBatch batch, final BitmapFont baseFont, final GlyphLayout glyphLayout) {
|
||||
super.internalRender(batch, baseFont, glyphLayout);
|
||||
for (final StringFrame frame : this.stringFrames) {
|
||||
frame.render(batch, baseFont, glyphLayout);
|
||||
}
|
||||
if (this.scrollBarFrame != null) {
|
||||
this.scrollBarFrame.render(batch, baseFont, glyphLayout);
|
||||
}
|
||||
}
|
||||
|
||||
public void addItem(final String item, final GameUI gameUI, final Viewport viewport) {
|
||||
this.listItems.add(item);
|
||||
while (this.listItems.size() > this.maxLines) {
|
||||
// TODO this is not performant
|
||||
this.listItems.remove(0);
|
||||
}
|
||||
updateUI(gameUI, viewport);
|
||||
}
|
||||
|
||||
public void setItems(final List<String> items, final GameUI gameUI, final Viewport viewport) {
|
||||
this.listItems.clear();
|
||||
this.listItems.addAll(items);
|
||||
updateUI(gameUI, viewport);
|
||||
}
|
||||
|
||||
public void removeItem(final String item, final GameUI gameUI, final Viewport viewport) {
|
||||
this.listItems.remove(item);
|
||||
updateUI(gameUI, viewport);
|
||||
}
|
||||
|
||||
public void removeItem(final int index, final GameUI gameUI, final Viewport viewport) {
|
||||
this.listItems.remove(index);
|
||||
updateUI(gameUI, viewport);
|
||||
}
|
||||
|
||||
private void updateUI(final GameUI gameUI, final Viewport viewport) {
|
||||
StringFrame prev = null;
|
||||
final int numStringFrames = (int) (Math
|
||||
.floor((this.renderBounds.height - (this.inset * 2)) / (this.lineHeight + this.lineGap)));
|
||||
final int scrollOffset = computeScrollOffset(numStringFrames);
|
||||
if (numStringFrames != this.stringFrames.size()) {
|
||||
this.stringFrames.clear();
|
||||
for (int stringFrameIndex = 0; stringFrameIndex < numStringFrames; stringFrameIndex++) {
|
||||
final int index = stringFrameIndex + scrollOffset;
|
||||
final StringFrame stringFrame = new StringFrame("LISTY" + index, this, Color.WHITE, TextJustify.LEFT,
|
||||
TextJustify.MIDDLE, this.frameFont, null, null, null);
|
||||
if (index < this.listItems.size()) {
|
||||
gameUI.setText(stringFrame, this.listItems.get(index));
|
||||
}
|
||||
else {
|
||||
gameUI.setText(stringFrame, "");
|
||||
}
|
||||
stringFrame.setWidth(this.renderBounds.width - (this.inset * 2));
|
||||
stringFrame.setHeight(this.lineHeight);
|
||||
if (prev != null) {
|
||||
stringFrame.addSetPoint(
|
||||
new SetPoint(FramePoint.TOPLEFT, prev, FramePoint.BOTTOMLEFT, 0, -this.lineGap));
|
||||
}
|
||||
else {
|
||||
stringFrame.addSetPoint(new SetPoint(FramePoint.TOPLEFT, this, FramePoint.TOPLEFT, this.inset,
|
||||
-this.inset - this.lineGap));
|
||||
}
|
||||
this.stringFrames.add(stringFrame);
|
||||
prev = stringFrame;
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (int stringFrameIndex = 0; stringFrameIndex < numStringFrames; stringFrameIndex++) {
|
||||
final int index = stringFrameIndex + scrollOffset;
|
||||
final StringFrame stringFrame = this.stringFrames.get(stringFrameIndex);
|
||||
if (index < this.listItems.size()) {
|
||||
gameUI.setText(stringFrame, this.listItems.get(index));
|
||||
}
|
||||
else {
|
||||
gameUI.setText(stringFrame, "");
|
||||
}
|
||||
}
|
||||
}
|
||||
this.scrollBarFrame.setVisible(this.listItems.size() > numStringFrames);
|
||||
positionChildren(gameUI, viewport);
|
||||
}
|
||||
|
||||
private int computeScrollOffset(final int numStringFrames) {
|
||||
int scrollOffset;
|
||||
if ((this.scrollBarFrame != null) && (this.listItems.size() > numStringFrames)) {
|
||||
scrollOffset = (int) Math
|
||||
.ceil(((100 - this.scrollBarFrame.getValue()) / 100f) * (this.listItems.size() - numStringFrames));
|
||||
}
|
||||
else {
|
||||
scrollOffset = 0;
|
||||
}
|
||||
return scrollOffset;
|
||||
}
|
||||
|
||||
@Override
|
||||
public UIFrame touchDown(final float screenX, final float screenY, final int button) {
|
||||
if (isVisible() && this.renderBounds.contains(screenX, screenY)) {
|
||||
if (this.scrollBarFrame != null) {
|
||||
final UIFrame sliderFrameChildUnderMouse = this.scrollBarFrame.touchDown(screenX, screenY, button);
|
||||
if (sliderFrameChildUnderMouse != null) {
|
||||
return sliderFrameChildUnderMouse;
|
||||
}
|
||||
}
|
||||
}
|
||||
return super.touchDown(screenX, screenY, button);
|
||||
}
|
||||
|
||||
@Override
|
||||
public UIFrame touchUp(final float screenX, final float screenY, final int button) {
|
||||
if (isVisible() && this.renderBounds.contains(screenX, screenY)) {
|
||||
if (this.scrollBarFrame != null) {
|
||||
final UIFrame sliderFrameChildUnderMouse = this.scrollBarFrame.touchDown(screenX, screenY, button);
|
||||
if (sliderFrameChildUnderMouse != null) {
|
||||
return sliderFrameChildUnderMouse;
|
||||
}
|
||||
}
|
||||
}
|
||||
return super.touchUp(screenX, screenY, button);
|
||||
}
|
||||
|
||||
@Override
|
||||
public UIFrame getFrameChildUnderMouse(final float screenX, final float screenY) {
|
||||
if (isVisible() && this.renderBounds.contains(screenX, screenY)) {
|
||||
if (this.scrollBarFrame != null) {
|
||||
final UIFrame sliderFrameChildUnderMouse = this.scrollBarFrame.getFrameChildUnderMouse(screenX,
|
||||
screenY);
|
||||
if (sliderFrameChildUnderMouse != null) {
|
||||
return sliderFrameChildUnderMouse;
|
||||
}
|
||||
}
|
||||
}
|
||||
return super.getFrameChildUnderMouse(screenX, screenY);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChange(final GameUI gameUI, final Viewport uiViewport, final int newValue) {
|
||||
updateUI(gameUI, uiViewport);
|
||||
}
|
||||
}
|
@ -91,10 +91,10 @@ public class StandardObjectData {
|
||||
profile.readTXT(this.source.getResourceAsStream("Units\\ItemFunc.txt"), true);
|
||||
profile.readTXT(this.source.getResourceAsStream("Units\\ItemStrings.txt"), true);
|
||||
itemData.readSLK(this.source.getResourceAsStream("Units\\ItemData.slk"));
|
||||
// final InputStream itemSkin = this.source.getResourceAsStream("Units\\ItemSkin.txt");
|
||||
// if (itemSkin != null) {
|
||||
// profile.readTXT(itemSkin, true);
|
||||
// }
|
||||
final InputStream itemSkin = this.source.getResourceAsStream("Units\\ItemSkin.txt");
|
||||
if (itemSkin != null) {
|
||||
profile.readTXT(itemSkin, true);
|
||||
}
|
||||
}
|
||||
catch (final IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
|
@ -19,7 +19,7 @@ public class MappedData {
|
||||
|
||||
public MappedData(final String buffer) {
|
||||
if (buffer != null) {
|
||||
this.load(buffer);
|
||||
load(buffer);
|
||||
}
|
||||
}
|
||||
|
||||
@ -33,11 +33,18 @@ public class MappedData {
|
||||
final SlkFile file = new SlkFile(buffer);
|
||||
final List<List<Object>> rows = file.rows;
|
||||
final List<Object> header = rows.get(0);
|
||||
int keyColumn = 0;
|
||||
for (int i = 1; i < header.size(); i++) {
|
||||
final Object headerColumnName = header.get(i);
|
||||
if ("AnimationEventCode".equals(headerColumnName)) {
|
||||
keyColumn = i;
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 1, l = rows.size(); i < l; i++) {
|
||||
final List<Object> row = rows.get(i);
|
||||
if (row != null) {
|
||||
String name = (String) row.get(0);
|
||||
String name = (String) row.get(keyColumn);
|
||||
|
||||
if (name != null) {
|
||||
name = name.toLowerCase();
|
||||
|
@ -1,5 +1,7 @@
|
||||
package com.etheller.warsmash.util;
|
||||
|
||||
import net.warsmash.uberserver.GamingNetwork;
|
||||
|
||||
public class WarsmashConstants {
|
||||
public static final int MAX_PLAYERS = 16;
|
||||
/*
|
||||
@ -25,7 +27,7 @@ public class WarsmashConstants {
|
||||
// find it yet so I used this
|
||||
public static final String DEFAULT_STRING = "Default string";
|
||||
|
||||
public static final boolean CATCH_CURSOR = false;
|
||||
public static final boolean CATCH_CURSOR = true;
|
||||
public static final boolean VERBOSE_LOGGING = false;
|
||||
public static final boolean ENABLE_DEBUG = false;
|
||||
public static final char SPECIAL_ESCAPE_KEYCODE = 0x7E;
|
||||
@ -40,4 +42,9 @@ public class WarsmashConstants {
|
||||
public static final boolean LOAD_UNITS_FROM_WORLDEDIT_DATA = false;
|
||||
public static final boolean CRASH_ON_INCOMPATIBLE_132_FEATURES = false;
|
||||
public static final boolean FIRE_DEATH_EVENTS_ON_REMOVEUNIT = false;
|
||||
|
||||
public static final String getGameId() {
|
||||
return (GAME_VERSION == 0) ? GamingNetwork.GAME_ID_BASE : GamingNetwork.GAME_ID_XPAC;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -163,9 +163,13 @@ public class EventObjectEmitterObject extends GenericObject implements EmitterOb
|
||||
if (!model.reforged) {
|
||||
tables.add(viewer.loadGeneric(pathSolver.solve("UI\\SoundInfo\\AnimLookups.slk", solverParams).finalSrc,
|
||||
FetchDataTypeName.SLK, mappedDataCallback));
|
||||
tables.add(viewer.loadGeneric(pathSolver.solve("UI\\SoundInfo\\AnimSounds.slk", solverParams).finalSrc,
|
||||
FetchDataTypeName.SLK, mappedDataCallback));
|
||||
}
|
||||
else {
|
||||
tables.add(viewer.loadGeneric(pathSolver.solve("UI\\SoundInfo\\AnimSounds.slk", solverParams).finalSrc,
|
||||
FetchDataTypeName.SLK, mappedDataCallback));
|
||||
}
|
||||
tables.add(viewer.loadGeneric(pathSolver.solve("UI\\SoundInfo\\AnimSounds.slk", solverParams).finalSrc,
|
||||
FetchDataTypeName.SLK, mappedDataCallback));
|
||||
}
|
||||
else {
|
||||
// Units\Critters\BlackStagMale\BlackStagMale.mdx has an event object named
|
||||
@ -175,7 +179,7 @@ public class EventObjectEmitterObject extends GenericObject implements EmitterOb
|
||||
|
||||
// TODO I am scrapping some async stuff with promises here from the JS and
|
||||
// calling load
|
||||
this.load(tables);
|
||||
load(tables);
|
||||
}
|
||||
|
||||
private float getFloat(final MappedDataRow row, final String name) {
|
||||
@ -272,9 +276,15 @@ public class EventObjectEmitterObject extends GenericObject implements EmitterOb
|
||||
// This is mostly to save on bandwidth and loading time, especially when loading
|
||||
// full maps.
|
||||
if (viewer.audioEnabled) {
|
||||
final MappedData animSounds = (MappedData) tables.get(1).data;
|
||||
|
||||
final MappedDataRow animSoundsRow = animSounds.getRow((String) row.get("SoundLabel"));
|
||||
final MappedDataRow animSoundsRow;
|
||||
if (model.reforged) {
|
||||
animSoundsRow = row;
|
||||
}
|
||||
else {
|
||||
final MappedData animSounds = (MappedData) tables.get(1).data;
|
||||
animSoundsRow = animSounds.getRow((String) row.get("SoundLabel"));
|
||||
}
|
||||
|
||||
if (animSoundsRow != null) {
|
||||
this.distanceCutoff = getFloat(animSoundsRow, "DistanceCutoff");
|
||||
@ -287,7 +297,14 @@ public class EventObjectEmitterObject extends GenericObject implements EmitterOb
|
||||
final String[] fileNames = ((String) animSoundsRow.get("FileNames")).split(",");
|
||||
final GenericResource[] resources = new GenericResource[fileNames.length];
|
||||
for (int i = 0; i < fileNames.length; i++) {
|
||||
final String path = ((String) animSoundsRow.get("DirectoryBase")) + fileNames[i];
|
||||
final String directoryBase = (String) animSoundsRow.get("DirectoryBase");
|
||||
String path;
|
||||
if (directoryBase != null) {
|
||||
path = (directoryBase) + fileNames[i];
|
||||
}
|
||||
else {
|
||||
path = fileNames[i];
|
||||
}
|
||||
try {
|
||||
final String pathString = pathSolver.solve(path, model.solverParams).finalSrc;
|
||||
final GenericResource genericResource = viewer.loadGeneric(pathString,
|
||||
@ -325,12 +342,12 @@ public class EventObjectEmitterObject extends GenericObject implements EmitterOb
|
||||
public int getValue(final long[] out, final MdxComplexInstance instance) {
|
||||
if (this.globalSequence != -1) {
|
||||
|
||||
return this.getValueAtTime(out, instance.counter % this.globalSequence, 0, this.globalSequence);
|
||||
return getValueAtTime(out, instance.counter % this.globalSequence, 0, this.globalSequence);
|
||||
}
|
||||
else if (instance.sequence != -1) {
|
||||
final long[] interval = this.model.getSequences().get(instance.sequence).getInterval();
|
||||
|
||||
return this.getValueAtTime(out, instance.frame, interval[0], interval[1]);
|
||||
return getValueAtTime(out, instance.frame, interval[0], interval[1]);
|
||||
}
|
||||
else {
|
||||
out[0] = this.defval[0];
|
||||
|
@ -220,7 +220,7 @@ public class CommandCardPopulatingAbilityVisitor implements CAbilityVisitor<Void
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
else if (this.menuBaseOrderId == 0) {
|
||||
if (this.multiSelect) {
|
||||
return;
|
||||
}
|
||||
|
@ -10,6 +10,7 @@ import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import com.badlogic.gdx.Gdx;
|
||||
import com.badlogic.gdx.Input;
|
||||
import com.badlogic.gdx.audio.Music;
|
||||
import com.badlogic.gdx.graphics.Color;
|
||||
import com.badlogic.gdx.graphics.g2d.BitmapFont;
|
||||
@ -29,6 +30,7 @@ import com.etheller.warsmash.networking.WarsmashClient;
|
||||
import com.etheller.warsmash.networking.WarsmashClientSendingOrderListener;
|
||||
import com.etheller.warsmash.networking.WarsmashClientWriter;
|
||||
import com.etheller.warsmash.parsers.fdf.GameUI;
|
||||
import com.etheller.warsmash.parsers.fdf.datamodel.AnchorDefinition;
|
||||
import com.etheller.warsmash.parsers.fdf.datamodel.FramePoint;
|
||||
import com.etheller.warsmash.parsers.fdf.datamodel.TextJustify;
|
||||
import com.etheller.warsmash.parsers.fdf.frames.EditBoxFrame;
|
||||
@ -68,6 +70,7 @@ import com.etheller.warsmash.viewer5.handlers.w3x.simulation.players.CRace;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.trigger.enumtypes.CPlayerSlotState;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.ui.command.ClickableFrame;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.ui.command.FocusableFrame;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.ui.dialog.DialogWar3;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.ui.mapsetup.MapInfoPane;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.ui.mapsetup.TeamSetupPane;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.ui.menu.BattleNetUI;
|
||||
@ -77,6 +80,13 @@ import com.etheller.warsmash.viewer5.handlers.w3x.ui.menu.CampaignMenuUI;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.ui.menu.CampaignMission;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.ui.sound.KeyedSounds;
|
||||
|
||||
import net.warsmash.uberserver.AccountCreationFailureReason;
|
||||
import net.warsmash.uberserver.GamingNetwork;
|
||||
import net.warsmash.uberserver.GamingNetworkConnection;
|
||||
import net.warsmash.uberserver.GamingNetworkServerToClientListener;
|
||||
import net.warsmash.uberserver.HandshakeDeniedReason;
|
||||
import net.warsmash.uberserver.LoginFailureReason;
|
||||
|
||||
public class MenuUI {
|
||||
private static final Vector2 screenCoordsVector = new Vector2();
|
||||
private static boolean ENABLE_NOT_YET_IMPLEMENTED_BUTTONS = false;
|
||||
@ -195,10 +205,16 @@ public class MenuUI {
|
||||
private Music[] currentMusics;
|
||||
private int currentMusicIndex;
|
||||
private boolean currentMusicRandomizeIndex;
|
||||
private final GamingNetworkConnection gamingNetworkConnection;
|
||||
private UIFrame battleNetConnectDialog;
|
||||
private StringFrame battleNetConnectInfoText;
|
||||
private GlueTextButtonFrame battleNetConnectCancelButton;
|
||||
private DialogWar3 dialog;
|
||||
|
||||
public MenuUI(final DataSource dataSource, final Viewport uiViewport, final Scene uiScene, final MdxViewer viewer,
|
||||
final WarsmashGdxMultiScreenGame screenManager, final SingleModelScreen menuScreen,
|
||||
final DataTable warsmashIni, final RootFrameListener rootFrameListener) {
|
||||
final DataTable warsmashIni, final RootFrameListener rootFrameListener,
|
||||
final GamingNetworkConnection gamingNetworkConnection) {
|
||||
this.dataSource = dataSource;
|
||||
this.uiViewport = uiViewport;
|
||||
this.uiScene = uiScene;
|
||||
@ -207,6 +223,7 @@ public class MenuUI {
|
||||
this.menuScreen = menuScreen;
|
||||
this.warsmashIni = warsmashIni;
|
||||
this.rootFrameListener = rootFrameListener;
|
||||
this.gamingNetworkConnection = gamingNetworkConnection;
|
||||
|
||||
this.widthRatioCorrection = getMinWorldWidth() / 1600f;
|
||||
this.heightRatioCorrection = getMinWorldHeight() / 1200f;
|
||||
@ -223,6 +240,131 @@ public class MenuUI {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
gamingNetworkConnection.addListener(new GamingNetworkServerToClientListener() {
|
||||
|
||||
@Override
|
||||
public void disconnected() {
|
||||
Gdx.app.postRunnable(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
System.err.println("Disconnected from server...");
|
||||
MenuUI.this.battleNetConnectDialog.setVisible(false);
|
||||
setMainMenuButtonsEnabled(true);
|
||||
MenuUI.this.dialog.showError("ERROR_ID_DISCONNECT", null);
|
||||
// MenuUI.this.battleNetUI.hide();
|
||||
// playCurrentBattleNetGlueSpriteDeath();
|
||||
// MenuUI.this.glueSpriteLayerCenter.setSequence("Death");
|
||||
// MenuUI.this.menuState = MenuState.LEAVING_BATTLE_NET_FROM_LOGGED_IN;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loginOk(final long sessionToken, final String welcomeMessage) {
|
||||
Gdx.app.postRunnable(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
MenuUI.this.battleNetUI.loginAccepted(sessionToken, welcomeMessage);
|
||||
MenuUI.this.battleNetUI.getDoors().setSequence(PrimaryTag.DEATH);
|
||||
MenuUI.this.menuState = MenuState.GOING_TO_BATTLE_NET_WELCOME;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loginFailed(final LoginFailureReason loginFailureReason) {
|
||||
String msg;
|
||||
switch (loginFailureReason) {
|
||||
case INVALID_CREDENTIALS:
|
||||
msg = "ERROR_ID_BADPASSWORD";
|
||||
break;
|
||||
case UNKNOWN_USER:
|
||||
msg = "ERROR_ID_UNKNOWNACCOUNT";
|
||||
break;
|
||||
default:
|
||||
msg = "ERROR_ID_INVALIDPARAMS";
|
||||
break;
|
||||
}
|
||||
MenuUI.this.dialog.showError(msg, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void joinedChannel(final String channelName) {
|
||||
MenuUI.this.battleNetUI.joinedChannel(channelName);
|
||||
MenuUI.this.battleNetUI.hideWelcomeScreen();
|
||||
MenuUI.this.glueSpriteLayerTopLeft.setSequence("BattleNetWelcome Death");
|
||||
MenuUI.this.glueSpriteLayerTopRight.setSequence("BattleNetWelcome Death");
|
||||
MenuUI.this.menuState = MenuState.GOING_TO_BATTLE_NET_CHAT_CHANNEL;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handshakeDenied(final HandshakeDeniedReason reason) {
|
||||
Gdx.app.postRunnable(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
MenuUI.this.battleNetConnectDialog.setVisible(true);
|
||||
MenuUI.this.rootFrame.setDecoratedText(MenuUI.this.battleNetConnectInfoText,
|
||||
"NETERROR_DEFAULTERROR");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handshakeAccepted() {
|
||||
Gdx.app.postRunnable(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
MenuUI.this.battleNetConnectDialog.setVisible(false);
|
||||
MenuUI.this.glueSpriteLayerTopLeft.setSequence("MainMenu Death");
|
||||
MenuUI.this.glueSpriteLayerTopRight.setSequence("MainMenu Death");
|
||||
setMainMenuButtonsEnabled(true);
|
||||
setMainMenuVisible(false);
|
||||
MenuUI.this.menuState = MenuState.GOING_TO_BATTLE_NET_LOGIN;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void channelMessage(final String userName, final String message) {
|
||||
MenuUI.this.battleNetUI.channelMessage(userName, message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void channelEmote(final String userName, final String message) {
|
||||
MenuUI.this.battleNetUI.channelEmote(userName, message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void badSession() {
|
||||
MenuUI.this.dialog.showError("ERROR_ID_NOTLOGGEDON", null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accountCreationOk() {
|
||||
Gdx.app.postRunnable(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
MenuUI.this.battleNetUI.accountCreatedOk();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accountCreationFailed(final AccountCreationFailureReason reason) {
|
||||
Gdx.app.postRunnable(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
switch (reason) {
|
||||
default:
|
||||
case USERNAME_ALREADY_EXISTS:
|
||||
MenuUI.this.dialog.showError("ERROR_ID_NAMEUSED", null);
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public float getHeightRatioCorrection() {
|
||||
@ -315,6 +457,20 @@ public class MenuUI {
|
||||
Gdx.input.setCursorCatched(true);
|
||||
}
|
||||
|
||||
this.battleNetConnectDialog = this.rootFrame.createFrame("BattleNetConnectDialog", this.rootFrame, 0, 0);
|
||||
this.battleNetConnectDialog.setVisible(false);
|
||||
this.battleNetConnectDialog.addAnchor(new AnchorDefinition(FramePoint.CENTER, 0, 0));
|
||||
this.battleNetConnectInfoText = (StringFrame) this.rootFrame.getFrameByName("ConnectInfoText", 0);
|
||||
this.battleNetConnectCancelButton = (GlueTextButtonFrame) this.rootFrame.getFrameByName("ConnectButton", 0);
|
||||
this.battleNetConnectCancelButton.setOnClick(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
MenuUI.this.gamingNetworkConnection.userRequestDisconnect();
|
||||
MenuUI.this.battleNetConnectDialog.setVisible(false);
|
||||
setMainMenuButtonsEnabled(true);
|
||||
}
|
||||
});
|
||||
|
||||
// Main Menu interactivity
|
||||
this.singlePlayerButton = (GlueTextButtonFrame) this.rootFrame.getFrameByName("SinglePlayerButton", 0);
|
||||
this.battleNetButton = (GlueTextButtonFrame) this.rootFrame.getFrameByName("BattleNetButton", 0);
|
||||
@ -365,16 +521,30 @@ public class MenuUI {
|
||||
this.battleNetButton.setOnClick(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
MenuUI.this.glueSpriteLayerTopLeft.setSequence("MainMenu Death");
|
||||
MenuUI.this.glueSpriteLayerTopRight.setSequence("MainMenu Death");
|
||||
setMainMenuVisible(false);
|
||||
MenuUI.this.menuState = MenuState.GOING_TO_BATTLE_NET_LOGIN;
|
||||
setMainMenuButtonsEnabled(false);
|
||||
MenuUI.this.rootFrame.setDecoratedText(MenuUI.this.battleNetConnectInfoText, "BNET_CONNECT_INIT");
|
||||
MenuUI.this.battleNetConnectDialog.positionBounds(MenuUI.this.rootFrame, MenuUI.this.uiViewport);
|
||||
MenuUI.this.battleNetConnectDialog.setVisible(true);
|
||||
if (MenuUI.this.gamingNetworkConnection.userRequestConnect()) {
|
||||
MenuUI.this.gamingNetworkConnection.handshake(WarsmashConstants.getGameId(),
|
||||
GamingNetwork.GAME_VERSION_DATA);
|
||||
}
|
||||
else {
|
||||
MenuUI.this.battleNetConnectDialog.setVisible(false);
|
||||
setMainMenuButtonsEnabled(true);
|
||||
MenuUI.this.dialog.showError("ERROR_ID_CANTCONNECT", new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
this.realmButton.setOnClick(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
|
||||
MenuUI.this.battleNetConnectDialog.setVisible(true);
|
||||
}
|
||||
});
|
||||
|
||||
@ -794,6 +964,7 @@ public class MenuUI {
|
||||
MenuUI.this.battleNetUI.getDoors().setSequence(PrimaryTag.DEATH);
|
||||
MenuUI.this.menuScreen.unAlternateModelBackToNormal();
|
||||
MenuUI.this.menuState = MenuState.LEAVING_BATTLE_NET;
|
||||
MenuUI.this.gamingNetworkConnection.userRequestDisconnect();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -803,10 +974,23 @@ public class MenuUI {
|
||||
|
||||
@Override
|
||||
public void logon(final String accountName, final String password) {
|
||||
// TODO: connection
|
||||
MenuUI.this.battleNetUI.loginAccepted();
|
||||
MenuUI.this.battleNetUI.getDoors().setSequence(PrimaryTag.DEATH);
|
||||
MenuUI.this.menuState = MenuState.GOING_TO_BATTLE_NET_WELCOME;
|
||||
if (accountName.isEmpty()) {
|
||||
MenuUI.this.dialog.showError("ERROR_ID_NAMEBLANK", null);
|
||||
}
|
||||
else if (password.isEmpty()) {
|
||||
MenuUI.this.dialog.showError("NETERROR_NOPASSWORD", null);
|
||||
}
|
||||
else {
|
||||
final char[] passwordData = getPasswordData(password);
|
||||
MenuUI.this.gamingNetworkConnection.login(accountName, passwordData);
|
||||
}
|
||||
}
|
||||
|
||||
private char[] getPasswordData(final String password) {
|
||||
final int nPasswordChars = password.length();
|
||||
final char[] passwordData = new char[nPasswordChars];
|
||||
password.getChars(0, nPasswordChars, passwordData, 0);
|
||||
return passwordData;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -815,22 +999,7 @@ public class MenuUI {
|
||||
playCurrentBattleNetGlueSpriteDeath();
|
||||
MenuUI.this.glueSpriteLayerCenter.setSequence("Death");
|
||||
MenuUI.this.menuState = MenuState.LEAVING_BATTLE_NET_FROM_LOGGED_IN;
|
||||
}
|
||||
|
||||
public void playCurrentBattleNetGlueSpriteDeath() {
|
||||
switch (MenuUI.this.menuState) {
|
||||
case BATTLE_NET_CHAT_CHANNEL:
|
||||
case GOING_TO_BATTLE_NET_CHAT_CHANNEL:
|
||||
MenuUI.this.glueSpriteLayerTopLeft.setSequence("BattleNetChatRoom Death");
|
||||
MenuUI.this.glueSpriteLayerTopRight.setSequence("BattleNetChatRoom Death");
|
||||
break;
|
||||
default:
|
||||
case BATTLE_NET_WELCOME:
|
||||
case GOING_TO_BATTLE_NET_WELCOME:
|
||||
MenuUI.this.glueSpriteLayerTopLeft.setSequence("BattleNetWelcome Death");
|
||||
MenuUI.this.glueSpriteLayerTopRight.setSequence("BattleNetWelcome Death");
|
||||
break;
|
||||
}
|
||||
MenuUI.this.gamingNetworkConnection.userRequestDisconnect();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -843,13 +1012,49 @@ public class MenuUI {
|
||||
|
||||
@Override
|
||||
public void enterDefaultChat() {
|
||||
MenuUI.this.battleNetUI.hideWelcomeScreen();
|
||||
MenuUI.this.glueSpriteLayerTopLeft.setSequence("BattleNetWelcome Death");
|
||||
MenuUI.this.glueSpriteLayerTopRight.setSequence("BattleNetWelcome Death");
|
||||
MenuUI.this.menuState = MenuState.GOING_TO_BATTLE_NET_CHAT_CHANNEL;
|
||||
MenuUI.this.gamingNetworkConnection.joinChannel(MenuUI.this.battleNetUI.getGamingNetworkSessionToken(),
|
||||
"Frozen Throne USA-1"); // TODO maybe not hardcode this
|
||||
}
|
||||
|
||||
@Override
|
||||
public void createAccount(final String username, final String password, final String repeatPassword) {
|
||||
if (!password.equals(repeatPassword)) {
|
||||
MenuUI.this.dialog.showError("NETERROR_PASSWORDMISMATCH", null);
|
||||
}
|
||||
else if (username.isEmpty()) {
|
||||
MenuUI.this.dialog.showError("ERROR_ID_NAMEBLANK", null);
|
||||
}
|
||||
else if (password.isEmpty()) {
|
||||
MenuUI.this.dialog.showError("NETERROR_NOPASSWORD", null);
|
||||
}
|
||||
else if (username.length() < 3) {
|
||||
// TODO checks like this should be server side!!!
|
||||
MenuUI.this.dialog.showError("NETERROR_USERNAMETOOSHORT", null);
|
||||
}
|
||||
else if (password.length() < 3) {
|
||||
MenuUI.this.dialog.showError("NETERROR_PASSWORDTOOSHORT", null);
|
||||
}
|
||||
else {
|
||||
final char[] passwordData = getPasswordData(password);
|
||||
MenuUI.this.gamingNetworkConnection.createAccount(username, passwordData);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void submitChatText(final String text) {
|
||||
if (text.startsWith("/me ")) {
|
||||
MenuUI.this.gamingNetworkConnection
|
||||
.emoteMessage(MenuUI.this.battleNetUI.getGamingNetworkSessionToken(), text.substring(4));
|
||||
}
|
||||
else {
|
||||
MenuUI.this.gamingNetworkConnection
|
||||
.chatMessage(MenuUI.this.battleNetUI.getGamingNetworkSessionToken(), text);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
this.dialog = new DialogWar3(this.rootFrame, this.uiViewport);
|
||||
|
||||
// position all
|
||||
this.rootFrame.positionBounds(this.rootFrame, this.uiViewport);
|
||||
|
||||
@ -969,6 +1174,19 @@ public class MenuUI {
|
||||
this.singlePlayerCancelButton.setEnabled(b);
|
||||
}
|
||||
|
||||
private void setMainMenuButtonsEnabled(final boolean b) {
|
||||
this.singlePlayerButton.setEnabled(b);
|
||||
this.battleNetButton.setEnabled(b);
|
||||
this.realmButton.setEnabled(b);
|
||||
this.localAreaNetworkButton.setEnabled(b && ENABLE_NOT_YET_IMPLEMENTED_BUTTONS);
|
||||
this.optionsButton.setEnabled(b && ENABLE_NOT_YET_IMPLEMENTED_BUTTONS);
|
||||
this.creditsButton.setEnabled(b && ENABLE_NOT_YET_IMPLEMENTED_BUTTONS);
|
||||
this.exitButton.setEnabled(b);
|
||||
if (this.editionButton != null) {
|
||||
this.editionButton.setEnabled(b);
|
||||
}
|
||||
}
|
||||
|
||||
private void setMainMenuVisible(final boolean visible) {
|
||||
this.mainMenuFrame.setVisible(visible);
|
||||
this.warcraftIIILogo.setVisible(visible);
|
||||
@ -1131,7 +1349,7 @@ public class MenuUI {
|
||||
break;
|
||||
case GOING_TO_BATTLE_NET_LOGIN_PART2:
|
||||
MenuUI.this.menuScreen.alternateModelToBattlenet();
|
||||
this.battleNetUI.showLoginPrompt("<NYI>");
|
||||
this.battleNetUI.showLoginPrompt(this.gamingNetworkConnection.getGatewayString());
|
||||
this.menuState = MenuState.BATTLE_NET_LOGIN;
|
||||
break;
|
||||
case LEAVING_BATTLE_NET_FROM_LOGGED_IN:
|
||||
@ -1402,35 +1620,13 @@ public class MenuUI {
|
||||
}
|
||||
|
||||
private static enum MenuState {
|
||||
GOING_TO_MAIN_MENU,
|
||||
MAIN_MENU,
|
||||
GOING_TO_BATTLE_NET_LOGIN,
|
||||
GOING_TO_BATTLE_NET_LOGIN_PART2,
|
||||
BATTLE_NET_LOGIN,
|
||||
LEAVING_BATTLE_NET,
|
||||
LEAVING_BATTLE_NET_FROM_LOGGED_IN,
|
||||
GOING_TO_BATTLE_NET_CUSTOM_GAME_MENU,
|
||||
BATTLE_NET_CUSTOM_GAME_MENU,
|
||||
GOING_TO_BATTLE_NET_WELCOME,
|
||||
BATTLE_NET_WELCOME,
|
||||
GOING_TO_SINGLE_PLAYER,
|
||||
LEAVING_CAMPAIGN,
|
||||
SINGLE_PLAYER,
|
||||
GOING_TO_SINGLE_PLAYER_SKIRMISH,
|
||||
SINGLE_PLAYER_SKIRMISH,
|
||||
GOING_TO_MAP,
|
||||
GOING_TO_CAMPAIGN,
|
||||
GOING_TO_CAMPAIGN_PART2,
|
||||
GOING_TO_MISSION_SELECT,
|
||||
MISSION_SELECT,
|
||||
CAMPAIGN,
|
||||
GOING_TO_SINGLE_PLAYER_PROFILE,
|
||||
SINGLE_PLAYER_PROFILE,
|
||||
GOING_TO_LOADING_SCREEN,
|
||||
QUITTING,
|
||||
RESTARTING,
|
||||
GOING_TO_BATTLE_NET_CHAT_CHANNEL,
|
||||
BATTLE_NET_CHAT_CHANNEL;
|
||||
GOING_TO_MAIN_MENU, MAIN_MENU, GOING_TO_BATTLE_NET_LOGIN, GOING_TO_BATTLE_NET_LOGIN_PART2, BATTLE_NET_LOGIN,
|
||||
LEAVING_BATTLE_NET, LEAVING_BATTLE_NET_FROM_LOGGED_IN, GOING_TO_BATTLE_NET_CUSTOM_GAME_MENU,
|
||||
BATTLE_NET_CUSTOM_GAME_MENU, GOING_TO_BATTLE_NET_WELCOME, BATTLE_NET_WELCOME, GOING_TO_SINGLE_PLAYER,
|
||||
LEAVING_CAMPAIGN, SINGLE_PLAYER, GOING_TO_SINGLE_PLAYER_SKIRMISH, SINGLE_PLAYER_SKIRMISH, GOING_TO_MAP,
|
||||
GOING_TO_CAMPAIGN, GOING_TO_CAMPAIGN_PART2, GOING_TO_MISSION_SELECT, MISSION_SELECT, CAMPAIGN,
|
||||
GOING_TO_SINGLE_PLAYER_PROFILE, SINGLE_PLAYER_PROFILE, GOING_TO_LOADING_SCREEN, QUITTING, RESTARTING,
|
||||
GOING_TO_BATTLE_NET_CHAT_CHANNEL, BATTLE_NET_CHAT_CHANNEL;
|
||||
}
|
||||
|
||||
public void hide() {
|
||||
@ -1452,8 +1648,22 @@ public class MenuUI {
|
||||
}
|
||||
|
||||
public boolean keyUp(final int keycode) {
|
||||
if (this.focusUIFrame != null) {
|
||||
this.focusUIFrame.keyUp(keycode);
|
||||
if (keycode == Input.Keys.TAB) {
|
||||
// accessibility tab focus ui
|
||||
final List<FocusableFrame> focusableFrames = this.rootFrame.getFocusableFrames();
|
||||
final int indexOf = focusableFrames.indexOf(this.focusUIFrame) + 1;
|
||||
for (int i = indexOf; i < focusableFrames.size(); i++) {
|
||||
final FocusableFrame focusableFrame = focusableFrames.get(i);
|
||||
if (focusableFrame.isVisibleOnScreen() && focusableFrame.isFocusable()) {
|
||||
setFocusFrame(focusableFrame);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (this.focusUIFrame != null) {
|
||||
this.focusUIFrame.keyUp(keycode);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@ -1581,4 +1791,20 @@ public class MenuUI {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public void playCurrentBattleNetGlueSpriteDeath() {
|
||||
switch (MenuUI.this.menuState) {
|
||||
case BATTLE_NET_CHAT_CHANNEL:
|
||||
case GOING_TO_BATTLE_NET_CHAT_CHANNEL:
|
||||
MenuUI.this.glueSpriteLayerTopLeft.setSequence("BattleNetChatRoom Death");
|
||||
MenuUI.this.glueSpriteLayerTopRight.setSequence("BattleNetChatRoom Death");
|
||||
break;
|
||||
default:
|
||||
case BATTLE_NET_WELCOME:
|
||||
case GOING_TO_BATTLE_NET_WELCOME:
|
||||
MenuUI.this.glueSpriteLayerTopLeft.setSequence("BattleNetWelcome Death");
|
||||
MenuUI.this.glueSpriteLayerTopRight.setSequence("BattleNetWelcome Death");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,127 @@
|
||||
package com.etheller.warsmash.viewer5.handlers.w3x.ui.dialog;
|
||||
|
||||
import com.badlogic.gdx.utils.viewport.Viewport;
|
||||
import com.etheller.warsmash.parsers.fdf.GameUI;
|
||||
import com.etheller.warsmash.parsers.fdf.datamodel.AnchorDefinition;
|
||||
import com.etheller.warsmash.parsers.fdf.datamodel.FramePoint;
|
||||
import com.etheller.warsmash.parsers.fdf.frames.BackdropFrame;
|
||||
import com.etheller.warsmash.parsers.fdf.frames.ClickConsumingTextureFrame;
|
||||
import com.etheller.warsmash.parsers.fdf.frames.GlueTextButtonFrame;
|
||||
import com.etheller.warsmash.parsers.fdf.frames.SimpleFrame;
|
||||
import com.etheller.warsmash.parsers.fdf.frames.StringFrame;
|
||||
import com.etheller.warsmash.parsers.fdf.frames.TextureFrame;
|
||||
import com.etheller.warsmash.parsers.fdf.frames.UIFrame;
|
||||
|
||||
public class DialogWar3 {
|
||||
|
||||
private final GameUI rootFrame;
|
||||
private final Viewport uiViewport;
|
||||
private final UIFrame dialogWar3;
|
||||
private final StringFrame dialogWar3Text;
|
||||
private final GlueTextButtonFrame dialogWar3ButtonOk;
|
||||
private final GlueTextButtonFrame dialogWar3ButtonNo;
|
||||
private final GlueTextButtonFrame dialogWar3ButtonYes;
|
||||
private final UIFrame dialogWar3ButtonOkBackdrop;
|
||||
private final UIFrame dialogWar3ButtonNoBackdrop;
|
||||
private final UIFrame dialogWar3ButtonYesBackdrop;
|
||||
private final float defaultHeight;
|
||||
private final BackdropFrame dialogWar3Icon;
|
||||
|
||||
public DialogWar3(final GameUI rootFrame, final Viewport uiViewport) {
|
||||
this.rootFrame = rootFrame;
|
||||
this.uiViewport = uiViewport;
|
||||
this.dialogWar3 = rootFrame.createFrame("DialogWar3", rootFrame, 0, 0);
|
||||
this.dialogWar3.addAnchor(new AnchorDefinition(FramePoint.CENTER, 0, 0));
|
||||
this.dialogWar3Text = (StringFrame) rootFrame.getFrameByName("DialogText", 0);
|
||||
this.dialogWar3ButtonOk = (GlueTextButtonFrame) rootFrame.getFrameByName("DialogButtonOK", 0);
|
||||
this.dialogWar3ButtonNo = (GlueTextButtonFrame) rootFrame.getFrameByName("DialogButtonNo", 0);
|
||||
this.dialogWar3ButtonYes = (GlueTextButtonFrame) rootFrame.getFrameByName("DialogButtonYes", 0);
|
||||
this.dialogWar3Icon = (BackdropFrame) rootFrame.getFrameByName("DialogIcon", 0);
|
||||
this.dialogWar3ButtonOkBackdrop = rootFrame.getFrameByName("DialogButtonOKBackdrop", 0);
|
||||
this.dialogWar3ButtonNoBackdrop = rootFrame.getFrameByName("DialogButtonNoBackdrop", 0);
|
||||
this.dialogWar3ButtonYesBackdrop = rootFrame.getFrameByName("DialogButtonYesBackdrop", 0);
|
||||
this.defaultHeight = this.dialogWar3.getAssignedHeight();
|
||||
this.dialogWar3.setVisible(false);
|
||||
|
||||
final TextureFrame modalDialogBlacknessScreenCover = new ClickConsumingTextureFrame(null, this.rootFrame, false,
|
||||
null);
|
||||
modalDialogBlacknessScreenCover.setTexture("Textures\\Black32.blp", rootFrame);
|
||||
modalDialogBlacknessScreenCover.setColor(1.0f, 1.0f, 1.0f, 0.5f);
|
||||
modalDialogBlacknessScreenCover.setSetAllPoints(true);
|
||||
((SimpleFrame) this.dialogWar3).add(0, modalDialogBlacknessScreenCover);
|
||||
}
|
||||
|
||||
public void showMessage(final String message, final Runnable runnable) {
|
||||
showMessage(DialogIcon.MESSAGE, message, runnable);
|
||||
}
|
||||
|
||||
public void showError(final String message, final Runnable runnable) {
|
||||
showMessage(DialogIcon.ERROR, message, runnable);
|
||||
}
|
||||
|
||||
public void showMessage(final DialogIcon icon, final String message, final Runnable runnable) {
|
||||
this.rootFrame.setDecoratedText(this.dialogWar3Text, message);
|
||||
this.dialogWar3ButtonOkBackdrop.setVisible(true);
|
||||
this.dialogWar3ButtonNoBackdrop.setVisible(false);
|
||||
this.dialogWar3ButtonYesBackdrop.setVisible(false);
|
||||
this.dialogWar3ButtonOk.setOnClick(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (runnable != null) {
|
||||
runnable.run();
|
||||
}
|
||||
DialogWar3.this.dialogWar3.setVisible(false);
|
||||
}
|
||||
});
|
||||
this.dialogWar3.setHeight(this.dialogWar3Text.getPredictedViewportHeight() + (this.defaultHeight * .75f));
|
||||
this.dialogWar3.positionBounds(this.rootFrame, this.uiViewport);
|
||||
this.dialogWar3.setVisible(true);
|
||||
this.dialogWar3Icon.setBackground(this.rootFrame.loadTexture(icon.getPath()));
|
||||
}
|
||||
|
||||
public void show(final String message, final DialogWar3Listener listener) {
|
||||
this.rootFrame.setDecoratedText(this.dialogWar3Text, message);
|
||||
this.dialogWar3ButtonOkBackdrop.setVisible(false);
|
||||
this.dialogWar3ButtonNoBackdrop.setVisible(true);
|
||||
this.dialogWar3ButtonYesBackdrop.setVisible(true);
|
||||
this.dialogWar3ButtonYes.setOnClick(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
listener.yes();
|
||||
DialogWar3.this.dialogWar3.setVisible(false);
|
||||
}
|
||||
});
|
||||
this.dialogWar3ButtonNo.setOnClick(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
listener.no();
|
||||
DialogWar3.this.dialogWar3.setVisible(false);
|
||||
}
|
||||
});
|
||||
this.dialogWar3Icon.setBackground(this.rootFrame.loadTexture(DialogIcon.QUESTION.getPath()));
|
||||
this.dialogWar3.setHeight(this.dialogWar3Text.getPredictedViewportHeight() + (this.defaultHeight * .75f));
|
||||
this.dialogWar3.positionBounds(this.rootFrame, this.uiViewport);
|
||||
this.dialogWar3.setVisible(true);
|
||||
}
|
||||
|
||||
public static interface DialogWar3Listener {
|
||||
void yes();
|
||||
|
||||
void no();
|
||||
}
|
||||
|
||||
public static enum DialogIcon {
|
||||
ERROR("UI\\Widgets\\Glues\\dialogbox-error.blp"), MESSAGE("UI\\Widgets\\Glues\\dialogbox-message.blp"),
|
||||
QUESTION("UI\\Widgets\\Glues\\dialogbox-question.blp");
|
||||
|
||||
private String path;
|
||||
|
||||
private DialogIcon(final String path) {
|
||||
this.path = path;
|
||||
}
|
||||
|
||||
public String getPath() {
|
||||
return this.path;
|
||||
}
|
||||
}
|
||||
}
|
@ -13,6 +13,7 @@ import com.etheller.warsmash.parsers.fdf.frames.GlueButtonFrame;
|
||||
import com.etheller.warsmash.parsers.fdf.frames.SimpleFrame;
|
||||
import com.etheller.warsmash.parsers.fdf.frames.SpriteFrame;
|
||||
import com.etheller.warsmash.parsers.fdf.frames.StringFrame;
|
||||
import com.etheller.warsmash.parsers.fdf.frames.TextAreaFrame;
|
||||
import com.etheller.warsmash.parsers.fdf.frames.UIFrame;
|
||||
|
||||
public class BattleNetUI {
|
||||
@ -67,6 +68,14 @@ public class BattleNetUI {
|
||||
private final GlueButtonFrame welcomeEnterChatButton;
|
||||
private final SimpleFrame welcomeQuitBattleNetButtonContainer;
|
||||
private final SimpleFrame chatQuitBattleNetButtonContainer;
|
||||
private long gamingNetworkSessionToken;
|
||||
private String gamingNetworkMessageOfTheDay;
|
||||
private final EditBoxFrame naAccountName;
|
||||
private final EditBoxFrame naPassword;
|
||||
private final EditBoxFrame naRepeatPassword;
|
||||
private final GlueButtonFrame okButton;
|
||||
private final StringFrame chatChannelNameLabel;
|
||||
private final TextAreaFrame chatTextArea;
|
||||
|
||||
public BattleNetUI(final GameUI rootFrame, final Viewport uiViewport,
|
||||
final BattleNetUIActionListener actionListener) {
|
||||
@ -100,11 +109,17 @@ public class BattleNetUI {
|
||||
|
||||
this.battleNetNewAccountPanel = rootFrame.getFrameByName("NewAccountPanel", 0);
|
||||
this.battleNetNewAccountPanel.setVisible(false);
|
||||
|
||||
this.naAccountName = (EditBoxFrame) rootFrame.getFrameByName("NAAccountName", 0);
|
||||
this.naPassword = (EditBoxFrame) rootFrame.getFrameByName("NAPassword", 0);
|
||||
this.naRepeatPassword = (EditBoxFrame) rootFrame.getFrameByName("NARepeatPassword", 0);
|
||||
|
||||
this.battleNetCancelBackdrop = rootFrame.getFrameByName("CancelBackdrop", 0);
|
||||
this.battleNetCancelBackdrop.setVisible(false);
|
||||
this.cancelButton = (GlueButtonFrame) rootFrame.getFrameByName("CancelButton", 0);
|
||||
this.battleNetOKBackdrop = rootFrame.getFrameByName("OKBackdrop", 0);
|
||||
this.battleNetOKBackdrop.setVisible(false);
|
||||
this.okButton = (GlueButtonFrame) rootFrame.getFrameByName("OKButton", 0);
|
||||
|
||||
// *******************************************
|
||||
// *
|
||||
@ -116,7 +131,16 @@ public class BattleNetUI {
|
||||
this.battleNetLoginPanel.setVisible(false);
|
||||
|
||||
this.accountNameEditBox = (EditBoxFrame) rootFrame.getFrameByName("AccountName", 0);
|
||||
final Runnable logonRunnable = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
actionListener.logon(BattleNetUI.this.accountNameEditBox.getText(),
|
||||
BattleNetUI.this.passwordEditBox.getText());
|
||||
}
|
||||
};
|
||||
this.accountNameEditBox.setOnEnter(logonRunnable);
|
||||
this.passwordEditBox = (EditBoxFrame) rootFrame.getFrameByName("Password", 0);
|
||||
this.passwordEditBox.setOnEnter(logonRunnable);
|
||||
this.passwordRecoveryButton = (GlueButtonFrame) rootFrame.getFrameByName("PasswordRecoveryButton", 0);
|
||||
this.passwordRecoveryButton.setOnClick(new Runnable() {
|
||||
@Override
|
||||
@ -129,6 +153,27 @@ public class BattleNetUI {
|
||||
this.changeEmailButton.setEnabled(false);
|
||||
this.changePasswordButton = (GlueButtonFrame) rootFrame.getFrameByName("ChangePasswordButton", 0);
|
||||
this.newAccountButton = (GlueButtonFrame) rootFrame.getFrameByName("NewAccountButton", 0);
|
||||
this.newAccountButton.setOnClick(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
BattleNetUI.this.battleNetLoginPanel.setVisible(false);
|
||||
BattleNetUI.this.battleNetNewAccountPanel.setVisible(true);
|
||||
BattleNetUI.this.battleNetOKBackdrop.setVisible(true);
|
||||
BattleNetUI.this.okButton.setOnClick(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
actionListener.createAccount(BattleNetUI.this.naAccountName.getText(),
|
||||
BattleNetUI.this.naPassword.getText(), BattleNetUI.this.naRepeatPassword.getText());
|
||||
}
|
||||
});
|
||||
BattleNetUI.this.cancelButton.setOnClick(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
leaveNewAccountPanel();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
this.tosButton = (GlueButtonFrame) rootFrame.getFrameByName("TOSButton", 0);
|
||||
this.tosButton.setOnClick(new Runnable() {
|
||||
@Override
|
||||
@ -159,13 +204,7 @@ public class BattleNetUI {
|
||||
};
|
||||
|
||||
this.logonButton = (GlueButtonFrame) rootFrame.getFrameByName("LogonButton", 0);
|
||||
this.logonButton.setOnClick(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
actionListener.logon(BattleNetUI.this.accountNameEditBox.getText(),
|
||||
BattleNetUI.this.passwordEditBox.getText());
|
||||
}
|
||||
});
|
||||
this.logonButton.setOnClick(logonRunnable);
|
||||
|
||||
this.battleNetChatPanel = rootFrame.createFrame("BattleNetChatPanel", rootFrame, 0, 0);
|
||||
this.battleNetChatPanel.setVisible(false);
|
||||
@ -205,6 +244,17 @@ public class BattleNetUI {
|
||||
this.battleNetChatTopButtons.add(this.profileButton);
|
||||
this.chatPanel = rootFrame.getFrameByName("ChatPanel", 0);
|
||||
this.chatPanel.setVisible(false);
|
||||
this.chatChannelNameLabel = (StringFrame) rootFrame.getFrameByName("ChatChannelNameLabel", 0);
|
||||
this.chatTextArea = (TextAreaFrame) rootFrame.getFrameByName("ChatTextArea", 0);
|
||||
final EditBoxFrame chatEditBox = (EditBoxFrame) rootFrame.getFrameByName("BattleNetChatEditBox", 0);
|
||||
chatEditBox.setFilterAllowAny();
|
||||
chatEditBox.setOnEnter(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
actionListener.submitChatText(chatEditBox.getText());
|
||||
chatEditBox.setText("", rootFrame, uiViewport);
|
||||
}
|
||||
});
|
||||
this.chatQuitBattleNetButtonContainer = (SimpleFrame) rootFrame
|
||||
.getFrameByName("ChatQuitBattleNetButtonContainer", 0);
|
||||
|
||||
@ -223,8 +273,6 @@ public class BattleNetUI {
|
||||
rootFrame.setText(this.welcomeNewItemCount, "(0)");
|
||||
this.welcomeNewsBoxContainer = (SimpleFrame) rootFrame.getFrameByName("NewsBoxContainer", 0);
|
||||
this.welcomeMOTDText = (StringFrame) rootFrame.getFrameByName("WelcomeMOTDText", 0);
|
||||
rootFrame.setText(this.welcomeMOTDText,
|
||||
"This MOTD is set from source code and is not an externalized string. |cffdd00ffWarsmash|r engine is producing this message locally.|n|n |cff00ff00TODO:|r Modify the |cffdd00ffWarsmash|r engine sourcecode to download a message from the server to put here that admins can customize!");
|
||||
this.welcomeUpcomingTournamentPanel = rootFrame.getFrameByName("UpcomingTournamentPanel", 0);
|
||||
this.welcomeUpcomingTournamentPanel.setVisible(false);
|
||||
this.welcomeEnterChatButton = (GlueButtonFrame) rootFrame.getFrameByName("EnterChatButton", 0);
|
||||
@ -247,6 +295,16 @@ public class BattleNetUI {
|
||||
actionListener.quitBattleNet();
|
||||
}
|
||||
});
|
||||
|
||||
// *******************************************
|
||||
// *
|
||||
// * New Account Panel NCS (Patch 1.31ish)
|
||||
// *
|
||||
// ******
|
||||
final UIFrame newAccountPanelNCS = rootFrame.getFrameByName("NewAccountPanelNCS", 0);
|
||||
if (newAccountPanelNCS != null) {
|
||||
newAccountPanelNCS.setVisible(false);
|
||||
}
|
||||
}
|
||||
|
||||
public void setTopButtonsVisible(final boolean flag) {
|
||||
@ -277,9 +335,11 @@ public class BattleNetUI {
|
||||
hideCurrentScreen();
|
||||
}
|
||||
|
||||
public void loginAccepted() {
|
||||
public void loginAccepted(final long sessionToken, final String welcomeMessage) {
|
||||
this.battleNetLoginPanel.setVisible(false);
|
||||
this.battleNetCancelBackdrop.setVisible(false);
|
||||
this.gamingNetworkSessionToken = sessionToken;
|
||||
this.rootFrame.setText(this.welcomeMOTDText, welcomeMessage);
|
||||
}
|
||||
|
||||
public void showWelcomeScreen() {
|
||||
@ -323,4 +383,36 @@ public class BattleNetUI {
|
||||
this.quitBattleNetButton.setSetAllPoints(true);
|
||||
this.quitBattleNetButton.positionBounds(this.rootFrame, this.uiViewport);
|
||||
}
|
||||
|
||||
public void accountCreatedOk() {
|
||||
leaveNewAccountPanel();
|
||||
}
|
||||
|
||||
private void leaveNewAccountPanel() {
|
||||
BattleNetUI.this.battleNetLoginPanel.setVisible(true);
|
||||
BattleNetUI.this.battleNetNewAccountPanel.setVisible(false);
|
||||
BattleNetUI.this.battleNetOKBackdrop.setVisible(false);
|
||||
BattleNetUI.this.cancelButton.setOnClick(BattleNetUI.this.exitLoginRunnable);
|
||||
}
|
||||
|
||||
public long getGamingNetworkSessionToken() {
|
||||
return this.gamingNetworkSessionToken;
|
||||
}
|
||||
|
||||
public void joinedChannel(final String channelName) {
|
||||
this.rootFrame.setText(this.chatChannelNameLabel, channelName);
|
||||
}
|
||||
|
||||
public void channelMessage(final String userName, final String message) {
|
||||
final String messageText = String.format(this.rootFrame.getTemplates().getDecoratedString("CHATEVENT_ID_TALK"),
|
||||
this.rootFrame.getTemplates().getDecoratedString("CHATCOLOR_TALK_USER"), userName,
|
||||
this.rootFrame.getTemplates().getDecoratedString("CHATCOLOR_TALK_MESSAGE"), message);
|
||||
this.chatTextArea.addItem(messageText, this.rootFrame, this.uiViewport);
|
||||
}
|
||||
|
||||
public void channelEmote(final String userName, final String message) {
|
||||
final String messageText = String.format(this.rootFrame.getTemplates().getDecoratedString("CHATEVENT_ID_EMOTE"),
|
||||
this.rootFrame.getTemplates().getDecoratedString("CHATCOLOR_EMOTE_MESSAGE"), userName, message);
|
||||
this.chatTextArea.addItem(messageText, this.rootFrame, this.uiViewport);
|
||||
}
|
||||
}
|
||||
|
@ -12,4 +12,8 @@ public interface BattleNetUIActionListener {
|
||||
void openCustomGameMenu();
|
||||
|
||||
void enterDefaultChat();
|
||||
|
||||
void createAccount(String username, String password, String repeatPassword);
|
||||
|
||||
void submitChatText(String text);
|
||||
}
|
||||
|
@ -39,7 +39,8 @@ public class GamingNetworkServerBusinessLogicImpl {
|
||||
final GamingNetworkServerToClientListener connectionContext) {
|
||||
if (this.acceptedGames.contains(new AcceptedGameListKey(gameId, version))) {
|
||||
connectionContext.handshakeAccepted();
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
connectionContext.handshakeDenied(HandshakeDeniedReason.BAD_GAME_VERSION);
|
||||
}
|
||||
}
|
||||
@ -49,7 +50,8 @@ public class GamingNetworkServerBusinessLogicImpl {
|
||||
final User user = this.userManager.createUser(username, passwordHash);
|
||||
if (user == null) {
|
||||
connectionContext.accountCreationFailed(AccountCreationFailureReason.USERNAME_ALREADY_EXISTS);
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
connectionContext.accountCreationOk();
|
||||
}
|
||||
}
|
||||
@ -68,10 +70,12 @@ public class GamingNetworkServerBusinessLogicImpl {
|
||||
this.tokenToSession.put(session.getToken(), session);
|
||||
this.userIdToCurrentSession.put(user.getId(), session);
|
||||
connectionContext.loginOk(session.getToken(), GamingNetworkServerBusinessLogicImpl.this.welcomeMessage);
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
connectionContext.loginFailed(LoginFailureReason.INVALID_CREDENTIALS);
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
connectionContext.loginFailed(LoginFailureReason.UNKNOWN_USER);
|
||||
}
|
||||
}
|
||||
@ -95,8 +99,10 @@ public class GamingNetworkServerBusinessLogicImpl {
|
||||
this.nameLowerCaseToChannel.put(channelKey, chatChannel);
|
||||
}
|
||||
chatChannel.addUser(session);
|
||||
session.currentChatChannel = channelKey;
|
||||
connectionContext.joinedChannel(channelName);
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
connectionContext.badSession();
|
||||
}
|
||||
}
|
||||
@ -122,7 +128,8 @@ public class GamingNetworkServerBusinessLogicImpl {
|
||||
if (chatChannel != null) {
|
||||
chatChannel.sendMessage(session.getUser().getUsername(), text);
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
connectionContext.badSession();
|
||||
}
|
||||
}
|
||||
@ -136,7 +143,8 @@ public class GamingNetworkServerBusinessLogicImpl {
|
||||
if (chatChannel != null) {
|
||||
chatChannel.sendEmote(session.getUser().getUsername(), text);
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
connectionContext.badSession();
|
||||
}
|
||||
}
|
||||
@ -148,7 +156,8 @@ public class GamingNetworkServerBusinessLogicImpl {
|
||||
if (session.getLastActiveTime() < (System.currentTimeMillis() - (60 * 60 * 1000))) {
|
||||
killSession(session);
|
||||
return null;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
session.notifyUsed(mostRecentConnectionContext);
|
||||
return session;
|
||||
}
|
||||
@ -222,7 +231,8 @@ public class GamingNetworkServerBusinessLogicImpl {
|
||||
for (final SessionImpl session : this.userSessions) {
|
||||
try {
|
||||
session.mostRecentConnectionContext.channelMessage(sourceUserName, message);
|
||||
} catch (final Exception exc) {
|
||||
}
|
||||
catch (final Exception exc) {
|
||||
exc.printStackTrace();
|
||||
}
|
||||
}
|
||||
@ -232,7 +242,8 @@ public class GamingNetworkServerBusinessLogicImpl {
|
||||
for (final SessionImpl session : this.userSessions) {
|
||||
try {
|
||||
session.mostRecentConnectionContext.channelEmote(sourceUserName, message);
|
||||
} catch (final Exception exc) {
|
||||
}
|
||||
catch (final Exception exc) {
|
||||
exc.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,28 @@
|
||||
package com.etheller.warsmash.networking.uberserver;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import com.etheller.warsmash.networking.uberserver.users.InRAMUserManager;
|
||||
|
||||
import net.warsmash.nio.channels.SelectableChannelOpener;
|
||||
import net.warsmash.uberserver.GamingNetwork;
|
||||
|
||||
public class GamingNetworkServerMain {
|
||||
public static void main(final String[] args) {
|
||||
final SelectableChannelOpener channelOpener = new SelectableChannelOpener();
|
||||
final Set<AcceptedGameListKey> acceptedGames = new HashSet<>();
|
||||
acceptedGames.add(new AcceptedGameListKey(GamingNetwork.GAME_ID_BASE, GamingNetwork.GAME_VERSION_DATA));
|
||||
acceptedGames.add(new AcceptedGameListKey(GamingNetwork.GAME_ID_XPAC, GamingNetwork.GAME_VERSION_DATA));
|
||||
final InRAMUserManager inRAMUserManager = new InRAMUserManager();
|
||||
final String welcomeMessage = "Thank you for connecting to the first draft of the Warsmash game server.";
|
||||
final TCPGamingNetworkServer tcpGamingNetworkServer = new TCPGamingNetworkServer(channelOpener,
|
||||
new DefaultGamingNetworkServerClientBuilder(
|
||||
new GamingNetworkServerBusinessLogicImpl(acceptedGames, inRAMUserManager, welcomeMessage)));
|
||||
tcpGamingNetworkServer.start();
|
||||
|
||||
while (true) {
|
||||
channelOpener.select(100);
|
||||
}
|
||||
}
|
||||
}
|
@ -114,4 +114,9 @@ public class GamingNetworkServerToClientWriter extends AbstractWriter implements
|
||||
this.writeBuffer.put(messageBytes);
|
||||
send();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void disconnected() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
}
|
||||
|
@ -30,7 +30,12 @@ public class TCPGamingNetworkServer {
|
||||
TCPGamingNetworkServer.this.gamingNetworkServerClientBuilder
|
||||
.createClient(writableOpenedChannel));
|
||||
}
|
||||
}, ExceptionListener.THROW_RUNTIME, 8 * 1024 * 1024, ByteOrder.BIG_ENDIAN);
|
||||
}, new ExceptionListener() {
|
||||
@Override
|
||||
public void caught(final Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}, 8 * 1024 * 1024, ByteOrder.LITTLE_ENDIAN);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -17,7 +17,7 @@ public class TCPGamingNetworkServerClientParser implements TCPClientParser {
|
||||
|
||||
@Override
|
||||
public void parse(final ByteBuffer data) {
|
||||
while (data.remaining() > 8) {
|
||||
while (data.remaining() >= 8) {
|
||||
final int protocolMessageId = data.getInt(data.position() + 0);
|
||||
final int length = data.getInt(data.position() + 4);
|
||||
if (data.remaining() >= length) {
|
||||
@ -61,6 +61,9 @@ public class TCPGamingNetworkServerClientParser implements TCPClientParser {
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -17,10 +17,13 @@ public class InRAMUserManager implements UserManager {
|
||||
private final transient XStream xstream = new XStream();
|
||||
|
||||
public InRAMUserManager() {
|
||||
this.xstream
|
||||
.allowTypesByWildcard(new String[] { "com.etheller.warsmash.networking.uberserver.users.UserImpl" });
|
||||
final File usersFile = new File("users.db");
|
||||
if (!usersFile.exists()) {
|
||||
this.users = new ArrayList<>();
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
this.users = (List<UserImpl>) this.xstream.fromXML(usersFile);
|
||||
for (final UserImpl user : this.users) {
|
||||
user.resumeTransientFields(this);
|
||||
@ -60,7 +63,8 @@ public class InRAMUserManager implements UserManager {
|
||||
synchronized (this.users) {
|
||||
try (PrintWriter writer = new PrintWriter("users.db")) {
|
||||
writer.print(usersXml);
|
||||
} catch (final FileNotFoundException e) {
|
||||
}
|
||||
catch (final FileNotFoundException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
@ -74,10 +78,12 @@ public class InRAMUserManager implements UserManager {
|
||||
if (PasswordAuthentication.authenticate(password, user.getPasswordHash())) {
|
||||
user.setPasswordHash(this.passwordAuthentication.hash(newPassword));
|
||||
authenticationListener.resetOk();
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
authenticationListener.resetFailed(PasswordResetFailureReason.INVALID_CREDENTIALS);
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
authenticationListener.resetFailed(PasswordResetFailureReason.UNKNOWN_USER);
|
||||
}
|
||||
}
|
||||
|
@ -87,12 +87,12 @@ public class SelectableChannelOpener implements ChannelOpener {
|
||||
channel.configureBlocking(false);
|
||||
final ByteBuffer readBuffer = ByteBuffer.allocate(bufferSize).order(byteOrder);
|
||||
final ByteBuffer writeBuffer = ByteBuffer.allocate(bufferSize).order(byteOrder);
|
||||
final TCPClientKeyAttachment keyAttachment = new TCPClientKeyAttachment(channel, exceptionListener,
|
||||
this.channelListener, readBuffer, writeBuffer);
|
||||
final TCPClientKeyAttachment keyAttachment = new TCPClientKeyAttachment(this.selector, channel,
|
||||
exceptionListener, this.channelListener, readBuffer, writeBuffer);
|
||||
keyAttachment.setParser(tcpClientParser);
|
||||
if (connected) {
|
||||
final SelectionKey key = channel.register(this.selector, SelectionKey.OP_READ | SelectionKey.OP_WRITE,
|
||||
keyAttachment);
|
||||
final SelectionKey key = channel.register(this.selector,
|
||||
SelectionKey.OP_READ/* | SelectionKey.OP_WRITE */, keyAttachment);
|
||||
keyAttachment.setKey(key);
|
||||
}
|
||||
else {
|
||||
@ -116,7 +116,9 @@ public class SelectableChannelOpener implements ChannelOpener {
|
||||
|
||||
while (keyIterator.hasNext()) {
|
||||
final SelectionKey key = keyIterator.next();
|
||||
((KeyAttachment) key.attachment()).selected();
|
||||
if (key.isValid()) {
|
||||
((KeyAttachment) key.attachment()).selected();
|
||||
}
|
||||
keyIterator.remove();
|
||||
}
|
||||
}
|
||||
|
@ -3,6 +3,7 @@ package net.warsmash.nio.channels.tcp;
|
||||
import java.io.IOException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.channels.SelectionKey;
|
||||
import java.nio.channels.Selector;
|
||||
import java.nio.channels.SocketChannel;
|
||||
|
||||
import net.warsmash.nio.channels.ChannelListener;
|
||||
@ -12,6 +13,7 @@ import net.warsmash.nio.util.ExceptionListener;
|
||||
|
||||
public class TCPClientKeyAttachment implements KeyAttachment, WritableOutput {
|
||||
private TCPClientParser parser;
|
||||
private final Selector selector;
|
||||
private final SocketChannel channel;
|
||||
private final ExceptionListener exceptionListener;
|
||||
private final ChannelListener channelListener;
|
||||
@ -19,8 +21,10 @@ public class TCPClientKeyAttachment implements KeyAttachment, WritableOutput {
|
||||
private final ByteBuffer writeBuffer;
|
||||
private SelectionKey key;
|
||||
|
||||
public TCPClientKeyAttachment(final SocketChannel channel, final ExceptionListener exceptionListener,
|
||||
final ChannelListener channelListener, final ByteBuffer readBuffer, final ByteBuffer writeBuffer) {
|
||||
public TCPClientKeyAttachment(final Selector selector, final SocketChannel channel,
|
||||
final ExceptionListener exceptionListener, final ChannelListener channelListener,
|
||||
final ByteBuffer readBuffer, final ByteBuffer writeBuffer) {
|
||||
this.selector = selector;
|
||||
this.channel = channel;
|
||||
this.exceptionListener = exceptionListener;
|
||||
this.channelListener = channelListener;
|
||||
@ -48,24 +52,30 @@ public class TCPClientKeyAttachment implements KeyAttachment, WritableOutput {
|
||||
}
|
||||
else if (nRead == -1) {
|
||||
this.parser.disconnected();
|
||||
this.channel.close();
|
||||
this.channelListener.channelClosed();
|
||||
close();
|
||||
return;
|
||||
}
|
||||
else {
|
||||
throw new IOException("Did not read bytes");
|
||||
}
|
||||
}
|
||||
catch (final IOException e) {
|
||||
close();
|
||||
this.exceptionListener.caught(e);
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (this.key.isWritable()) {
|
||||
this.writeBuffer.flip();
|
||||
try {
|
||||
this.channel.write(this.writeBuffer);
|
||||
}
|
||||
catch (final IOException e) {
|
||||
this.exceptionListener.caught(e);
|
||||
if (this.writeBuffer.remaining() > 0) {
|
||||
try {
|
||||
this.channel.write(this.writeBuffer);
|
||||
}
|
||||
catch (final IOException e) {
|
||||
close();
|
||||
this.exceptionListener.caught(e);
|
||||
return;
|
||||
}
|
||||
}
|
||||
this.writeBuffer.compact();
|
||||
}
|
||||
@ -74,6 +84,13 @@ public class TCPClientKeyAttachment implements KeyAttachment, WritableOutput {
|
||||
@Override
|
||||
public void close() {
|
||||
try {
|
||||
if (this.key != null) {
|
||||
this.key.cancel();
|
||||
}
|
||||
else {
|
||||
throw new IllegalStateException("close() called multiple times on TCPClientKeyAttachment");
|
||||
}
|
||||
this.key = null;
|
||||
this.channel.close();
|
||||
this.channelListener.channelClosed();
|
||||
}
|
||||
|
@ -50,13 +50,13 @@ public class TCPServerKeyAttachment implements KeyAttachment, OpenedChannel {
|
||||
readBuffer.order(this.byteOrder);
|
||||
final ByteBuffer writeBuffer = ByteBuffer.allocate(this.bufferSize);
|
||||
writeBuffer.order(this.byteOrder);
|
||||
final TCPClientKeyAttachment tcpServerClientKeyAttachment = new TCPClientKeyAttachment(socketChannel,
|
||||
this.exceptionListener, this.channelListener, readBuffer, writeBuffer);
|
||||
final TCPClientKeyAttachment tcpServerClientKeyAttachment = new TCPClientKeyAttachment(this.selector,
|
||||
socketChannel, this.exceptionListener, this.channelListener, readBuffer, writeBuffer);
|
||||
final TCPClientParser parser = this.callback.onConnect(tcpServerClientKeyAttachment,
|
||||
socketChannel.getRemoteAddress());
|
||||
tcpServerClientKeyAttachment.setParser(parser);
|
||||
tcpServerClientKeyAttachment.setKey(socketChannel.register(this.selector,
|
||||
SelectionKey.OP_READ | SelectionKey.OP_WRITE, tcpServerClientKeyAttachment));
|
||||
SelectionKey.OP_READ/* | SelectionKey.OP_WRITE */, tcpServerClientKeyAttachment));
|
||||
this.channelListener.channelOpened();
|
||||
}
|
||||
catch (final IOException e) {
|
||||
|
@ -7,4 +7,9 @@ public class GamingNetwork {
|
||||
public static final int CHANNEL_NAME_MAX_LENGTH = 128;
|
||||
public static final int PASSWORD_DATA_MAX_LENGTH = 512;
|
||||
public static final int MESSAGE_MAX_LENGTH = 256;
|
||||
|
||||
public static final String GAME_ID_BASE = "WAR3";
|
||||
public static final String GAME_ID_XPAC = "W3XP";
|
||||
|
||||
public static final int GAME_VERSION_DATA = 102201;
|
||||
}
|
||||
|
@ -0,0 +1,11 @@
|
||||
package net.warsmash.uberserver;
|
||||
|
||||
public interface GamingNetworkConnection extends GamingNetworkClientToServerListener {
|
||||
void addListener(GamingNetworkServerToClientListener listener);
|
||||
|
||||
void userRequestDisconnect();
|
||||
|
||||
boolean userRequestConnect();
|
||||
|
||||
String getGatewayString();
|
||||
}
|
@ -1,5 +1,8 @@
|
||||
package net.warsmash.uberserver;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import net.warsmash.nio.util.DisconnectListener;
|
||||
|
||||
public interface GamingNetworkServerToClientListener extends DisconnectListener {
|
||||
@ -35,4 +38,90 @@ public interface GamingNetworkServerToClientListener extends DisconnectListener
|
||||
public static final int CHANNEL_MESSAGE = 9;
|
||||
public static final int CHANNEL_EMOTE = 10;
|
||||
}
|
||||
|
||||
public static final class GamingNetworkServerToClientNotifier implements GamingNetworkServerToClientListener {
|
||||
private final List<GamingNetworkServerToClientListener> listeners = new ArrayList<>();
|
||||
|
||||
public void addSubscriber(final GamingNetworkServerToClientListener listener) {
|
||||
this.listeners.add(listener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void disconnected() {
|
||||
for (final GamingNetworkServerToClientListener listener : this.listeners) {
|
||||
listener.disconnected();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handshakeAccepted() {
|
||||
for (final GamingNetworkServerToClientListener listener : this.listeners) {
|
||||
listener.handshakeAccepted();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handshakeDenied(final HandshakeDeniedReason reason) {
|
||||
for (final GamingNetworkServerToClientListener listener : this.listeners) {
|
||||
listener.handshakeDenied(reason);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accountCreationOk() {
|
||||
for (final GamingNetworkServerToClientListener listener : this.listeners) {
|
||||
listener.accountCreationOk();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accountCreationFailed(final AccountCreationFailureReason reason) {
|
||||
for (final GamingNetworkServerToClientListener listener : this.listeners) {
|
||||
listener.accountCreationFailed(reason);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loginOk(final long sessionToken, final String welcomeMessage) {
|
||||
for (final GamingNetworkServerToClientListener listener : this.listeners) {
|
||||
listener.loginOk(sessionToken, welcomeMessage);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loginFailed(final LoginFailureReason loginFailureReason) {
|
||||
for (final GamingNetworkServerToClientListener listener : this.listeners) {
|
||||
listener.loginFailed(loginFailureReason);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void joinedChannel(final String channelName) {
|
||||
for (final GamingNetworkServerToClientListener listener : this.listeners) {
|
||||
listener.joinedChannel(channelName);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void badSession() {
|
||||
for (final GamingNetworkServerToClientListener listener : this.listeners) {
|
||||
listener.badSession();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void channelMessage(final String userName, final String message) {
|
||||
for (final GamingNetworkServerToClientListener listener : this.listeners) {
|
||||
listener.channelMessage(userName, message);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void channelEmote(final String userName, final String message) {
|
||||
for (final GamingNetworkServerToClientListener listener : this.listeners) {
|
||||
listener.channelEmote(userName, message);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -13,7 +13,7 @@ public class TCPGamingNetworkServerToClientParser implements TCPClientParser {
|
||||
|
||||
@Override
|
||||
public void parse(final ByteBuffer data) {
|
||||
while (data.remaining() > 8) {
|
||||
while (data.remaining() >= 8) {
|
||||
final int protocolMessageId = data.getInt(data.position() + 0);
|
||||
final int length = data.getInt(data.position() + 4);
|
||||
if (data.remaining() >= length) {
|
||||
@ -92,6 +92,9 @@ public class TCPGamingNetworkServerToClientParser implements TCPClientParser {
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user