Compress kart control action

This commit is contained in:
Benau 2018-09-15 14:25:38 +08:00
parent 01b95d873e
commit 4c6d535f00
5 changed files with 70 additions and 29 deletions

View File

@ -335,7 +335,7 @@ void AIBaseController::saveState(BareNetworkString *buffer) const
{
// Endcontroller needs this for proper offset in kart rewinder
// Must match the number of bytes in Playercontroller.
buffer->addUInt32(0).addUInt32(0).addUInt8(0);
buffer->addUInt32(0).addUInt16(0).addUInt8(0);
} // copyToBuffer
//-----------------------------------------------------------------------------
@ -343,5 +343,5 @@ void AIBaseController::rewindTo(BareNetworkString *buffer)
{
// Endcontroller needs this for proper offset in kart rewinder.
// Skip the same number of bytes as PlayerController.
buffer->skip(4 * 2 + 1);
buffer->skip(4 + 2 + 1);
} // rewindTo

View File

@ -171,10 +171,12 @@ bool PlayerController::action(PlayerAction action, int value, bool dry_run)
break;
case PA_ACCEL:
SET_OR_TEST(m_prev_accel, value);
if (value)
{
uint16_t v16 = (uint16_t)value;
SET_OR_TEST(m_prev_accel, v16);
if (v16)
{
SET_OR_TEST_GETTER(Accel, value/32768.0f);
SET_OR_TEST_GETTER(Accel, v16 / 32768.0f);
SET_OR_TEST_GETTER(Brake, false);
SET_OR_TEST_GETTER(Nitro, m_prev_nitro);
}
@ -185,6 +187,7 @@ bool PlayerController::action(PlayerAction action, int value, bool dry_run)
SET_OR_TEST_GETTER(Nitro, false);
}
break;
}
case PA_BRAKE:
SET_OR_TEST(m_prev_brake, value!=0);
// let's consider below that to be a deadzone
@ -374,8 +377,8 @@ void PlayerController::saveState(BareNetworkString *buffer) const
{
// NOTE: when the size changes, the AIBaseController::saveState and
// restore state MUST be adjusted!!
buffer->addUInt32(m_steer_val).addUInt32(m_prev_accel)
.addUInt8(m_prev_brake);
buffer->addUInt32(m_steer_val).addUInt16(m_prev_accel)
.addUInt8((m_prev_brake ? 1 : 0) | (m_prev_nitro ? 2 : 0));
} // copyToBuffer
//-----------------------------------------------------------------------------
@ -384,8 +387,10 @@ void PlayerController::rewindTo(BareNetworkString *buffer)
// NOTE: when the size changes, the AIBaseController::saveState and
// restore state MUST be adjusted!!
m_steer_val = buffer->getUInt32();
m_prev_accel = buffer->getUInt32();
m_prev_brake = buffer->getUInt8();
m_prev_accel = buffer->getUInt16();
uint8_t c = buffer->getUInt8();
m_prev_brake = (c & 1) != 0;
m_prev_nitro = (c & 2) != 0;
} // rewindTo
// ----------------------------------------------------------------------------

View File

@ -29,7 +29,7 @@ class PlayerController : public Controller
friend class KartRewinder;
protected:
int m_steer_val, m_steer_val_l, m_steer_val_r;
int m_prev_accel;
uint16_t m_prev_accel;
bool m_prev_brake;
bool m_prev_nitro;

View File

@ -77,11 +77,17 @@ void GameProtocol::sendActions()
// Clear left-over data from previous frame. This way the network
// string will increase till it reaches maximum size necessary
m_data_to_send->clear();
if (m_all_actions.size() > 255)
{
Log::warn("GameProtocol",
"Too many actions unsent %d.", (int)m_all_actions.size());
m_all_actions.resize(255);
}
m_data_to_send->addUInt8(GP_CONTROLLER_ACTION)
.addUInt8(uint8_t(m_all_actions.size()));
// Add all actions
for (auto a : m_all_actions)
for (auto& a : m_all_actions)
{
if (Network::m_connection_debug)
{
@ -92,8 +98,9 @@ void GameProtocol::sendActions()
}
m_data_to_send->addUInt32(a.m_ticks);
m_data_to_send->addUInt8(a.m_kart_id);
m_data_to_send->addUInt8((uint8_t)(a.m_action)).addUInt32(a.m_value)
.addUInt32(a.m_value_l).addUInt32(a.m_value_r);
const auto& c = compressAction(a);
m_data_to_send->addUInt8(std::get<0>(c)).addUInt16(std::get<1>(c))
.addUInt16(std::get<2>(c)).addUInt16(std::get<3>(c));
} // for a in m_all_actions
// FIXME: for now send reliable
@ -147,12 +154,12 @@ void GameProtocol::controllerAction(int kart_id, PlayerAction action,
a.m_ticks = World::getWorld()->getTicksSinceStart();
m_all_actions.push_back(a);
const auto& c = compressAction(a);
// Store the event in the rewind manager, which is responsible
// for freeing the allocated memory
BareNetworkString *s = new BareNetworkString(4);
s->addUInt8(kart_id).addUInt8(action).addUInt32(value)
.addUInt32(val_l).addUInt32(val_r);
s->addUInt8(kart_id).addUInt8(std::get<0>(c)).addUInt16(std::get<1>(c))
.addUInt16(std::get<2>(c)).addUInt16(std::get<3>(c));
RewindManager::get()->addEvent(this, s, /*confirmed*/true,
World::getWorld()->getTicksSinceStart());
@ -193,19 +200,21 @@ void GameProtocol::handleControllerAction(Event *event)
return;
}
PlayerAction action = (PlayerAction)(data.getUInt8());
int value = data.getUInt32();
int value_l = data.getUInt32();
int value_r = data.getUInt32();
uint8_t w = data.getUInt8();
uint16_t x = data.getUInt16();
uint16_t y = data.getUInt16();
uint16_t z = data.getUInt16();
if (Network::m_connection_debug)
{
const auto& a = decompressAction(w, x, y, z);
Log::verbose("GameProtocol",
"Controller action: %d %d %d %d %d %d",
cur_ticks, kart_id, action, value, value_l, value_r);
cur_ticks, kart_id, std::get<0>(a), std::get<1>(a),
std::get<2>(a), std::get<3>(a));
}
BareNetworkString *s = new BareNetworkString(3);
s->addUInt8(kart_id).addUInt8(action).addUInt32(value)
.addUInt32(value_l).addUInt32(value_r);
s->addUInt8(kart_id).addUInt8(w).addUInt16(x).addUInt16(y)
.addUInt16(z);
RewindManager::get()->addNetworkEvent(this, s, cur_ticks);
}
@ -425,15 +434,19 @@ void GameProtocol::undo(BareNetworkString *buffer)
void GameProtocol::rewind(BareNetworkString *buffer)
{
int kart_id = buffer->getUInt8();
PlayerAction action = PlayerAction(buffer->getUInt8());
int value = buffer->getUInt32();
int value_l = buffer->getUInt32();
int value_r = buffer->getUInt32();
uint8_t w = buffer->getUInt8();
uint16_t x = buffer->getUInt16();
uint16_t y = buffer->getUInt16();
uint16_t z = buffer->getUInt16();
const auto& a = decompressAction(w, x, y, z);
Controller *c = World::getWorld()->getKart(kart_id)->getController();
PlayerController *pc = dynamic_cast<PlayerController*>(c);
// This can be endcontroller when finishing the race
if (pc)
pc->actionFromNetwork(action, value, value_l, value_r);
{
pc->actionFromNetwork(std::get<0>(a), std::get<1>(a), std::get<2>(a),
std::get<3>(a));
}
} // rewind
// ----------------------------------------------------------------------------

View File

@ -26,8 +26,10 @@
#include "utils/cpp2011.hpp"
#include "utils/singleton.hpp"
#include <cstdlib>
#include <map>
#include <vector>
#include <tuple>
class BareNetworkString;
class NetworkString;
@ -75,7 +77,28 @@ private:
static std::weak_ptr<GameProtocol> m_game_protocol;
std::map<STKPeer*, int> m_initial_ticks;
std::map<STKPeer*, double> m_last_adjustments;
// Maximum value of values are only 32768
std::tuple<uint8_t, uint16_t, uint16_t, uint16_t>
compressAction(const Action& a)
{
uint8_t w = (uint8_t)(a.m_action & 63) |
(a.m_value_l > 0 ? 64 : 0) | (a.m_value_r > 0 ? 128 : 0);
uint16_t x = (uint16_t)a.m_value;
uint16_t y = (uint16_t)std::abs(a.m_value_l);
uint16_t z = (uint16_t)std::abs(a.m_value_r);
return std::make_tuple(w, x, y, z);
}
std::tuple<PlayerAction, int, int, int>
decompressAction(uint8_t w, uint16_t x, uint16_t y , uint16_t z)
{
PlayerAction a = (PlayerAction)(w & 63);
int l_sign = ((w >> 6) & 1) != 0 ? 1 : -1;
int r_sign = ((w >> 7) & 1) != 0 ? 1 : -1;
int b = x;
int c = y * l_sign;
int d = z * r_sign;
return std::make_tuple(a, b, c, d);
}
public:
GameProtocol();
virtual ~GameProtocol();