Some network updates, check box UI frame, fix bug in unit sound play index

This commit is contained in:
Retera 2022-04-13 16:13:49 -04:00
parent 0e37ed51cc
commit 5240f17480
26 changed files with 1125 additions and 198 deletions

View File

@ -11,6 +11,7 @@ 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.LobbyGameSpeed;
import net.warsmash.uberserver.TCPGamingNetworkServerToClientParser;
public class GamingNetworkConnectionImpl implements GamingNetworkConnection {
@ -86,6 +87,28 @@ public class GamingNetworkConnectionImpl implements GamingNetworkConnection {
this.gamingNetworkClientToServerWriter.emoteMessage(sessionToken, text);
}
@Override
public void queryGamesList(final long sessionToken) {
this.gamingNetworkClientToServerWriter.queryGamesList(sessionToken);
}
@Override
public void queryGameInfo(final long sessionToken, final String gameName) {
this.gamingNetworkClientToServerWriter.queryGameInfo(sessionToken, gameName);
}
@Override
public void joinGame(final long sessionToken, final String gameName) {
this.gamingNetworkClientToServerWriter.joinGame(sessionToken, gameName);
}
@Override
public void createGame(final long sessionToken, final String gameName, final String mapName, final int totalSlots,
final LobbyGameSpeed gameSpeed, final long gameCreationTimeMillis) {
this.gamingNetworkClientToServerWriter.createGame(sessionToken, gameName, mapName, totalSlots, gameSpeed,
gameCreationTimeMillis);
}
@Override
public void disconnected() {
stop();

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.CheckBoxFrame;
import com.etheller.warsmash.parsers.fdf.frames.ClickConsumingTextureFrame;
import com.etheller.warsmash.parsers.fdf.frames.ControlFrame;
import com.etheller.warsmash.parsers.fdf.frames.EditBoxFrame;
@ -384,6 +385,19 @@ public final class GameUI extends AbstractUIFrame implements UIFrame {
&& parentDefinitionIfAvailable.has("DecorateFileNames"));
final ScrollBarFrame scrollBarFrame = new ScrollBarFrame(frameDefinition.getName(), parent, vertical);
final Float sliderMinValue = frameDefinition.getFloat("SliderMinValue");
if (sliderMinValue != null) {
scrollBarFrame.setMinValue(sliderMinValue.intValue());
}
final Float sliderMaxValue = frameDefinition.getFloat("SliderMaxValue");
if (sliderMaxValue != null) {
scrollBarFrame.setMaxValue(sliderMaxValue.intValue());
}
final Float sliderStepSize = frameDefinition.getFloat("SliderStepSize");
if (sliderStepSize != null) {
scrollBarFrame.setStepSize(sliderStepSize.intValue());
}
final String controlBackdropKey = frameDefinition.getString("ControlBackdrop");
final String incButtonFrameKey = frameDefinition.getString("ScrollBarIncButtonFrame");
final String decButtonFrameKey = frameDefinition.getString("ScrollBarDecButtonFrame");
@ -415,6 +429,10 @@ public final class GameUI extends AbstractUIFrame implements UIFrame {
scrollBarFrame.setValue(this, viewport2, 50);
}
}
final Float sliderInitialValue = frameDefinition.getFloat("SliderInitialValue");
if (sliderInitialValue != null) {
scrollBarFrame.setValue(this, viewport2, sliderInitialValue.intValue());
}
inflatedFrame = scrollBarFrame;
}
else if ("SPRITE".equals(frameDefinition.getFrameType())) {
@ -885,6 +903,54 @@ public final class GameUI extends AbstractUIFrame implements UIFrame {
}
inflatedFrame = glueButtonFrame;
}
else if ("CHECKBOX".equals(frameDefinition.getFrameType())
|| "GLUECHECKBOX".equals(frameDefinition.getFrameType())) {
// ButtonText & ControlBackdrop
final CheckBoxFrame glueButtonFrame = new CheckBoxFrame(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
this.nameToFrame.put(frameDefinition.getName(), glueButtonFrame);
final String controlBackdropKey = frameDefinition.getString("ControlBackdrop");
final String controlPushedBackdropKey = frameDefinition.getString("ControlPushedBackdrop");
final String controlDisabledBackdropKey = frameDefinition.getString("ControlDisabledBackdrop");
final String checkBoxCheckHighlightKey = frameDefinition.getString("CheckBoxCheckHighlight");
final String checkBoxDisabledCheckHighlightKey = frameDefinition
.getString("CheckBoxDisabledCheckHighlight");
for (final FrameDefinition childDefinition : frameDefinition.getInnerFrames()) {
if (childDefinition.getName().equals(controlBackdropKey)) {
final UIFrame inflatedChild = inflate(childDefinition, glueButtonFrame, frameDefinition,
inDecorateFileNames || childDefinition.has("DecorateFileNames"));
inflatedChild.setSetAllPoints(true);
glueButtonFrame.setControlBackdrop(inflatedChild);
}
else if (childDefinition.getName().equals(controlPushedBackdropKey)) {
final UIFrame inflatedChild = inflate(childDefinition, glueButtonFrame, frameDefinition,
inDecorateFileNames || childDefinition.has("DecorateFileNames"));
inflatedChild.setSetAllPoints(true);
glueButtonFrame.setControlPushedBackdrop(inflatedChild);
}
else if (childDefinition.getName().equals(controlDisabledBackdropKey)) {
final UIFrame inflatedChild = inflate(childDefinition, glueButtonFrame, frameDefinition,
inDecorateFileNames || childDefinition.has("DecorateFileNames"));
inflatedChild.setSetAllPoints(true);
glueButtonFrame.setControlDisabledBackdrop(inflatedChild);
}
else if (childDefinition.getName().equals(checkBoxCheckHighlightKey)) {
final UIFrame inflatedChild = inflate(childDefinition, glueButtonFrame, frameDefinition,
inDecorateFileNames || childDefinition.has("DecorateFileNames"));
inflatedChild.setSetAllPoints(true);
glueButtonFrame.setCheckBoxCheckHighlight(inflatedChild);
}
else if (childDefinition.getName().equals(checkBoxDisabledCheckHighlightKey)) {
final UIFrame inflatedChild = inflate(childDefinition, glueButtonFrame, frameDefinition,
inDecorateFileNames || childDefinition.has("DecorateFileNames"));
inflatedChild.setSetAllPoints(true);
glueButtonFrame.setCheckBoxDisabledCheckHighlight(inflatedChild);
}
}
inflatedFrame = glueButtonFrame;
}
else if ("TEXTBUTTON".equals(frameDefinition.getFrameType())) {
// ButtonText & ControlBackdrop
final TextButtonFrame glueButtonFrame = new TextButtonFrame(frameDefinition.getName(), parent);
@ -1188,6 +1254,9 @@ public final class GameUI extends AbstractUIFrame implements UIFrame {
if ("ADD".equals(highlightAlphaMode)) {
textureFrame.setFilterMode(FilterMode.ADDALPHA);
}
else if ("BLEND".equals(highlightAlphaMode)) {
textureFrame.setFilterMode(FilterMode.BLEND);
}
return textureFrame;
}
else if ("BACKDROP".equals(frameDefinition.getFrameType())) {

View File

@ -0,0 +1,82 @@
package com.etheller.warsmash.parsers.fdf.frames;
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;
public class CheckBoxFrame extends GlueButtonFrame {
private boolean checked = false;
private UIFrame checkBoxCheckHighlight;
private UIFrame checkBoxDisabledCheckHighlight;
private UIFrame activeChildHighlight;
public CheckBoxFrame(final String name, final UIFrame parent) {
super(name, parent);
}
public void setCheckBoxCheckHighlight(final UIFrame checkBoxCheckHighlight) {
this.checkBoxCheckHighlight = checkBoxCheckHighlight;
}
public void setCheckBoxDisabledCheckHighlight(final UIFrame checkBoxDisabledCheckHighlight) {
this.checkBoxDisabledCheckHighlight = checkBoxDisabledCheckHighlight;
}
@Override
protected void innerPositionBounds(final GameUI gameUI, final Viewport viewport) {
super.innerPositionBounds(gameUI, viewport);
if (this.checkBoxCheckHighlight != null) {
this.checkBoxCheckHighlight.positionBounds(gameUI, viewport);
}
if (this.checkBoxDisabledCheckHighlight != null) {
this.checkBoxDisabledCheckHighlight.positionBounds(gameUI, viewport);
}
updateCheckHighlight();
}
@Override
protected void internalRender(final SpriteBatch batch, final BitmapFont baseFont, final GlyphLayout glyphLayout) {
super.internalRender(batch, baseFont, glyphLayout);
if (this.activeChildHighlight != null) {
this.activeChildHighlight.render(batch, baseFont, glyphLayout);
}
}
@Override
public void mouseUp(final GameUI gameUI, final Viewport uiViewport) {
super.mouseUp(gameUI, uiViewport);
updateCheckHighlight();
}
private void updateCheckHighlight() {
if (this.checked) {
if (isEnabled()) {
this.activeChildHighlight = this.checkBoxCheckHighlight;
}
else {
this.activeChildHighlight = this.checkBoxDisabledCheckHighlight;
}
}
else {
this.activeChildHighlight = null;
}
}
public void setChecked(final boolean checked) {
this.checked = checked;
updateCheckHighlight();
}
public boolean isChecked() {
return this.checked;
}
@Override
public void onClick(final int button) {
this.checked = !this.checked;
super.onClick(button);
}
}

View File

@ -148,8 +148,9 @@ public class ListBoxFrame extends ControlFrame implements ScrollBarFrame.ScrollB
SingleStringFrame prev = null;
boolean foundSelected = false;
boolean foundMouseOver = false;
final int numStringFrames = (int) (Math
.floor((this.renderBounds.height - (this.listBoxBorder * 2)) / (this.frameFont.getLineHeight())));
final int numStringFrames = (int) Math.min(this.listItems.size(),
(Math.floor((this.renderBounds.height - (this.listBoxBorder * 2)) / (this.frameFont.getLineHeight()))));
final int scrollOffset = computeScrollOffset(numStringFrames);
if (numStringFrames != this.stringFrames.size()) {
this.stringFrames.clear();

View File

@ -9,15 +9,20 @@ 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 final boolean vertical;
private UIFrame controlBackdrop;
private UIFrame incButtonFrame;
private UIFrame decButtonFrame;
private UIFrame thumbButtonFrame;
private int scrollValuePercent = 50;
private ScrollBarChangeListener changeListener = ScrollBarChangeListener.DO_NOTHING;
private int minValue = 0;
private int maxValue = 100;
private int stepSize = 10;
public ScrollBarFrame(final String name, final UIFrame parent, final boolean vertical) {
super(name, parent);
this.vertical = vertical;
}
public void setControlBackdrop(final UIFrame controlBackdrop) {
@ -34,7 +39,7 @@ public class ScrollBarFrame extends AbstractRenderableFrame implements Clickable
@Override
public void mouseUp(final GameUI gameUI, final Viewport uiViewport) {
setValue(gameUI, uiViewport, ScrollBarFrame.this.scrollValuePercent + 10);
setValue(gameUI, uiViewport, ScrollBarFrame.this.scrollValuePercent + ScrollBarFrame.this.stepSize);
}
@Override
@ -54,7 +59,7 @@ public class ScrollBarFrame extends AbstractRenderableFrame implements Clickable
@Override
public void mouseUp(final GameUI gameUI, final Viewport uiViewport) {
setValue(gameUI, uiViewport, ScrollBarFrame.this.scrollValuePercent - 10);
setValue(gameUI, uiViewport, ScrollBarFrame.this.scrollValuePercent - ScrollBarFrame.this.stepSize);
}
@Override
@ -89,15 +94,37 @@ public class ScrollBarFrame extends AbstractRenderableFrame implements Clickable
}
}
public void setMinValue(final int minValue) {
this.minValue = minValue;
}
public void setMaxValue(final int maxValue) {
this.maxValue = maxValue;
}
public void setStepSize(final int stepSize) {
this.stepSize = stepSize;
}
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;
if (this.vertical) {
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;
}
else {
final float incButtonFrameWidth = this.incButtonFrame == null ? 0 : this.incButtonFrame.getAssignedWidth();
final float decButtonFrameWidth = this.decButtonFrame == null ? 0 : this.decButtonFrame.getAssignedWidth();
return this.renderBounds.width - this.thumbButtonFrame.getAssignedWidth() - incButtonFrameWidth
- decButtonFrameWidth;
}
}
public void setValue(final GameUI gameUI, final Viewport uiViewport, final int percent) {
this.scrollValuePercent = Math.min(100, Math.max(0, percent));
this.scrollValuePercent = Math.min(this.maxValue, Math.max(this.minValue, percent));
updateThumbButtonPoint();
this.changeListener.onChange(gameUI, uiViewport, this.scrollValuePercent);
positionBounds(gameUI, uiViewport);
@ -108,13 +135,28 @@ public class ScrollBarFrame extends AbstractRenderableFrame implements Clickable
}
public void updateThumbButtonPoint() {
final float newYValue = (this.scrollValuePercent / 100f) * getMaxThumbButtonTravelDistance();
if (this.decButtonFrame != null) {
this.thumbButtonFrame
.addSetPoint(new SetPoint(FramePoint.BOTTOM, this.decButtonFrame, FramePoint.TOP, 0, newYValue));
if (this.vertical) {
final float newYValue = (this.scrollValuePercent / (float) this.maxValue)
* getMaxThumbButtonTravelDistance();
if (this.decButtonFrame != null) {
this.thumbButtonFrame.addSetPoint(
new SetPoint(FramePoint.BOTTOM, this.decButtonFrame, FramePoint.TOP, 0, newYValue));
}
else {
this.thumbButtonFrame
.addSetPoint(new SetPoint(FramePoint.BOTTOM, this, FramePoint.BOTTOM, 0, newYValue));
}
}
else {
this.thumbButtonFrame.addSetPoint(new SetPoint(FramePoint.BOTTOM, this, FramePoint.BOTTOM, 0, newYValue));
final float newXValue = (this.scrollValuePercent / (float) this.maxValue)
* getMaxThumbButtonTravelDistance();
if (this.decButtonFrame != null) {
this.thumbButtonFrame.addSetPoint(
new SetPoint(FramePoint.LEFT, this.decButtonFrame, FramePoint.RIGHT, 0, newXValue));
}
else {
this.thumbButtonFrame.addSetPoint(new SetPoint(FramePoint.LEFT, this, FramePoint.LEFT, newXValue, 0));
}
}
}
@ -174,11 +216,20 @@ public class ScrollBarFrame extends AbstractRenderableFrame implements Clickable
@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)));
final int newScrollValuePercent;
if (this.vertical) {
final float decFrameHeight = this.decButtonFrame == null ? 0 : this.decButtonFrame.getAssignedHeight();
newScrollValuePercent = Math.min(this.maxValue, Math.max(this.minValue, Math
.round(((y - this.renderBounds.y - decFrameHeight - (this.thumbButtonFrame.getAssignedHeight() / 2))
/ maxThumbButtonTravelDistance) * this.maxValue)));
}
else {
final float decFrameWidth = this.decButtonFrame == null ? 0 : this.decButtonFrame.getAssignedWidth();
newScrollValuePercent = Math.min(this.maxValue,
Math.max(this.minValue, Math.round(
((x - this.renderBounds.x - decFrameWidth - (this.thumbButtonFrame.getAssignedWidth() / 2))
/ maxThumbButtonTravelDistance) * this.maxValue)));
}
if (newScrollValuePercent != this.scrollValuePercent) {
setValue(rootFrame, uiViewport, newScrollValuePercent);
positionBounds(rootFrame, uiViewport);
@ -193,17 +244,23 @@ public class ScrollBarFrame extends AbstractRenderableFrame implements Clickable
if (frameChildUnderMouse != null) {
return frameChildUnderMouse;
}
frameChildUnderMouse = this.incButtonFrame.touchUp(screenX, screenY, button);
if (frameChildUnderMouse != null) {
return frameChildUnderMouse;
if (this.incButtonFrame != null) {
frameChildUnderMouse = this.incButtonFrame.touchUp(screenX, screenY, button);
if (frameChildUnderMouse != null) {
return frameChildUnderMouse;
}
}
frameChildUnderMouse = this.decButtonFrame.touchUp(screenX, screenY, button);
if (frameChildUnderMouse != null) {
return frameChildUnderMouse;
if (this.decButtonFrame != null) {
frameChildUnderMouse = this.decButtonFrame.touchUp(screenX, screenY, button);
if (frameChildUnderMouse != null) {
return frameChildUnderMouse;
}
}
frameChildUnderMouse = this.controlBackdrop.touchUp(screenX, screenY, button);
if (frameChildUnderMouse != null) {
return frameChildUnderMouse;
if (this.controlBackdrop != null) {
frameChildUnderMouse = this.controlBackdrop.touchUp(screenX, screenY, button);
if (frameChildUnderMouse != null) {
return frameChildUnderMouse;
}
}
return this;
}
@ -217,17 +274,23 @@ public class ScrollBarFrame extends AbstractRenderableFrame implements Clickable
if (frameChildUnderMouse != null) {
return frameChildUnderMouse;
}
frameChildUnderMouse = this.incButtonFrame.touchDown(screenX, screenY, button);
if (frameChildUnderMouse != null) {
return frameChildUnderMouse;
if (this.incButtonFrame != null) {
frameChildUnderMouse = this.incButtonFrame.touchDown(screenX, screenY, button);
if (frameChildUnderMouse != null) {
return frameChildUnderMouse;
}
}
frameChildUnderMouse = this.decButtonFrame.touchDown(screenX, screenY, button);
if (frameChildUnderMouse != null) {
return frameChildUnderMouse;
if (this.decButtonFrame != null) {
frameChildUnderMouse = this.decButtonFrame.touchDown(screenX, screenY, button);
if (frameChildUnderMouse != null) {
return frameChildUnderMouse;
}
}
frameChildUnderMouse = this.controlBackdrop.touchDown(screenX, screenY, button);
if (frameChildUnderMouse != null) {
return frameChildUnderMouse;
if (this.controlBackdrop != null) {
frameChildUnderMouse = this.controlBackdrop.touchDown(screenX, screenY, button);
if (frameChildUnderMouse != null) {
return frameChildUnderMouse;
}
}
return this;
}
@ -241,17 +304,23 @@ public class ScrollBarFrame extends AbstractRenderableFrame implements Clickable
if (frameChildUnderMouse != null) {
return frameChildUnderMouse;
}
frameChildUnderMouse = this.incButtonFrame.getFrameChildUnderMouse(screenX, screenY);
if (frameChildUnderMouse != null) {
return frameChildUnderMouse;
if (this.incButtonFrame != null) {
frameChildUnderMouse = this.incButtonFrame.getFrameChildUnderMouse(screenX, screenY);
if (frameChildUnderMouse != null) {
return frameChildUnderMouse;
}
}
frameChildUnderMouse = this.decButtonFrame.getFrameChildUnderMouse(screenX, screenY);
if (frameChildUnderMouse != null) {
return frameChildUnderMouse;
if (this.decButtonFrame != null) {
frameChildUnderMouse = this.decButtonFrame.getFrameChildUnderMouse(screenX, screenY);
if (frameChildUnderMouse != null) {
return frameChildUnderMouse;
}
}
frameChildUnderMouse = this.controlBackdrop.getFrameChildUnderMouse(screenX, screenY);
if (frameChildUnderMouse != null) {
return frameChildUnderMouse;
if (this.controlBackdrop != null) {
frameChildUnderMouse = this.controlBackdrop.getFrameChildUnderMouse(screenX, screenY);
if (frameChildUnderMouse != null) {
return frameChildUnderMouse;
}
}
return this;
}

View File

@ -1,5 +1,7 @@
package com.etheller.warsmash.parsers.fdf.frames;
import java.util.EnumSet;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.g2d.BitmapFont;
import com.badlogic.gdx.graphics.g2d.GlyphLayout;
@ -12,6 +14,7 @@ import com.etheller.warsmash.viewer5.handlers.mdx.MdxComplexInstance;
import com.etheller.warsmash.viewer5.handlers.mdx.MdxModel;
import com.etheller.warsmash.viewer5.handlers.mdx.SequenceLoopMode;
import com.etheller.warsmash.viewer5.handlers.w3x.AnimationTokens.PrimaryTag;
import com.etheller.warsmash.viewer5.handlers.w3x.AnimationTokens.SecondaryTag;
import com.etheller.warsmash.viewer5.handlers.w3x.SequenceUtils;
public class SpriteFrame extends AbstractUIFrame {
@ -94,6 +97,12 @@ public class SpriteFrame extends AbstractUIFrame {
}
}
public void setSequence(final PrimaryTag animationName, final EnumSet<SecondaryTag> secondaryTags) {
if (this.instance != null) {
SequenceUtils.randomSequence(this.instance, animationName, secondaryTags, true);
}
}
public void setAnimationSpeed(final float speedRatio) {
if (this.instance != null) {
this.instance.setAnimationSpeed(speedRatio);

View File

@ -204,7 +204,12 @@ public class Jass2 {
final JassProgramVisitor jassProgramVisitor = new JassProgramVisitor();
final ConfigEnvironment environment = new ConfigEnvironment(jassProgramVisitor, dataSource, uiViewport, uiScene,
gameUI, mapConfig);
for (final String jassFile : files) {
for (String jassFilePath : files) {
if (!dataSource.has(jassFilePath)) {
jassFilePath = jassFilePath
.substring(Math.max(jassFilePath.lastIndexOf('/'), jassFilePath.lastIndexOf('\\')) + 1);
}
final String jassFile = jassFilePath;
try {
JassLexer lexer;
try {

View File

@ -27,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 = true;
public static final boolean CATCH_CURSOR = false;
public static final boolean VERBOSE_LOGGING = false;
public static final boolean ENABLE_DEBUG = false;
public static final char SPECIAL_ESCAPE_KEYCODE = 0x7E;
@ -38,7 +38,7 @@ public class WarsmashConstants {
// workaround to fix it if you need the local files
// to take priority over built-ins for tilesets.
public static final boolean FIX_FLAT_FILES_TILESET_LOADING = false;
public static final boolean ENABLE_MUSIC = true;
public static final boolean ENABLE_MUSIC = false;
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;

View File

@ -106,7 +106,7 @@ public final class UnitSound {
if (millisTime < unit.lastUnitResponseEndTimeMillis) {
return false;
}
if (play(audioContext, unit.location[0], unit.location[1], unit.location[2])) {
if (play(audioContext, unit.location[0], unit.location[1], unit.location[2], index)) {
final float duration = Extensions.audio.getDuration(this.lastPlayedSound);
unit.lastUnitResponseEndTimeMillis = millisTime + (long) (1000 * duration);
return true;

View File

@ -11,6 +11,7 @@ import java.util.EnumSet;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Queue;
import java.util.Set;
import java.util.concurrent.TimeUnit;
@ -2053,7 +2054,7 @@ public class MeleeUI implements CUnitStateListener, CommandButtonListener, Comma
int index = -1;
for (int i = 0; i < model.attachments.size(); i++) {
final Attachment attachment = model.attachments.get(i);
if (attachment.getName().startsWith("sprite")) {
if (attachment.getName().toLowerCase(Locale.US).startsWith("sprite rally")) {
index = i;
break;
}
@ -2061,7 +2062,16 @@ public class MeleeUI implements CUnitStateListener, CommandButtonListener, Comma
if (index == -1) {
for (int i = 0; i < model.attachments.size(); i++) {
final Attachment attachment = model.attachments.get(i);
if (attachment.getName().startsWith("overhead ref")) {
if (attachment.getName().toLowerCase(Locale.US).startsWith("sprite")) {
index = i;
break;
}
}
}
if (index == -1) {
for (int i = 0; i < model.attachments.size(); i++) {
final Attachment attachment = model.attachments.get(i);
if (attachment.getName().toLowerCase(Locale.US).startsWith("overhead ref")) {
index = i;
}
}

View File

@ -5,8 +5,6 @@ import java.io.InputStream;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import com.badlogic.gdx.Gdx;
@ -58,6 +56,7 @@ import com.etheller.warsmash.util.WorldEditStrings;
import com.etheller.warsmash.viewer5.Scene;
import com.etheller.warsmash.viewer5.handlers.mdx.MdxViewer;
import com.etheller.warsmash.viewer5.handlers.w3x.AnimationTokens.PrimaryTag;
import com.etheller.warsmash.viewer5.handlers.w3x.SequenceUtils;
import com.etheller.warsmash.viewer5.handlers.w3x.UnitSound;
import com.etheller.warsmash.viewer5.handlers.w3x.War3MapViewer;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.config.CBasePlayer;
@ -72,6 +71,7 @@ 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.MapListContainer;
import com.etheller.warsmash.viewer5.handlers.w3x.ui.mapsetup.TeamSetupPane;
import com.etheller.warsmash.viewer5.handlers.w3x.ui.menu.BattleNetUI;
import com.etheller.warsmash.viewer5.handlers.w3x.ui.menu.BattleNetUIActionListener;
@ -85,6 +85,7 @@ import net.warsmash.uberserver.GamingNetwork;
import net.warsmash.uberserver.GamingNetworkConnection;
import net.warsmash.uberserver.GamingNetworkServerToClientListener;
import net.warsmash.uberserver.HandshakeDeniedReason;
import net.warsmash.uberserver.JoinGameFailureReason;
import net.warsmash.uberserver.LoginFailureReason;
public class MenuUI {
@ -266,7 +267,7 @@ public class MenuUI {
@Override
public void run() {
MenuUI.this.battleNetUI.loginAccepted(sessionToken, welcomeMessage);
MenuUI.this.battleNetUI.getDoors().setSequence(PrimaryTag.DEATH);
MenuUI.this.battleNetUI.getDoors().setSequence(PrimaryTag.DEATH, SequenceUtils.ALTERNATE);
MenuUI.this.menuState = MenuState.GOING_TO_BATTLE_NET_WELCOME;
}
});
@ -388,6 +389,59 @@ public class MenuUI {
}
});
}
@Override
public void joinedGame(final String gameName) {
Gdx.app.postRunnable(new Runnable() {
@Override
public void run() {
MenuUI.this.battleNetUI.joinedChannel(gameName);
MenuUI.this.battleNetUI.hideCurrentScreen();
playCurrentBattleNetGlueSpriteDeath();
MenuUI.this.menuState = MenuState.GOING_TO_BATTLE_NET_CHAT_CHANNEL;
MenuUI.this.dialog.showError("bruh program the join game function", null);
}
});
}
@Override
public void joinGameFailed(final JoinGameFailureReason reason) {
Gdx.app.postRunnable(new Runnable() {
@Override
public void run() {
switch (reason) {
case GAME_ALREADY_STARTED:
MenuUI.this.dialog.showError("ERROR_ID_GAMECLOSED", null);
break;
case GAME_FULL:
MenuUI.this.dialog.showError("ERROR_ID_GAMEFULL", null);
break;
default:
case NO_SUCH_GAME:
MenuUI.this.dialog.showError("NETERROR_JOINGAMENOTFOUND", null);
break;
}
}
});
}
@Override
public void beginGamesList() {
// TODO Auto-generated method stub
}
@Override
public void gamesListItem(final String gameName, final int openSlots, final int totalSlots) {
// TODO Auto-generated method stub
}
@Override
public void endGamesList() {
// TODO Auto-generated method stub
}
});
}
@ -751,24 +805,9 @@ public class MenuUI {
final GlueTextButtonFrame playGameButton = (GlueTextButtonFrame) this.rootFrame.getFrameByName("PlayGameButton",
0);
final SimpleFrame mapListContainer = (SimpleFrame) this.rootFrame.getFrameByName("MapListContainer", 0);
final ListBoxFrame mapListBox = (ListBoxFrame) this.rootFrame.createFrameByType("LISTBOX", "MapListBox",
mapListContainer, "WITHCHILDREN", 0);
mapListBox.setSetAllPoints(true);
mapListBox.setFrameFont(profileListText.getFrameFont());
final Collection<String> listfile = this.dataSource.getListfile();
final List<String> displayItemPaths = new ArrayList<>();
for (final String file : listfile) {
if ((file.toLowerCase().endsWith(".w3x") || file.toLowerCase().endsWith(".w3m")) && !file.contains("/")
&& !file.contains("\\")) {
displayItemPaths.add(file);
}
}
Collections.sort(displayItemPaths);
for (final String displayItemPath : displayItemPaths) {
mapListBox.addItem(displayItemPath, this.rootFrame, this.uiViewport);
}
mapListBox.setSelectionListener(new ListBoxSelelectionListener() {
final MapListContainer mapListContainer = new MapListContainer(this.rootFrame, this.uiViewport,
"MapListContainer", this.dataSource, profileListText.getFrameFont());
mapListContainer.addSelectionListener(new ListBoxSelelectionListener() {
@Override
public void onSelectionChanged(final int newSelectedIndex, final String newSelectedItem) {
if (newSelectedItem != null) {
@ -805,11 +844,10 @@ public class MenuUI {
}
}
});
mapListContainer.add(mapListBox);
playGameButton.setOnClick(new Runnable() {
@Override
public void run() {
final String selectedItem = mapListBox.getSelectedItem();
final String selectedItem = mapListContainer.getSelectedItem();
if (selectedItem != null) {
MenuUI.this.campaignMenu.setVisible(false);
MenuUI.this.campaignBackButton.setVisible(false);
@ -982,122 +1020,160 @@ public class MenuUI {
this.loadingMeleePanel = this.rootFrame.getFrameByName("LoadingMeleePanel", 0);
this.loadingMeleePanel.setVisible(false);
this.battleNetUI = new BattleNetUI(this.rootFrame, this.uiViewport, new BattleNetUIActionListener() {
@Override
public void cancelLoginPrompt() {
MenuUI.this.battleNetUI.hide();
MenuUI.this.battleNetUI.getDoors().setSequence(PrimaryTag.DEATH);
MenuUI.this.menuScreen.unAlternateModelBackToNormal();
MenuUI.this.menuState = MenuState.LEAVING_BATTLE_NET;
MenuUI.this.gamingNetworkConnection.userRequestDisconnect();
}
this.battleNetUI = new BattleNetUI(this.rootFrame, this.uiViewport, this.dataSource,
new BattleNetUIActionListener() {
@Override
public void cancelLoginPrompt() {
MenuUI.this.battleNetUI.hide();
MenuUI.this.battleNetUI.getDoors().setSequence(PrimaryTag.DEATH);
MenuUI.this.menuScreen.unAlternateModelBackToNormal();
MenuUI.this.menuState = MenuState.LEAVING_BATTLE_NET;
MenuUI.this.gamingNetworkConnection.userRequestDisconnect();
}
@Override
public void recoverPassword(final String text) {
@Override
public void recoverPassword(final String text) {
}
}
@Override
public void logon(final String accountName, final String password) {
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);
}
}
@Override
public void logon(final String accountName, final String password) {
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;
}
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
public void quitBattleNet() {
MenuUI.this.battleNetUI.hide();
playCurrentBattleNetGlueSpriteDeath();
MenuUI.this.glueSpriteLayerCenter.setSequence("Death");
MenuUI.this.menuState = MenuState.LEAVING_BATTLE_NET_FROM_LOGGED_IN;
MenuUI.this.gamingNetworkConnection.userRequestDisconnect();
}
@Override
public void quitBattleNet() {
MenuUI.this.battleNetUI.hide();
playCurrentBattleNetGlueSpriteDeath();
MenuUI.this.glueSpriteLayerCenter.setSequence("Death");
MenuUI.this.menuState = MenuState.LEAVING_BATTLE_NET_FROM_LOGGED_IN;
MenuUI.this.gamingNetworkConnection.userRequestDisconnect();
}
@Override
public void openCustomGameMenu() {
MenuUI.this.battleNetUI.hideCurrentScreen();
playCurrentBattleNetGlueSpriteDeath();
MenuUI.this.glueSpriteLayerCenter.setSequence("Death");
MenuUI.this.menuState = MenuState.GOING_TO_BATTLE_NET_CUSTOM_GAME_MENU;
}
@Override
public void openCustomGameMenu() {
MenuUI.this.battleNetUI.hideCurrentScreen();
playCurrentBattleNetGlueSpriteDeath();
final boolean insideTopBarMode = isInsideTopBarMode();
if (insideTopBarMode) {
MenuUI.this.glueSpriteLayerCenter.setSequence("Death");
}
MenuUI.this.menuState = MenuState.GOING_TO_BATTLE_NET_CUSTOM_GAME_MENU;
}
@Override
public void enterDefaultChat() {
MenuUI.this.gamingNetworkConnection.joinChannel(MenuUI.this.battleNetUI.getGamingNetworkSessionToken(),
"Frozen Throne USA-1"); // TODO maybe not hardcode this
}
@Override
public void enterDefaultChat() {
MenuUI.this.gamingNetworkConnection.joinChannel(
MenuUI.this.battleNetUI.getGamingNetworkSessionToken(), "Frozen Throne USA-1"); // TODO
// maybe
// not
// hardcode
// this
}
@Override
public void returnToChat() {
MenuUI.this.battleNetUI.hideCurrentScreen();
playCurrentBattleNetGlueSpriteDeath();
MenuUI.this.menuState = MenuState.GOING_TO_BATTLE_NET_CHAT_CHANNEL;
}
@Override
public void returnToChat() {
MenuUI.this.battleNetUI.hideCurrentScreen();
playCurrentBattleNetGlueSpriteDeath();
if (MenuUI.this.battleNetUI.getCurrentChannel() == null) {
MenuUI.this.menuState = MenuState.GOING_TO_BATTLE_NET_WELCOME;
}
else {
final boolean insideTopBarMode = isInsideTopBarMode();
if (insideTopBarMode) {
MenuUI.this.menuState = MenuState.GOING_TO_BATTLE_NET_CHAT_CHANNEL;
}
else {
MenuUI.this.menuState = MenuState.GOING_TO_BATTLE_NET_CHAT_CHANNEL_FROM_OUTSIDE;
}
}
}
@Override
public void requestJoinChannel(final String text) {
MenuUI.this.gamingNetworkConnection.joinChannel(MenuUI.this.battleNetUI.getGamingNetworkSessionToken(),
text);
}
@Override
public void requestJoinChannel(final String text) {
MenuUI.this.gamingNetworkConnection
.joinChannel(MenuUI.this.battleNetUI.getGamingNetworkSessionToken(), text);
}
@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 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);
}
}
@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);
}
}
@Override
public void showChannelChooserPanel() {
MenuUI.this.battleNetUI.hideCurrentScreen();
playCurrentBattleNetGlueSpriteDeath();
MenuUI.this.menuState = MenuState.GOING_TO_BATTLE_NET_CHANNEL_MENU;
@Override
public void showChannelChooserPanel() {
MenuUI.this.battleNetUI.hideCurrentScreen();
playCurrentBattleNetGlueSpriteDeath();
MenuUI.this.menuState = MenuState.GOING_TO_BATTLE_NET_CHANNEL_MENU;
}
});
}
@Override
public void showCreateGameMenu() {
MenuUI.this.battleNetUI.hideCurrentScreen();
playCurrentBattleNetGlueSpriteDeath();
MenuUI.this.menuState = MenuState.GOING_TO_BATTLE_NET_CREATE_CUSTOM_GAME_MENU;
}
@Override
public void requestJoinGame(final String text) {
MenuUI.this.gamingNetworkConnection
.joinGame(MenuUI.this.battleNetUI.getGamingNetworkSessionToken(), text);
}
@Override
public void showError(final String errorKey) {
MenuUI.this.dialog.showError(errorKey, null);
}
});
this.dialog = new DialogWar3(this.rootFrame, this.uiViewport);
@ -1274,7 +1350,7 @@ public class MenuUI {
return;
}
else if (this.loadingMap != null) {
final int localPlayerIndex = MultiplayerHack.LP_VAL;
int localPlayerIndex = MultiplayerHack.LP_VAL;
try {
this.loadingMap.viewer.loadMap(this.loadingMap.map, this.loadingMap.mapInfo, localPlayerIndex);
}
@ -1302,13 +1378,22 @@ public class MenuUI {
uiOrderListener = new WarsmashClientSendingOrderListener(warsmashClientWriter);
}
else {
final War3MapViewer mapViewer = this.loadingMap.viewer;
for (int i = 0; i < WarsmashConstants.MAX_PLAYERS; i++) {
final CBasePlayer configPlayer = mapViewer.getMapConfig().getPlayer(i);
if ((configPlayer.getSlotState() == CPlayerSlotState.PLAYING)
&& (configPlayer.getController() == CMapControl.USER)) {
localPlayerIndex = i;
break;
}
}
mapViewer.setLocalPlayerIndex(localPlayerIndex);
final CPlayerUnitOrderExecutor executor = new CPlayerUnitOrderExecutor(
this.loadingMap.viewer.simulation, localPlayerIndex);
final CPlayerUnitOrderListenerDelaying delayingListener = new CPlayerUnitOrderListenerDelaying(
executor);
uiOrderListener = delayingListener;
warsmashClient = null;
final War3MapViewer mapViewer = this.loadingMap.viewer;
mapViewer.setGameTurnManager(new GameTurnManager() {
@Override
public void turnCompleted(final int gameTurnTick) {
@ -1444,6 +1529,16 @@ public class MenuUI {
MenuUI.this.glueSpriteLayerTopLeft.setSequence("BattleNetCustom Stand");
MenuUI.this.glueSpriteLayerTopRight.setSequence("BattleNetCustom Stand");
break;
case GOING_TO_BATTLE_NET_CREATE_CUSTOM_GAME_MENU:
MenuUI.this.glueSpriteLayerTopLeft.setSequence("BattleNetCustomCreate Birth");
MenuUI.this.glueSpriteLayerTopRight.setSequence("BattleNetCustomCreate Birth");
this.menuState = MenuState.BATTLE_NET_CREATE_CUSTOM_GAME_MENU;
break;
case BATTLE_NET_CREATE_CUSTOM_GAME_MENU:
this.battleNetUI.showCustomGameCreateMenu();
MenuUI.this.glueSpriteLayerTopLeft.setSequence("BattleNetCustomCreate Stand");
MenuUI.this.glueSpriteLayerTopRight.setSequence("BattleNetCustomCreate Stand");
break;
case GOING_TO_BATTLE_NET_CHANNEL_MENU:
MenuUI.this.glueSpriteLayerTopLeft.setSequence("BattleNetChannel Birth");
MenuUI.this.glueSpriteLayerTopRight.setSequence("BattleNetChannel Birth");
@ -1454,6 +1549,9 @@ public class MenuUI {
MenuUI.this.glueSpriteLayerTopLeft.setSequence("BattleNetChannel Stand");
MenuUI.this.glueSpriteLayerTopRight.setSequence("BattleNetChannel Stand");
break;
case GOING_TO_BATTLE_NET_CHAT_CHANNEL_FROM_OUTSIDE:
this.glueSpriteLayerCenter.setVisible(true);
this.glueSpriteLayerCenter.setSequence("Birth");
case GOING_TO_BATTLE_NET_CHAT_CHANNEL:
MenuUI.this.glueSpriteLayerTopLeft.setSequence("BattleNetChatRoom Birth");
MenuUI.this.glueSpriteLayerTopRight.setSequence("BattleNetChatRoom Birth");
@ -1689,11 +1787,12 @@ 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_CHANNEL_MENU, BATTLE_NET_CHANNEL_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_CUSTOM_GAME_MENU, GOING_TO_BATTLE_NET_CREATE_CUSTOM_GAME_MENU, BATTLE_NET_CREATE_CUSTOM_GAME_MENU,
GOING_TO_BATTLE_NET_CHANNEL_MENU, BATTLE_NET_CHANNEL_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, GOING_TO_BATTLE_NET_CHAT_CHANNEL_FROM_OUTSIDE,
BATTLE_NET_CHAT_CHANNEL;
}
@ -1867,6 +1966,16 @@ public class MenuUI {
MenuUI.this.glueSpriteLayerTopLeft.setSequence("BattleNetChatRoom Death");
MenuUI.this.glueSpriteLayerTopRight.setSequence("BattleNetChatRoom Death");
break;
case BATTLE_NET_CUSTOM_GAME_MENU:
case GOING_TO_BATTLE_NET_CUSTOM_GAME_MENU:
MenuUI.this.glueSpriteLayerTopLeft.setSequence("BattleNetCustom Death");
MenuUI.this.glueSpriteLayerTopRight.setSequence("BattleNetCustom Death");
break;
case BATTLE_NET_CREATE_CUSTOM_GAME_MENU:
case GOING_TO_BATTLE_NET_CREATE_CUSTOM_GAME_MENU:
MenuUI.this.glueSpriteLayerTopLeft.setSequence("BattleNetCustomCreate Death");
MenuUI.this.glueSpriteLayerTopRight.setSequence("BattleNetCustomCreate Death");
break;
case BATTLE_NET_CHANNEL_MENU:
case GOING_TO_BATTLE_NET_CHANNEL_MENU:
MenuUI.this.glueSpriteLayerTopLeft.setSequence("BattleNetChannel Death");
@ -1880,4 +1989,20 @@ public class MenuUI {
break;
}
}
private boolean isInsideTopBarMode() {
boolean insideTopBarMode = false;
switch (MenuUI.this.menuState) {
case GOING_TO_BATTLE_NET_CHANNEL_MENU:
case BATTLE_NET_CHANNEL_MENU:
case GOING_TO_BATTLE_NET_CHAT_CHANNEL:
case GOING_TO_BATTLE_NET_CHAT_CHANNEL_FROM_OUTSIDE:
case BATTLE_NET_CHAT_CHANNEL:
case GOING_TO_BATTLE_NET_WELCOME:
case BATTLE_NET_WELCOME:
insideTopBarMode = true;
break;
}
return insideTopBarMode;
}
}

View File

@ -0,0 +1,49 @@
package com.etheller.warsmash.viewer5.handlers.w3x.ui.mapsetup;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import com.badlogic.gdx.graphics.g2d.BitmapFont;
import com.badlogic.gdx.utils.viewport.Viewport;
import com.etheller.warsmash.datasources.DataSource;
import com.etheller.warsmash.parsers.fdf.GameUI;
import com.etheller.warsmash.parsers.fdf.frames.ListBoxFrame;
import com.etheller.warsmash.parsers.fdf.frames.ListBoxFrame.ListBoxSelelectionListener;
import com.etheller.warsmash.parsers.fdf.frames.SimpleFrame;
public class MapListContainer {
private final SimpleFrame mapListContainer;
private final ListBoxFrame mapListBox;
public MapListContainer(final GameUI rootFrame, final Viewport uiViewport, final String containerKey,
final DataSource dataSource, final BitmapFont font) {
this.mapListContainer = (SimpleFrame) rootFrame.getFrameByName(containerKey, 0);
this.mapListBox = (ListBoxFrame) rootFrame.createFrameByType("LISTBOX", "MapListBox", this.mapListContainer,
"WITHCHILDREN", 0);
this.mapListBox.setSetAllPoints(true);
this.mapListBox.setFrameFont(font);
final Collection<String> listfile = dataSource.getListfile();
final List<String> displayItemPaths = new ArrayList<>();
for (final String file : listfile) {
if ((file.toLowerCase().endsWith(".w3x") || file.toLowerCase().endsWith(".w3m")) && !file.contains("/")
&& !file.contains("\\")) {
displayItemPaths.add(file);
}
}
Collections.sort(displayItemPaths);
for (final String displayItemPath : displayItemPaths) {
this.mapListBox.addItem(displayItemPath, rootFrame, uiViewport);
}
this.mapListContainer.add(this.mapListBox);
}
public void addSelectionListener(final ListBoxSelelectionListener listener) {
this.mapListBox.setSelectionListener(listener);
}
public String getSelectedItem() {
return this.mapListBox.getSelectedItem();
}
}

View File

@ -9,8 +9,10 @@ import com.etheller.warsmash.parsers.fdf.GameUI;
import com.etheller.warsmash.parsers.fdf.datamodel.FramePoint;
import com.etheller.warsmash.parsers.fdf.frames.SetPoint;
import com.etheller.warsmash.parsers.fdf.frames.SimpleFrame;
import com.etheller.warsmash.util.WarsmashConstants;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.config.CBasePlayer;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.config.War3MapConfig;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.trigger.enumtypes.CPlayerSlotState;
public class TeamSetupPane {
private final List<PlayerSlotPane> playerSlots = new ArrayList<>();
@ -26,19 +28,24 @@ public class TeamSetupPane {
this.container.remove(playerSlotPane.getPlayerSlotFrame());
}
this.playerSlots.clear();
for (int i = 0; i < playerCount; i++) {
int usedSlots = 0;
for (int i = 0; (i < WarsmashConstants.MAX_PLAYERS) && (usedSlots < playerCount); i++) {
final CBasePlayer player = config.getPlayer(i);
if (player.getSlotState() == CPlayerSlotState.EMPTY) {
continue;
}
final PlayerSlotPane playerSlotPane = new PlayerSlotPane(rootFrame, uiViewport, this.container, i);
this.playerSlots.add(playerSlotPane);
if (i == 0) {
if (usedSlots == 0) {
playerSlotPane.getPlayerSlotFrame()
.addSetPoint(new SetPoint(FramePoint.TOPLEFT, this.container, FramePoint.TOPLEFT, 0, 0));
}
else {
playerSlotPane.getPlayerSlotFrame().addSetPoint(new SetPoint(FramePoint.TOPLEFT,
this.playerSlots.get(i - 1).getPlayerSlotFrame(), FramePoint.BOTTOMLEFT, 0, 0));
this.playerSlots.get(usedSlots - 1).getPlayerSlotFrame(), FramePoint.BOTTOMLEFT, 0, 0));
}
playerSlotPane.setForPlayer(dataSource, rootFrame, uiViewport, player);
usedSlots++;
}
this.container.positionBounds(rootFrame, uiViewport);
}

View File

@ -6,16 +6,25 @@ import java.util.ArrayList;
import java.util.List;
import com.badlogic.gdx.utils.viewport.Viewport;
import com.etheller.warsmash.datasources.DataSource;
import com.etheller.warsmash.parsers.fdf.GameUI;
import com.etheller.warsmash.parsers.fdf.frames.BackdropFrame;
import com.etheller.warsmash.parsers.fdf.frames.CheckBoxFrame;
import com.etheller.warsmash.parsers.fdf.frames.EditBoxFrame;
import com.etheller.warsmash.parsers.fdf.frames.GlueButtonFrame;
import com.etheller.warsmash.parsers.fdf.frames.GlueTextButtonFrame;
import com.etheller.warsmash.parsers.fdf.frames.ListBoxFrame;
import com.etheller.warsmash.parsers.fdf.frames.ListBoxFrame.ListBoxSelelectionListener;
import com.etheller.warsmash.parsers.fdf.frames.ScrollBarFrame;
import com.etheller.warsmash.parsers.fdf.frames.ScrollBarFrame.ScrollBarChangeListener;
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;
import com.etheller.warsmash.viewer5.handlers.w3x.ui.mapsetup.MapListContainer;
import net.warsmash.uberserver.LobbyGameSpeed;
public class BattleNetUI {
private final GameUI rootFrame;
@ -81,8 +90,21 @@ public class BattleNetUI {
private final GlueButtonFrame channelPanelBackButton;
private final EditBoxFrame channelNameField;
private final GlueButtonFrame channelPanelJoinChannelButton;
private final UIFrame battleNetCustomJoinPanel;
private final GlueButtonFrame customJoinPanelBackButton;
private String currentChannel;
private final EditBoxFrame joinGameEditBox;
private final GlueButtonFrame joinGameButton;
private final GlueButtonFrame customJoinPanelCreateGameButton;
private final GlueButtonFrame customJoinPanelLoadGameButton;
private final UIFrame battleNetCustomCreatePanel;
private final GlueButtonFrame customCreatePanelBackButton;
private final ScrollBarFrame createGameSpeedSlider;
private final StringFrame createGameSpeedValue;
private final CheckBoxFrame publicGameRadio;
private final CheckBoxFrame privateGameRadio;
public BattleNetUI(final GameUI rootFrame, final Viewport uiViewport,
public BattleNetUI(final GameUI rootFrame, final Viewport uiViewport, final DataSource dataSource,
final BattleNetUIActionListener actionListener) {
this.rootFrame = rootFrame;
this.uiViewport = uiViewport;
@ -335,6 +357,138 @@ public class BattleNetUI {
if (newAccountPanelNCS != null) {
newAccountPanelNCS.setVisible(false);
}
// *******************************************
// *
// * Battle Net Custom Join Panel
// *
// ******
this.battleNetCustomJoinPanel = rootFrame.createFrame("BattleNetCustomJoinPanel", rootFrame, 0, 0);
this.battleNetCustomJoinPanel.setVisible(false);
this.customJoinPanelBackButton = (GlueButtonFrame) rootFrame.getFrameByName("CancelButton", 0);
this.customJoinPanelBackButton.setOnClick(new Runnable() {
@Override
public void run() {
actionListener.returnToChat();
}
});
this.customJoinPanelCreateGameButton = (GlueButtonFrame) rootFrame.getFrameByName("CreateGameButton", 0);
this.customJoinPanelCreateGameButton.setOnClick(new Runnable() {
@Override
public void run() {
actionListener.showCreateGameMenu();
}
});
this.customJoinPanelLoadGameButton = (GlueButtonFrame) rootFrame.getFrameByName("LoadGameButton", 0);
this.customJoinPanelLoadGameButton.setEnabled(false);
final SimpleFrame joinGameListContainer = (SimpleFrame) this.rootFrame.getFrameByName("JoinGameListContainer",
0);
final ListBoxFrame joinGameListBox = (ListBoxFrame) this.rootFrame.createFrameByType("LISTBOX", "MapListBox",
joinGameListContainer, "WITHCHILDREN", 0);
joinGameListBox.setSetAllPoints(true);
final StringFrame joinGameListLabel = (StringFrame) this.rootFrame.getFrameByName("JoinGameListLabel", 0);
joinGameListBox.setFrameFont(joinGameListLabel.getFrameFont());
this.joinGameEditBox = (EditBoxFrame) this.rootFrame.getFrameByName("JoinGameNameEditBox", 0);
final List<String> testItems = new ArrayList<>();
testItems.add("Retera???'s game (1/4)");
for (final String displayItemPath : testItems) {
joinGameListBox.addItem(displayItemPath, this.rootFrame, this.uiViewport);
}
joinGameListBox.setSelectionListener(new ListBoxSelelectionListener() {
@Override
public void onSelectionChanged(final int newSelectedIndex, final String newSelectedItem) {
if (newSelectedItem != null) {
BattleNetUI.this.joinGameEditBox.setText(newSelectedItem, rootFrame, uiViewport);
}
}
});
joinGameListContainer.add(joinGameListBox);
this.joinGameButton = (GlueButtonFrame) this.rootFrame.getFrameByName("JoinGameButton", 0);
this.joinGameButton.setOnClick(new Runnable() {
@Override
public void run() {
final String text = BattleNetUI.this.joinGameEditBox.getText();
if (text.isEmpty()) {
actionListener.showError("NETERROR_NOGAMESPECIFIED");
}
else {
actionListener.requestJoinGame(text);
}
}
});
// *******************************************
// *
// * Battle Net Custom Create Panel
// *
// ******
this.battleNetCustomCreatePanel = rootFrame.createFrame("BattleNetCustomCreatePanel", rootFrame, 0, 0);
this.battleNetCustomCreatePanel.setVisible(false);
this.customCreatePanelBackButton = (GlueButtonFrame) rootFrame.getFrameByName("CancelButton", 0);
this.customCreatePanelBackButton.setOnClick(new Runnable() {
@Override
public void run() {
actionListener.openCustomGameMenu();
}
});
final StringFrame mapListLabel = (StringFrame) this.rootFrame.getFrameByName("MapListLabel", 0);
final MapListContainer mapListContainer = new MapListContainer(this.rootFrame, this.uiViewport,
"MapListContainer", dataSource, mapListLabel.getFrameFont());
mapListContainer.addSelectionListener(new ListBoxSelelectionListener() {
@Override
public void onSelectionChanged(final int newSelectedIndex, final String newSelectedItem) {
if (newSelectedItem != null) {
}
}
});
this.createGameSpeedValue = (StringFrame) this.rootFrame.getFrameByName("CreateGameSpeedValue", 0);
this.createGameSpeedSlider = (ScrollBarFrame) this.rootFrame.getFrameByName("CreateGameSpeedSlider", 0);
this.createGameSpeedSlider.setChangeListener(new ScrollBarChangeListener() {
@Override
public void onChange(final GameUI gameUI, final Viewport uiViewport, final int newValue) {
if ((newValue >= 0) && (newValue < LobbyGameSpeed.VALUES.length)) {
gameUI.setDecoratedText(BattleNetUI.this.createGameSpeedValue,
LobbyGameSpeed.VALUES[newValue].name());
}
}
});
this.createGameSpeedSlider.setValue(rootFrame, uiViewport, LobbyGameSpeed.NORMAL.ordinal());
this.publicGameRadio = (CheckBoxFrame) this.rootFrame.getFrameByName("PublicGameRadio", 0);
this.privateGameRadio = (CheckBoxFrame) this.rootFrame.getFrameByName("PrivateGameRadio", 0);
this.publicGameRadio.setOnClick(new Runnable() {
@Override
public void run() {
if (BattleNetUI.this.privateGameRadio.isEnabled()) {
BattleNetUI.this.privateGameRadio.setChecked(!BattleNetUI.this.publicGameRadio.isChecked());
}
else {
BattleNetUI.this.publicGameRadio.setChecked(true);
}
}
});
this.privateGameRadio.setOnClick(new Runnable() {
@Override
public void run() {
BattleNetUI.this.publicGameRadio.setChecked(!BattleNetUI.this.privateGameRadio.isChecked());
}
});
this.publicGameRadio.setChecked(true);
this.privateGameRadio.setEnabled(false);
}
public void setTopButtonsVisible(final boolean flag) {
@ -386,7 +540,11 @@ public class BattleNetUI {
}
public void showCustomGameMenu() {
this.battleNetCustomJoinPanel.setVisible(true);
}
public void showCustomGameCreateMenu() {
this.battleNetCustomCreatePanel.setVisible(true);
}
public void hideWelcomeScreen() {
@ -400,6 +558,8 @@ public class BattleNetUI {
this.channelPanel.setVisible(false);
this.welcomePanel.setVisible(false);
this.quitBattleNetButton.setVisible(false);
this.battleNetCustomJoinPanel.setVisible(false);
this.battleNetCustomCreatePanel.setVisible(false);
setTopButtonsVisible(false);
}
@ -431,6 +591,7 @@ public class BattleNetUI {
}
public void joinedChannel(final String channelName) {
this.currentChannel = channelName;
this.rootFrame.setText(this.chatChannelNameLabel, channelName);
final String messageText = String.format(this.rootFrame.getTemplates().getDecoratedString("BNET_JOIN_CHANNEL"),
channelName);
@ -453,4 +614,8 @@ public class BattleNetUI {
public void showChannelMenu() {
this.channelPanel.setVisible(true);
}
public String getCurrentChannel() {
return this.currentChannel;
}
}

View File

@ -22,4 +22,10 @@ public interface BattleNetUIActionListener {
void returnToChat();
void requestJoinChannel(String text);
void requestJoinGame(String text);
void showError(String errorKey);
void showCreateGameMenu();
}

View File

@ -77,7 +77,7 @@ public class DesktopLauncher {
argIndex++;
MultiplayerHack.LP_VAL = Integer.parseInt(arg[argIndex]);
}
else if((arg.length > (argIndex + 1)) && "-ini".equals(arg[argIndex])) {
else if ((arg.length > (argIndex + 1)) && "-ini".equals(arg[argIndex])) {
argIndex++;
iniPath = arg[argIndex];
}
@ -127,9 +127,9 @@ public class DesktopLauncher {
});
}
public static DataTable loadWarsmashIni(String iniPath) {
public static DataTable loadWarsmashIni(final String iniPath) {
final DataTable warsmashIni = new DataTable(StringBundle.EMPTY);
try (FileInputStream warsmashIniInputStream = new FileInputStream(iniPath!=null?iniPath:"warsmash.ini")) {
try (FileInputStream warsmashIniInputStream = new FileInputStream(iniPath != null ? iniPath : "warsmash.ini")) {
warsmashIni.readTXT(warsmashIniInputStream, true);
}
catch (final FileNotFoundException e) {
@ -140,7 +140,8 @@ public class DesktopLauncher {
}
return warsmashIni;
}
public static DataTable loadWarsmashIni(){
public static DataTable loadWarsmashIni() {
return loadWarsmashIni(null);
}
@ -183,8 +184,8 @@ public class DesktopLauncher {
}
};
Extensions.audio = new AudioExtension() {
final FloatBuffer orientation = (FloatBuffer) BufferUtils.createFloatBuffer(6).clear();
final FloatBuffer position = (FloatBuffer) BufferUtils.createFloatBuffer(3).clear();
final FloatBuffer orientation = BufferUtils.createFloatBuffer(6).clear();
final FloatBuffer position = BufferUtils.createFloatBuffer(3).clear();
@Override
public float getDuration(final Sound sound) {

View File

@ -2,6 +2,7 @@ package com.etheller.warsmash.networking.uberserver;
import net.warsmash.nio.channels.WritableOutput;
import net.warsmash.uberserver.GamingNetworkClientToServerListener;
import net.warsmash.uberserver.LobbyGameSpeed;
public class DefaultGamingNetworkServerClientBuilder implements GamingNetworkServerClientBuilder {
private final GamingNetworkServerBusinessLogicImpl businessLogicImpl;
@ -35,6 +36,11 @@ public class DefaultGamingNetworkServerClientBuilder implements GamingNetworkSer
writer);
}
@Override
public void joinGame(final long sessionToken, final String gameName) {
DefaultGamingNetworkServerClientBuilder.this.businessLogicImpl.joinGame(sessionToken, gameName, writer);
}
@Override
public void emoteMessage(final long sessionToken, final String text) {
DefaultGamingNetworkServerClientBuilder.this.businessLogicImpl.emoteMessage(sessionToken, text, writer);
@ -50,6 +56,22 @@ public class DefaultGamingNetworkServerClientBuilder implements GamingNetworkSer
public void chatMessage(final long sessionToken, final String text) {
DefaultGamingNetworkServerClientBuilder.this.businessLogicImpl.chatMessage(sessionToken, text, writer);
}
@Override
public void queryGamesList(final long sessionToken) {
DefaultGamingNetworkServerClientBuilder.this.businessLogicImpl.queryGamesList(sessionToken, writer);
}
@Override
public void queryGameInfo(final long sessionToken, final String gameName) {
DefaultGamingNetworkServerClientBuilder.this.businessLogicImpl.queryGameInfo(sessionToken, writer);
}
@Override
public void createGame(final long sessionToken, final String gameName, final String mapName,
final int totalSlots, final LobbyGameSpeed gameSpeed, final long gameCreationTimeMillis) {
throw new UnsupportedOperationException();
}
};
}

View File

@ -15,6 +15,7 @@ import com.etheller.warsmash.networking.uberserver.users.UserManager;
import net.warsmash.uberserver.AccountCreationFailureReason;
import net.warsmash.uberserver.GamingNetworkServerToClientListener;
import net.warsmash.uberserver.HandshakeDeniedReason;
import net.warsmash.uberserver.JoinGameFailureReason;
import net.warsmash.uberserver.LoginFailureReason;
public class GamingNetworkServerBusinessLogicImpl {
@ -24,6 +25,7 @@ public class GamingNetworkServerBusinessLogicImpl {
private final Map<Integer, SessionImpl> userIdToCurrentSession = new HashMap<>();
private final Map<Long, SessionImpl> tokenToSession;
private final Map<String, ChatChannel> nameLowerCaseToChannel = new HashMap<>();
private final Map<String, HostedGame> nameLowerCaseToGame = new HashMap<>();
private final Random random;
public GamingNetworkServerBusinessLogicImpl(final Set<AcceptedGameListKey> acceptedGames,
@ -107,6 +109,26 @@ public class GamingNetworkServerBusinessLogicImpl {
}
}
public void joinGame(final long sessionToken, final String gameName,
final GamingNetworkServerToClientListener connectionContext) {
final SessionImpl session = getSession(sessionToken, connectionContext);
if (session != null) {
removeSessionFromCurrentChannel(session);
final String gameKey = gameName.toLowerCase(Locale.US);
final HostedGame game = this.nameLowerCaseToGame.get(gameName);
if (game == null) {
connectionContext.joinGameFailed(JoinGameFailureReason.NO_SUCH_GAME);
}
game.addUser(session);
session.currentGameName = gameKey;
connectionContext.joinedGame(gameName);
}
else {
connectionContext.badSession();
}
}
private void removeSessionFromCurrentChannel(final SessionImpl session) {
final String previousChatChannel = session.currentChatChannel;
if (previousChatChannel != null) {
@ -149,6 +171,31 @@ public class GamingNetworkServerBusinessLogicImpl {
}
}
public void queryGamesList(final long sessionToken, final GamingNetworkServerToClientListener connectionContext) {
final SessionImpl session = getSession(sessionToken, connectionContext);
if (session != null) {
connectionContext.beginGamesList();
for (final Map.Entry<String, HostedGame> nameAndGame : this.nameLowerCaseToGame.entrySet()) {
final HostedGame game = nameAndGame.getValue();
connectionContext.gamesListItem(nameAndGame.getKey(), game.getUsedSlots(), game.getTotalSlots());
}
connectionContext.endGamesList();
}
else {
connectionContext.badSession();
}
}
public void queryGameInfo(final long sessionToken, final GamingNetworkServerToClientWriter connectionContext) {
final SessionImpl session = getSession(sessionToken, connectionContext);
if (session != null) {
// TODO
}
else {
connectionContext.badSession();
}
}
private SessionImpl getSession(final long token,
final GamingNetworkServerToClientListener mostRecentConnectionContext) {
final SessionImpl session = this.tokenToSession.get(token);
@ -249,4 +296,58 @@ public class GamingNetworkServerBusinessLogicImpl {
}
}
}
private static final class HostedGame {
private final String gameName;
private final List<SessionImpl> userSessions = new ArrayList<>();
private final int totalSlots;
public HostedGame(final String gameName, final int totalSlots) {
this.gameName = gameName;
this.totalSlots = totalSlots;
}
public void removeUser(final SessionImpl session) {
this.userSessions.remove(session);
}
public void addUser(final SessionImpl session) {
this.userSessions.add(session);
}
public boolean isEmpty() {
return this.userSessions.isEmpty();
}
public int getUsedSlots() {
return this.userSessions.size();
}
public int getTotalSlots() {
return this.totalSlots;
}
public void sendMessage(final String sourceUserName, final String message) {
for (final SessionImpl session : this.userSessions) {
try {
session.mostRecentConnectionContext.channelMessage(sourceUserName, message);
}
catch (final Exception exc) {
exc.printStackTrace();
}
}
}
public void sendEmote(final String sourceUserName, final String message) {
for (final SessionImpl session : this.userSessions) {
try {
session.mostRecentConnectionContext.channelEmote(sourceUserName, message);
}
catch (final Exception exc) {
exc.printStackTrace();
}
}
}
}
}

View File

@ -8,6 +8,7 @@ import net.warsmash.uberserver.AccountCreationFailureReason;
import net.warsmash.uberserver.GamingNetwork;
import net.warsmash.uberserver.GamingNetworkServerToClientListener;
import net.warsmash.uberserver.HandshakeDeniedReason;
import net.warsmash.uberserver.JoinGameFailureReason;
import net.warsmash.uberserver.LoginFailureReason;
public class GamingNetworkServerToClientWriter extends AbstractWriter implements GamingNetworkServerToClientListener {
@ -117,6 +118,51 @@ public class GamingNetworkServerToClientWriter extends AbstractWriter implements
send();
}
@Override
public void beginGamesList() {
beginMessage(Protocol.BEGIN_GAMES_LIST, 0);
send();
}
@Override
public void gamesListItem(String gameName, final int openSlots, final int totalSlots) {
if (gameName.length() > GamingNetwork.CHANNEL_NAME_MAX_LENGTH) {
gameName = gameName.substring(0, GamingNetwork.CHANNEL_NAME_MAX_LENGTH);
}
final byte[] gameNameBytes = gameName.getBytes();
beginMessage(Protocol.GAMES_LIST_ITEM, 4 + gameNameBytes.length + 4 + 4);
this.writeBuffer.putInt(gameNameBytes.length);
this.writeBuffer.put(gameNameBytes);
this.writeBuffer.putInt(openSlots);
this.writeBuffer.putInt(totalSlots);
send();
}
@Override
public void endGamesList() {
beginMessage(Protocol.END_GAMES_LIST, 0);
send();
}
@Override
public void joinedGame(String gameName) {
if (gameName.length() > GamingNetwork.CHANNEL_NAME_MAX_LENGTH) {
gameName = gameName.substring(0, GamingNetwork.CHANNEL_NAME_MAX_LENGTH);
}
final byte[] bytes = gameName.getBytes(Charset.forName("utf-8"));
beginMessage(Protocol.JOINED_GAME, 4 + bytes.length);
this.writeBuffer.putInt(bytes.length);
this.writeBuffer.put(bytes);
send();
}
@Override
public void joinGameFailed(final JoinGameFailureReason joinGameFailureReason) {
beginMessage(Protocol.JOIN_GAME_FAILED, 4);
this.writeBuffer.putInt(joinGameFailureReason.ordinal());
send();
}
@Override
public void disconnected() {
throw new UnsupportedOperationException();

View File

@ -19,10 +19,11 @@ public class TCPGamingNetworkServerClientParser implements TCPClientParser {
@Override
public void parse(final ByteBuffer data) {
while (data.remaining() >= 8) {
final int protocolMessageId = data.getInt(data.position() + 0);
final int length = data.getInt(data.position() + 4);
final int position = data.position();
final int protocolMessageId = data.getInt(position + 0);
final int length = data.getInt(position + 4);
if (data.remaining() >= length) {
data.position(data.position() + 8);
data.position(position + 8);
switch (protocolMessageId) {
case GamingNetworkClientToServerListener.Protocol.HANDSHAKE: {
final int gameIdInt = data.getInt();
@ -60,7 +61,10 @@ public class TCPGamingNetworkServerClientParser implements TCPClientParser {
this.listener.emoteMessage(sessionToken, text);
break;
}
default:
break;
}
data.position(position + length);
}
else {
break;

View File

@ -5,6 +5,7 @@ public class GamingNetwork {
public static final int USERNAME_MAX_LENGTH = 64;
public static final int CHANNEL_NAME_MAX_LENGTH = 128;
public static final int MAP_NAME_MAX_LENGTH = 128;
public static final int PASSWORD_DATA_MAX_LENGTH = 512;
public static final int MESSAGE_MAX_LENGTH = 256;

View File

@ -15,6 +15,15 @@ public interface GamingNetworkClientToServerListener extends DisconnectListener
void emoteMessage(long sessionToken, String text);
void queryGamesList(long sessionToken);
void queryGameInfo(long sessionToken, String gameName);
void joinGame(long sessionToken, String gameName);
void createGame(long sessionToken, String gameName, String mapName, int totalSlots, LobbyGameSpeed gameSpeed,
long gameCreationTimeMillis);
class Protocol {
public static final int HANDSHAKE = 1;
public static final int CREATE_ACCOUNT = 2;
@ -22,5 +31,9 @@ public interface GamingNetworkClientToServerListener extends DisconnectListener
public static final int JOIN_CHANNEL = 4;
public static final int CHAT_MESSAGE = 5;
public static final int EMOTE_MESSAGE = 6;
public static final int QUERY_GAMES_LIST = 7;
public static final int QUERY_GAME_INFO = 8;
public static final int JOIN_GAME = 9;
public static final int CREATE_GAME = 10;
}
}

View File

@ -95,6 +95,61 @@ public class GamingNetworkClientToServerWriter extends AbstractWriter implements
send();
}
@Override
public void queryGamesList(final long sessionToken) {
beginMessage(Protocol.QUERY_GAMES_LIST, 0);
send();
}
@Override
public void queryGameInfo(final long sessionToken, String gameName) {
if (gameName.length() > GamingNetwork.CHANNEL_NAME_MAX_LENGTH) {
gameName = gameName.substring(0, GamingNetwork.CHANNEL_NAME_MAX_LENGTH);
}
final byte[] channelNameBytes = gameName.getBytes(Charset.forName("utf-8"));
beginMessage(Protocol.QUERY_GAME_INFO, 8 + 4 + channelNameBytes.length);
this.writeBuffer.putLong(sessionToken);
this.writeBuffer.putInt(channelNameBytes.length);
this.writeBuffer.put(channelNameBytes);
send();
}
@Override
public void joinGame(final long sessionToken, String gameName) {
if (gameName.length() > GamingNetwork.CHANNEL_NAME_MAX_LENGTH) {
gameName = gameName.substring(0, GamingNetwork.CHANNEL_NAME_MAX_LENGTH);
}
final byte[] channelNameBytes = gameName.getBytes(Charset.forName("utf-8"));
beginMessage(Protocol.JOIN_GAME, 8 + 4 + channelNameBytes.length);
this.writeBuffer.putLong(sessionToken);
this.writeBuffer.putInt(channelNameBytes.length);
this.writeBuffer.put(channelNameBytes);
send();
}
@Override
public void createGame(final long sessionToken, String gameName, String mapName, final int totalSlots,
final LobbyGameSpeed gameSpeed, final long gameCreationTimeMillis) {
if (gameName.length() > GamingNetwork.CHANNEL_NAME_MAX_LENGTH) {
gameName = gameName.substring(0, GamingNetwork.CHANNEL_NAME_MAX_LENGTH);
}
final byte[] channelNameBytes = gameName.getBytes(Charset.forName("utf-8"));
if (mapName.length() > GamingNetwork.MAP_NAME_MAX_LENGTH) {
mapName = mapName.substring(0, GamingNetwork.MAP_NAME_MAX_LENGTH);
}
final byte[] mapNameBytes = mapName.getBytes(Charset.forName("utf-8"));
beginMessage(Protocol.CREATE_GAME, 8 + 4 + channelNameBytes.length + 4 + mapNameBytes.length + 4 + 4 + 8);
this.writeBuffer.putLong(sessionToken);
this.writeBuffer.putInt(channelNameBytes.length);
this.writeBuffer.put(channelNameBytes);
this.writeBuffer.putInt(mapNameBytes.length);
this.writeBuffer.put(mapNameBytes);
this.writeBuffer.putInt(totalSlots);
this.writeBuffer.putInt(gameSpeed.ordinal());
this.writeBuffer.putLong(gameCreationTimeMillis);
send();
}
@Override
public void disconnected() {
throw new UnsupportedOperationException();

View File

@ -26,6 +26,16 @@ public interface GamingNetworkServerToClientListener extends DisconnectListener
void channelEmote(String userName, String message);
void beginGamesList();
void gamesListItem(String gameName, int openSlots, int totalSlots);
void endGamesList();
void joinedGame(String gameName);
void joinGameFailed(JoinGameFailureReason joinGameFailureReason);
class Protocol {
public static final int HANDSHAKE_ACCEPTED = 1;
public static final int HANDSHAKE_DENIED = 2;
@ -37,6 +47,11 @@ public interface GamingNetworkServerToClientListener extends DisconnectListener
public static final int BAD_SESSION = 8;
public static final int CHANNEL_MESSAGE = 9;
public static final int CHANNEL_EMOTE = 10;
public static final int BEGIN_GAMES_LIST = 11;
public static final int GAMES_LIST_ITEM = 12;
public static final int END_GAMES_LIST = 13;
public static final int JOINED_GAME = 14;
public static final int JOIN_GAME_FAILED = 15;
}
public static final class GamingNetworkServerToClientNotifier implements GamingNetworkServerToClientListener {
@ -123,5 +138,40 @@ public interface GamingNetworkServerToClientListener extends DisconnectListener
}
}
@Override
public void beginGamesList() {
for (final GamingNetworkServerToClientListener listener : this.listeners) {
listener.beginGamesList();
}
}
@Override
public void gamesListItem(final String gameName, final int openSlots, final int totalSlots) {
for (final GamingNetworkServerToClientListener listener : this.listeners) {
listener.gamesListItem(gameName, openSlots, totalSlots);
}
}
@Override
public void endGamesList() {
for (final GamingNetworkServerToClientListener listener : this.listeners) {
listener.endGamesList();
}
}
@Override
public void joinedGame(final String gameName) {
for (final GamingNetworkServerToClientListener listener : this.listeners) {
listener.joinedGame(gameName);
}
}
@Override
public void joinGameFailed(final JoinGameFailureReason joinGameFailureReason) {
for (final GamingNetworkServerToClientListener listener : this.listeners) {
listener.joinGameFailed(joinGameFailureReason);
}
}
}
}

View File

@ -0,0 +1,7 @@
package net.warsmash.uberserver;
public enum JoinGameFailureReason {
NO_SUCH_GAME, GAME_FULL, GAME_ALREADY_STARTED;
public static JoinGameFailureReason VALUES[] = values();
}

View File

@ -0,0 +1,7 @@
package net.warsmash.uberserver;
public enum LobbyGameSpeed {
SLOW, NORMAL, FAST;
public static final LobbyGameSpeed VALUES[] = values();
}