Skip to content

Commit

Permalink
UI|Client: Setting up MapOutlineWidget; ServerLink parses outline res…
Browse files Browse the repository at this point in the history
…ponse
  • Loading branch information
skyjake committed Feb 1, 2017
1 parent 5c1fa14 commit 35dcc4d
Show file tree
Hide file tree
Showing 4 changed files with 337 additions and 42 deletions.
47 changes: 47 additions & 0 deletions doomsday/apps/client/include/ui/widgets/mapoutlinewidget.h
@@ -0,0 +1,47 @@
/** @file mapoutlinewidget.h Shows a map outline.
*
* @authors Copyright (c) 2017 Jaakko Keränen <jaakko.keranen@iki.fi>
*
* @par License
* GPL: http://www.gnu.org/licenses/gpl.html
*
* <small>This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. This program is distributed in the hope that it
* will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
* Public License for more details. You should have received a copy of the GNU
* General Public License along with this program; if not, see:
* http://www.gnu.org/licenses</small>
*/

#ifndef DENG_CLIENT_UI_MAPOUTLINEWIDGET_H
#define DENG_CLIENT_UI_MAPOUTLINEWIDGET_H

#include <de/GuiWidget>
#include <de/shell/Protocol>

/**
* Map outline visualizing information from a shell::MapOutlinePacket.
*/
class MapOutlineWidget : public de::GuiWidget
{
public:
MapOutlineWidget(de::String const &name = de::String());

void setOutline(de::shell::MapOutlinePacket const &mapOutline);

// Events.
void viewResized() override;
void drawContent() override;

protected:
void glInit() override;
void glDeinit() override;

private:
DENG2_PRIVATE(d)
};

#endif // DENG_CLIENT_UI_MAPOUTLINEWIDGET_H
49 changes: 38 additions & 11 deletions doomsday/apps/client/src/network/serverlink.cpp
Expand Up @@ -32,6 +32,7 @@

#include <de/BlockPacket>
#include <de/ByteRefArray>
#include <de/ByteSubArray>
#include <de/GuiApp>
#include <de/Message>
#include <de/MessageDialog>
Expand All @@ -49,6 +50,7 @@ enum LinkState
{
None,
Discovering,
QueryingMapOutline,
WaitingForInfoResponse,
Joining,
WaitingForJoinResponse,
Expand Down Expand Up @@ -153,7 +155,27 @@ DENG2_PIMPL(ServerLink)
}
catch (Error const &er)
{
LOG_NET_WARNING("Reply from %s was invalid: %s") << svAddress << er.asText();
LOG_NET_WARNING("Info reply from %s was invalid: %s") << svAddress << er.asText();
}
}
else if (reply.size() >= 11 && reply.startsWith("MapOutline\n"))
{
try
{
shell::MapOutlinePacket outline;
{
Block const data = Block(ByteSubArray(reply, 11)).decompressed();
Reader src(data);
src.withHeader() >> outline;
}
DENG2_FOR_PUBLIC_AUDIENCE2(MapOutline, i)
{
i->mapOutlineReceived(svAddress, outline);
}
}
catch (Error const &er)
{
LOG_NET_WARNING("MapOutline reply from %s was invalid: %s") << svAddress << er.asText();
}
}
else
Expand Down Expand Up @@ -191,10 +213,9 @@ DENG2_PIMPL(ServerLink)
// Call game's NetConnect.
gx.NetConnect(false);

DENG2_FOR_PUBLIC_AUDIENCE(Join, i) i->networkGameJoined();
DENG2_FOR_PUBLIC_AUDIENCE2(Join, i) i->networkGameJoined();

// G'day mate! The client is responsible for beginning the
// handshake.
// G'day mate! The client is responsible for beginning the handshake.
Cl_SendHello();

return true;
Expand Down Expand Up @@ -544,15 +565,20 @@ Packet *ServerLink::interpret(Message const &msg)

void ServerLink::initiateCommunications()
{
if (d->state == Discovering)
switch (d->state)
{
case Discovering:
// Ask for the serverinfo.
*this << ByteRefArray("Info?", 5);
d->state = WaitingForInfoResponse;
break;

case QueryingMapOutline:
*this << ByteRefArray("MapOutline?", 11);
d->state = WaitingForInfoResponse;
}
else if (d->state == Joining)
{
break;

case Joining: {
ClientWindow::main().glActivate();

Demo_StopPlayback();
Expand All @@ -574,10 +600,11 @@ void ServerLink::initiateCommunications()
d->state = WaitingForJoinResponse;

ClientWindow::main().glDone();
}
else
{
break; }

default:
DENG2_ASSERT(false);
break;
}
}

Expand Down
177 changes: 146 additions & 31 deletions doomsday/apps/client/src/ui/dialogs/serverinfodialog.cpp
Expand Up @@ -17,39 +17,77 @@
*/

#include "ui/dialogs/serverinfodialog.h"
#include "ui/dialogs/packageinfodialog.h"
#include "ui/widgets/packageswidget.h"
#include "ui/widgets/homemenuwidget.h"
#include "ui/widgets/mapoutlinewidget.h"
#include "network/serverlink.h"

#include <de/ButtonWidget>
#include <de/SequentialLayout>
#include <de/ui/SubwidgetItem>
#include <de/ProgressWidget>

#include <QTimer>

using namespace de;

DENG_GUI_PIMPL(ServerInfoDialog)
, public PackagesWidget::IPackageStatus
{
// Server info & status.
Address host;
String domainName;
ServerLink link; // querying details from the server
GameProfile profile;
shell::ServerInfo serverInfo;

// Network queries.
ServerLink link; // querying details from the server
QTimer queryTimer; // allow the dialog to open nicely before starting network queries
enum Query
{
QueryNone,
QueryStatus,
QueryMapOutline,
};
Query pendingQuery = QueryNone;

// Widgets.
LabelWidget *title;
LabelWidget *subtitle;
LabelWidget *description;
PackagesWidget *packages = nullptr;
MapOutlineWidget *mapOutline;
ui::ListData packageActions;

Impl(Public *i, shell::ServerInfo const &sv)
: Base(i)
, link(ServerLink::ManualConnectionOnly)
, serverInfo(sv)
, link(ServerLink::ManualConnectionOnly)
{
connect(&queryTimer, &QTimer::timeout, [this] () { beginPendingQuery(); });

self().useInfoStyle();

// The Close button is always available. Other actions are shown depending
// on what kind of package is being displayed.
self().buttons()
<< new DialogButtonItem(Default | Accept, tr("Close"));

packageActions << new ui::SubwidgetItem(tr("..."), ui::Right, [this] () -> PopupWidget *
{
return new PackageInfoDialog(packages->actionPackage());
});

createWidgets();
}

bool isPackageHighlighted(String const &) const
{
// No highlights.
return false;
}

void createWidgets()
{
auto &area = self().area();
Expand All @@ -74,19 +112,43 @@ DENG_GUI_PIMPL(ServerInfoDialog)
description->setTextColor("inverted.text");
description->setTextLineAlignment(ui::AlignLeft);

mapOutline = new MapOutlineWidget;
mapOutline->rule().setInput(Rule::Width, Const(2*4*90));
area.add(mapOutline);

updateLayout();
}

void updateLayout()
{
auto &area = self().area();
SequentialLayout layout(area.contentRule().left(),
area.contentRule().top(),
ui::Down);
layout.setOverrideWidth(Const(2*4*90));
layout << *title << *subtitle << *description;
if (packages)
{
layout << *packages;
}

/*SequentialLayout rightLayout(title->rule().right(),
title->rule().top(),
ui::Down);
rightLayout << *mapOutline;*/

mapOutline->rule()
.setInput(Rule::Height, layout.height())
.setLeftTop(title->rule().right(), title->rule().top());

area.setContentSize(layout.width(), layout.height());
area.setContentSize(layout.width() + mapOutline->rule().width(),
layout.height());
//OperatorRule::maximum(layout.height());
//rightLayout.height()));
}

void updateContent()
void updateContent(bool updatePackages = true)
{
qDebug() << "\n\nupdating with:\n" << serverInfo.asText().toLatin1().constData();

title->setText(serverInfo.name());

// Title and description.
Expand Down Expand Up @@ -125,6 +187,82 @@ DENG_GUI_PIMPL(ServerInfoDialog)
}
description->setText(msg);
}

if (updatePackages && !serverInfo.packages().isEmpty())
{
qDebug() << "updating with packages:" << serverInfo.packages();
if (!packages)
{
packages = new PackagesWidget(serverInfo.packages());
packages->setHiddenTags(StringList()); // show everything
packages->setActionItems(packageActions);
packages->setActionsAlwaysShown(true);
packages->setPackageStatus(*this);
packages->searchTermsEditor().setColorTheme(Inverted);
packages->searchTermsEditor().setFont("small");
packages->searchTermsEditor().setEmptyContentHint(tr("Filter Server Packages"), "editor.hint.small");
packages->searchTermsEditor().margins().setTopBottom("dialog.gap");
packages->setColorTheme(Inverted, Inverted, Inverted, Inverted);
self().area().add(packages);

updateLayout();
}
else
{
packages->setManualPackageIds(serverInfo.packages());
}
}
}

void startQuery(Query query)
{
pendingQuery = query;

queryTimer.stop();
queryTimer.setInterval(500);
queryTimer.setSingleShot(true);
queryTimer.start();
}

void beginPendingQuery()
{
switch (pendingQuery)
{
case QueryStatus:
if (!domainName.isEmpty())
{
// Begin a query for the latest details.
link.acquireServerProfile(domainName, [this] (Address resolvedAddress,
GameProfile const *svProfile)
{
host = resolvedAddress;

qDebug() << "[domain] reply from" << host.asText();
link.foundServerInfo(0, serverInfo);
profile = *svProfile;
updateContent();
});
}
else
{
link.acquireServerProfile(host, [this] (GameProfile const *svProfile)
{
qDebug() << "[ip] reply from" << host.asText();
link.foundServerInfo(0, serverInfo);
profile = *svProfile;
updateContent();
});
}
break;

case QueryMapOutline:
break;

case QueryNone:
break;
}

pendingQuery = QueryNone;
}
};

Expand All @@ -134,30 +272,7 @@ ServerInfoDialog::ServerInfoDialog(shell::ServerInfo const &serverInfo)
d->domainName = serverInfo.domainName();
d->host = serverInfo.address();

d->updateContent();
d->updateContent(false /* don't update packages yet */);

if (!d->domainName.isEmpty())
{
// Begin a query for the latest details.
d->link.acquireServerProfile(d->domainName, [this] (Address resolvedAddress,
GameProfile const *profile)
{
d->host = resolvedAddress;

qDebug() << "[domain] reply from" << d->host.asText();
d->link.foundServerInfo(0, d->serverInfo);
d->profile = *profile;
d->updateContent();
});
}
else
{
d->link.acquireServerProfile(d->host, [this] (GameProfile const *profile)
{
qDebug() << "[ip] reply from" << d->host.asText();
d->link.foundServerInfo(0, d->serverInfo);
d->profile = *profile;
d->updateContent();
});
}
d->startQuery(Impl::QueryStatus);
}

0 comments on commit 35dcc4d

Please sign in to comment.