2018-11-03 08:58:25 -07:00
|
|
|
/**
|
|
|
|
* @file
|
|
|
|
*/
|
|
|
|
#include "TestTraze.h"
|
|
|
|
#include "io/Filesystem.h"
|
|
|
|
#include "core/command/Command.h"
|
|
|
|
#include "voxel/MaterialColor.h"
|
|
|
|
#include "voxel/polyvox/Region.h"
|
|
|
|
|
|
|
|
namespace {
|
|
|
|
const int PlayFieldVolume = 0;
|
2018-11-16 13:07:59 -08:00
|
|
|
const int FontSize = 48;
|
2018-11-03 08:58:25 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
TestTraze::TestTraze(const metric::MetricPtr& metric, const io::FilesystemPtr& filesystem, const core::EventBusPtr& eventBus, const core::TimeProviderPtr& timeProvider) :
|
2018-11-20 00:50:55 -08:00
|
|
|
Super(metric, filesystem, eventBus, timeProvider), _protocol(eventBus), _voxelFontRender(FontSize, 4, voxel::VoxelFont::OriginUpperLeft) {
|
2018-11-03 08:58:25 -07:00
|
|
|
init(ORGANISATION, "testtraze");
|
|
|
|
setRenderAxis(false);
|
|
|
|
_eventBus->subscribe<traze::NewGridEvent>(*this);
|
|
|
|
_eventBus->subscribe<traze::NewGamesEvent>(*this);
|
|
|
|
_eventBus->subscribe<traze::PlayerListEvent>(*this);
|
|
|
|
_eventBus->subscribe<traze::TickerEvent>(*this);
|
|
|
|
_eventBus->subscribe<traze::SpawnEvent>(*this);
|
|
|
|
_eventBus->subscribe<traze::BikeEvent>(*this);
|
|
|
|
}
|
|
|
|
|
2018-11-20 00:50:55 -08:00
|
|
|
const std::string& TestTraze::playerName(traze::PlayerId playerId) const {
|
|
|
|
return player(playerId).name;
|
|
|
|
}
|
|
|
|
|
|
|
|
const traze::Player& TestTraze::player(traze::PlayerId playerId) const {
|
|
|
|
for (auto& p : _players) {
|
|
|
|
if (p.id == playerId) {
|
|
|
|
return p;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
static traze::Player player;
|
|
|
|
return player;
|
|
|
|
}
|
|
|
|
|
2018-11-03 08:58:25 -07:00
|
|
|
core::AppState TestTraze::onConstruct() {
|
|
|
|
core::AppState state = Super::onConstruct();
|
|
|
|
core::Var::get("mosquitto_host", "traze.iteratec.de");
|
|
|
|
core::Var::get("mosquitto_port", "1883");
|
|
|
|
_name = core::Var::get("name", "noname_testtraze");
|
|
|
|
core::Command::registerCommand("join", [&] (const core::CmdArgs& args) { _protocol.join(_name->strVal()); });
|
|
|
|
core::Command::registerCommand("bail", [&] (const core::CmdArgs& args) { _protocol.bail(); });
|
|
|
|
core::Command::registerCommand("left", [&] (const core::CmdArgs& args) { _protocol.steer(traze::BikeDirection::W); });
|
|
|
|
core::Command::registerCommand("right", [&] (const core::CmdArgs& args) { _protocol.steer(traze::BikeDirection::E); });
|
|
|
|
core::Command::registerCommand("forward", [&] (const core::CmdArgs& args) { _protocol.steer(traze::BikeDirection::N); });
|
|
|
|
core::Command::registerCommand("backward", [&] (const core::CmdArgs& args) { _protocol.steer(traze::BikeDirection::S); });
|
|
|
|
core::Command::registerCommand("players", [&] (const core::CmdArgs& args) {
|
|
|
|
for (const auto& p : _players) {
|
|
|
|
Log::info("%s", p.name.c_str());
|
|
|
|
}
|
|
|
|
});
|
2018-11-20 00:50:55 -08:00
|
|
|
_messageQueue.construct();
|
2018-11-03 08:58:25 -07:00
|
|
|
return state;
|
|
|
|
}
|
|
|
|
|
|
|
|
core::AppState TestTraze::onInit() {
|
|
|
|
core::AppState state = Super::onInit();
|
|
|
|
if (state != core::AppState::Running) {
|
|
|
|
return state;
|
|
|
|
}
|
|
|
|
if (!voxel::initDefaultMaterialColors()) {
|
|
|
|
Log::error("Failed to initialize the palette data");
|
|
|
|
return core::AppState::InitFailure;
|
|
|
|
}
|
|
|
|
if (!_protocol.init()) {
|
|
|
|
Log::error("Failed to init protocol");
|
|
|
|
return core::AppState::InitFailure;
|
|
|
|
}
|
|
|
|
if (!_rawVolumeRenderer.init()) {
|
|
|
|
Log::error("Failed to initialize the raw volume renderer");
|
|
|
|
return core::AppState::InitFailure;
|
|
|
|
}
|
|
|
|
if (!_rawVolumeRenderer.onResize(glm::ivec2(0), dimension())) {
|
|
|
|
Log::error("Failed to initialize the raw volume renderer");
|
|
|
|
return core::AppState::InitFailure;
|
|
|
|
}
|
2018-11-20 00:50:55 -08:00
|
|
|
if (!_messageQueue.init()) {
|
|
|
|
Log::error("Failed to init message queue");
|
|
|
|
return core::AppState::InitFailure;
|
|
|
|
}
|
2018-11-14 12:55:14 -08:00
|
|
|
if (!_voxelFontRender.init()) {
|
2018-11-03 08:58:25 -07:00
|
|
|
Log::error("Failed to init voxel font");
|
|
|
|
return core::AppState::InitFailure;
|
|
|
|
}
|
|
|
|
|
|
|
|
_camera.setPosition(glm::vec3(0.0f, 50.0f, 84.0f));
|
|
|
|
_logLevelVar->setVal(std::to_string(SDL_LOG_PRIORITY_INFO));
|
|
|
|
Log::init();
|
|
|
|
|
2018-11-16 13:11:04 -08:00
|
|
|
_textCamera.setMode(video::CameraMode::Orthogonal);
|
|
|
|
_textCamera.setNearPlane(-10.0f);
|
|
|
|
_textCamera.setFarPlane(10.0f);
|
|
|
|
_textCamera.init(glm::ivec2(0), dimension());
|
|
|
|
_textCamera.update(0L);
|
|
|
|
|
|
|
|
_voxelFontRender.setViewProjectionMatrix(_textCamera.viewProjectionMatrix());
|
|
|
|
|
2018-11-03 08:58:25 -07:00
|
|
|
return state;
|
|
|
|
}
|
|
|
|
|
|
|
|
void TestTraze::onEvent(const traze::NewGamesEvent& event) {
|
|
|
|
_games = event.get();
|
|
|
|
Log::debug("Got %i games", (int)_games.size());
|
|
|
|
// there are some points were we assume a limited amount of games...
|
|
|
|
if (_games.size() >= UCHAR_MAX) {
|
|
|
|
Log::warn("Too many games found - reducing them");
|
|
|
|
_games.resize(UCHAR_MAX - 1);
|
|
|
|
}
|
|
|
|
// TODO: this doesn't work if the instanceName changed (new game added, old game removed...)
|
|
|
|
if (_games.empty() || _currentGameIndex > (int8_t)_games.size()) {
|
|
|
|
_protocol.unsubscribe();
|
|
|
|
_currentGameIndex = -1;
|
|
|
|
} else if (!_games.empty() && _currentGameIndex == -1) {
|
|
|
|
Log::info("Select first game");
|
|
|
|
_currentGameIndex = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void TestTraze::onEvent(const traze::BikeEvent& event) {
|
2018-11-13 10:48:40 -08:00
|
|
|
const traze::Bike& bike = event.get();
|
|
|
|
Log::debug("Received bike event for player %u", bike.playerId);
|
2018-11-03 08:58:25 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
void TestTraze::onEvent(const traze::TickerEvent& event) {
|
2018-11-13 10:48:40 -08:00
|
|
|
const traze::Ticker& ticker = event.get();
|
2018-11-20 00:50:55 -08:00
|
|
|
const std::string& name = playerName(ticker.fragger);
|
2018-11-13 10:48:40 -08:00
|
|
|
switch (ticker.type) {
|
|
|
|
case traze::TickerType::Frag:
|
2018-11-20 00:50:55 -08:00
|
|
|
_messageQueue.message("%s fragged another player", name.c_str());
|
2018-11-13 10:48:40 -08:00
|
|
|
break;
|
|
|
|
case traze::TickerType::Suicide:
|
2018-11-20 00:50:55 -08:00
|
|
|
_messageQueue.message("%s commited suicide", name.c_str());
|
2018-11-13 10:48:40 -08:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
2018-11-03 08:58:25 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
void TestTraze::onEvent(const traze::SpawnEvent& event) {
|
2018-11-13 10:48:40 -08:00
|
|
|
const glm::ivec2& position = event.get();
|
|
|
|
Log::info("Spawn at position %i:%i", position.x, position.y);
|
2018-11-03 08:58:25 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
void TestTraze::onEvent(const traze::NewGridEvent& event) {
|
|
|
|
voxel::RawVolume* v = event.get();
|
|
|
|
delete _rawVolumeRenderer.setVolume(PlayFieldVolume, v);
|
|
|
|
const glm::mat4& translate = glm::translate(-v->region().getCentre());
|
|
|
|
const glm::mat4& rotateY = glm::rotate(glm::radians(90.0f), glm::vec3(0.0f, 1.0f, 0.0f));
|
|
|
|
const glm::mat4& rotateX = glm::rotate(glm::radians(25.0f), glm::vec3(1.0f, 0.0f, 0.0f));
|
|
|
|
_rawVolumeRenderer.setModelMatrix(PlayFieldVolume, rotateX * rotateY * translate);
|
|
|
|
if (!_rawVolumeRenderer.extract(PlayFieldVolume)) {
|
|
|
|
Log::error("Failed to extract the volume");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void TestTraze::onEvent(const traze::PlayerListEvent& event) {
|
|
|
|
_players = event.get();
|
2018-11-16 11:56:06 -08:00
|
|
|
_maxLength = 200;
|
|
|
|
for (const traze::Player& p : _players) {
|
2018-11-16 13:07:59 -08:00
|
|
|
_maxLength = glm::max(_maxLength, _voxelFontRender.stringWidth(p.name.c_str()) + 60);
|
2018-11-16 11:56:06 -08:00
|
|
|
}
|
2018-11-03 08:58:25 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
core::AppState TestTraze::onRunning() {
|
2018-11-12 12:04:07 -08:00
|
|
|
const int remaining = _eventBus->update(2);
|
2018-11-03 08:58:25 -07:00
|
|
|
if (remaining) {
|
2018-11-12 12:04:07 -08:00
|
|
|
Log::debug("Remaining events in queue: %i", remaining);
|
2018-11-03 08:58:25 -07:00
|
|
|
}
|
|
|
|
core::AppState state = Super::onRunning();
|
2018-11-16 11:56:06 -08:00
|
|
|
if (!_protocol.connected()) {
|
|
|
|
const uint64_t current = lifetimeInSeconds();
|
|
|
|
if (_nextConnectTime < current) {
|
|
|
|
const uint64_t delaySeconds = 3;
|
|
|
|
_nextConnectTime += delaySeconds;
|
|
|
|
_protocol.connect();
|
|
|
|
}
|
|
|
|
} else if (_currentGameIndex != -1) {
|
2018-11-03 08:58:25 -07:00
|
|
|
_protocol.subscribe(_games[_currentGameIndex]);
|
|
|
|
}
|
2018-11-20 00:50:55 -08:00
|
|
|
_messageQueue.update(_deltaFrameMillis);
|
2018-11-03 08:58:25 -07:00
|
|
|
return state;
|
|
|
|
}
|
|
|
|
|
|
|
|
core::AppState TestTraze::onCleanup() {
|
|
|
|
core::AppState state = Super::onCleanup();
|
2018-11-14 12:55:14 -08:00
|
|
|
_voxelFontRender.shutdown();
|
2018-11-03 08:58:25 -07:00
|
|
|
const std::vector<voxel::RawVolume*>& old = _rawVolumeRenderer.shutdown();
|
|
|
|
for (voxel::RawVolume* v : old) {
|
|
|
|
delete v;
|
|
|
|
}
|
|
|
|
_protocol.shutdown();
|
2018-11-20 00:50:55 -08:00
|
|
|
_messageQueue.shutdown();
|
2018-11-03 08:58:25 -07:00
|
|
|
return state;
|
|
|
|
}
|
|
|
|
|
|
|
|
void TestTraze::onRenderUI() {
|
|
|
|
if (ImGui::BeginCombo("GameInfo", _currentGameIndex == -1 ? "" : _games[_currentGameIndex].name.c_str(), 0)) {
|
|
|
|
for (size_t i = 0u; i < (size_t)_games.size(); ++i) {
|
|
|
|
const traze::GameInfo& game = _games[i];
|
|
|
|
const bool selected = _currentGameIndex == (int)i;
|
|
|
|
if (ImGui::Selectable(game.name.c_str(), selected)) {
|
|
|
|
_currentGameIndex = i;
|
|
|
|
}
|
|
|
|
if (selected) {
|
|
|
|
ImGui::SetItemDefaultFocus();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
ImGui::EndCombo();
|
|
|
|
}
|
|
|
|
ImGui::InputVarString("Name", _name);
|
|
|
|
if (!_protocol.joined() && ImGui::Button("Join")) {
|
|
|
|
_protocol.join(_name->strVal());
|
|
|
|
}
|
|
|
|
if (_protocol.joined() && ImGui::Button("Leave")) {
|
|
|
|
_protocol.bail();
|
|
|
|
}
|
2018-11-14 05:38:09 -08:00
|
|
|
ImGui::Checkbox("Render board", &_renderBoard);
|
|
|
|
ImGui::Checkbox("Render player names", &_renderPlayerNames);
|
2018-11-03 08:58:25 -07:00
|
|
|
Super::onRenderUI();
|
|
|
|
}
|
|
|
|
|
|
|
|
void TestTraze::doRender() {
|
2018-11-14 05:38:09 -08:00
|
|
|
if (_renderBoard) {
|
|
|
|
_rawVolumeRenderer.render(_camera);
|
|
|
|
}
|
|
|
|
|
2018-11-20 05:45:58 -08:00
|
|
|
const glm::ivec2& dim = dimension();
|
|
|
|
_voxelFontRender.setModelMatrix(glm::translate(glm::vec3(dim.x / 3, 0.0f, 0.0f)));
|
2018-11-20 00:50:55 -08:00
|
|
|
int messageOffset = 0;
|
|
|
|
_messageQueue.visitMessages([&] (int64_t /*remainingMillis*/, const std::string& msg) {
|
|
|
|
_voxelFontRender.text(glm::ivec3(0.0f, (float)messageOffset, 0.0f), core::Color::White, "%s", msg.c_str());
|
|
|
|
messageOffset += _voxelFontRender.lineHeight();
|
|
|
|
});
|
|
|
|
_voxelFontRender.swapBuffers();
|
|
|
|
_voxelFontRender.render();
|
|
|
|
|
2018-11-16 11:56:06 -08:00
|
|
|
if (!_protocol.connected()) {
|
|
|
|
const char* connecting = "Connecting";
|
|
|
|
const int w = _voxelFontRender.stringWidth(connecting);
|
2018-11-16 13:11:04 -08:00
|
|
|
_voxelFontRender.setModelMatrix(glm::translate(glm::vec3(dim.x / 2 - w / 2, dim.y / 2 - _voxelFontRender.lineHeight() / 2, 0.0f)));
|
2018-11-16 13:07:59 -08:00
|
|
|
const glm::ivec3 pos(0, 0, 0);
|
|
|
|
_voxelFontRender.text(pos, core::Color::Red, "%s", connecting);
|
|
|
|
const int offset = int((_now - _initMillis) / 75);
|
|
|
|
_voxelFontRender.text(glm::ivec3(pos.x + (offset % w), pos.y + _voxelFontRender.lineHeight(), pos.z), core::Color::Red, ".");
|
|
|
|
} else if (_renderPlayerNames) {
|
2018-11-16 13:11:04 -08:00
|
|
|
_voxelFontRender.setModelMatrix(glm::translate(glm::vec3(20.0f, 20.0f, 0.0f)));
|
2018-11-14 12:55:14 -08:00
|
|
|
int yOffset = 0;
|
2018-11-16 13:07:59 -08:00
|
|
|
_voxelFontRender.text(glm::ivec3(0, yOffset, 0), core::Color::White, "Players");
|
2018-11-16 11:56:06 -08:00
|
|
|
yOffset += _voxelFontRender.lineHeight();
|
2018-11-14 12:55:14 -08:00
|
|
|
for (const traze::Player& p : _players) {
|
2018-11-16 13:07:59 -08:00
|
|
|
_voxelFontRender.text(glm::ivec3(0, yOffset, 0), p.color, "* %s", p.name.c_str());
|
|
|
|
_voxelFontRender.text(glm::ivec3(_maxLength, yOffset, 0), p.color, "%i", p.frags);
|
2018-11-16 11:56:06 -08:00
|
|
|
yOffset += _voxelFontRender.lineHeight();
|
2018-11-14 05:38:09 -08:00
|
|
|
}
|
|
|
|
}
|
2018-11-16 11:56:06 -08:00
|
|
|
|
2018-11-16 13:07:59 -08:00
|
|
|
_voxelFontRender.swapBuffers();
|
2018-11-16 11:56:06 -08:00
|
|
|
_voxelFontRender.render();
|
2018-11-03 08:58:25 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
TEST_APP(TestTraze)
|