Commit of updates for server from last weekend

This commit is contained in:
Retera 2022-02-21 10:12:59 -05:00
parent ccacf2cb57
commit 9becca479e
32 changed files with 1562 additions and 343 deletions

View File

@ -21,7 +21,7 @@ allprojects {
appName = "warsmash"
gdxVersion = '1.9.8'
antlrVersion = '4.7'
xstreamVersion = '1.4.9'
xstreamVersion = '1.4.19'
}
repositories {

View File

@ -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();

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;

View File

@ -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);
}
}

View File

@ -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);
}
}
}

View File

@ -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);
}
};
}
}

View File

@ -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) {
}
};
}
}
};
}
}

View File

@ -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);
}
}

View File

@ -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);

View File

@ -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();

View File

@ -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;
}
}

View File

@ -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];

View File

@ -220,7 +220,7 @@ public class CommandCardPopulatingAbilityVisitor implements CAbilityVisitor<Void
}
}
}
else {
else if (this.menuBaseOrderId == 0) {
if (this.multiSelect) {
return;
}

View File

@ -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;
}
}
}

View File

@ -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;
}
}
}

View File

@ -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);
}
}

View File

@ -12,4 +12,8 @@ public interface BattleNetUIActionListener {
void openCustomGameMenu();
void enterDefaultChat();
void createAccount(String username, String password, String repeatPassword);
void submitChatText(String text);
}

View File

@ -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();
}
}

View File

@ -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);
}
}
}

View File

@ -114,4 +114,9 @@ public class GamingNetworkServerToClientWriter extends AbstractWriter implements
this.writeBuffer.put(messageBytes);
send();
}
@Override
public void disconnected() {
throw new UnsupportedOperationException();
}
}

View File

@ -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);
}
}

View File

@ -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;
}
}
}

View File

@ -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);
}
}

View File

@ -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();
}
}

View File

@ -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();
}

View File

@ -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) {

View File

@ -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;
}

View File

@ -0,0 +1,11 @@
package net.warsmash.uberserver;
public interface GamingNetworkConnection extends GamingNetworkClientToServerListener {
void addListener(GamingNetworkServerToClientListener listener);
void userRequestDisconnect();
boolean userRequestConnect();
String getGatewayString();
}

View File

@ -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);
}
}
}
}

View File

@ -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;
}
}
}