#include "player.h"
#include <cmath>
#include "hud_element.h"
#include "constants.h"
#include "gamedef.h"
#include "client/inputhandler.h"
#include <tuple>
const struct EnumString es_CameraMode[] = {
{CAMERA_MODE_ANY, "any"},
{CAMERA_MODE_FIRST, "first"},
{CAMERA_MODE_THIRD, "third"},
{CAMERA_MODE_THIRD_FRONT, "third_front"},
{0, nullptr}
};
bool is_valid_player_name(std::string_view name)
{
return !name.empty() && name.size() <= PLAYERNAME_SIZE && string_allowed(name, PLAYERNAME_ALLOWED_CHARS);
}
Player::Player(const std::string &name, IItemDefManager *idef):
inventory(idef)
{
m_name = name;
inventory.clear();
inventory.addList("main", PLAYER_INVENTORY_SIZE);
InventoryList *craft = inventory.addList("craft", 9);
craft->setWidth(3);
inventory.addList("craftpreview", 1);
inventory.addList("craftresult", 1);
inventory.setModified(false);
inventory_formspec = "size[8,7.5]"
"list[current_player;main;0,3.5;8,4;]"
"list[current_player;craft;3,0;3,3;]"
"listring[]"
"list[current_player;craftpreview;7,1;1,1;]";
movement_acceleration_default = 3 * BS;
movement_acceleration_air = 2 * BS;
movement_acceleration_fast = 10 * BS;
movement_speed_walk = 4 * BS;
movement_speed_crouch = 1.35 * BS;
movement_speed_fast = 20 * BS;
movement_speed_climb = 2 * BS;
movement_speed_jump = 6.5 * BS;
movement_liquid_fluidity = 1 * BS;
movement_liquid_fluidity_smooth = 0.5 * BS;
movement_liquid_sink = 10 * BS;
movement_gravity = 9.81 * BS;
local_animation_speed = 0.0;
hud_flags =
HUD_FLAG_HOTBAR_VISIBLE | HUD_FLAG_HEALTHBAR_VISIBLE |
HUD_FLAG_CROSSHAIR_VISIBLE | HUD_FLAG_WIELDITEM_VISIBLE |
HUD_FLAG_BREATHBAR_VISIBLE | HUD_FLAG_MINIMAP_VISIBLE |
HUD_FLAG_MINIMAP_RADAR_VISIBLE | HUD_FLAG_BASIC_DEBUG |
HUD_FLAG_CHAT_VISIBLE;
hud_hotbar_itemcount = HUD_HOTBAR_ITEMCOUNT_DEFAULT;
}
Player::~Player()
{
}
void Player::setWieldIndex(u16 index)
{
const InventoryList *mlist = inventory.getList("main");
m_wield_index = MYMIN(index, mlist ? mlist->getSize() : 0);
}
u16 Player::getWieldIndex()
{
return std::min(m_wield_index, getMaxHotbarItemcount());
}
ItemStack &Player::getWieldedItem(ItemStack *selected, ItemStack *hand) const
{
assert(selected);
const InventoryList *mlist = inventory.getList("main");
const InventoryList *hlist = inventory.getList("hand");
if (mlist && m_wield_index < mlist->getSize())
*selected = mlist->getItem(m_wield_index);
if (hand && hlist)
*hand = hlist->getItem(0);
return (hand && selected->name.empty()) ? *hand : *selected;
}
u32 PlayerHud::getFreeID()
{
size_t size = m_elements.size();
for (size_t i = 0; i != size; i++) {
if (!m_elements[i])
return i;
}
return size;
}
u32 PlayerHud::add(std::unique_ptr<HudElement> toadd)
{
u32 id = getFreeID();
if (id < m_elements.size())
m_elements[id] = std::move(toadd);
else
m_elements.push_back(std::move(toadd));
return id;
}
HudElement* PlayerHud::get(u32 id)
{
if (id < m_elements.size())
return m_elements[id].get();
return nullptr;
}
bool PlayerHud::remove(u32 id)
{
bool removed = false;
if (id < m_elements.size()) {
m_elements[id].reset();
removed = true;
}
while (!m_elements.empty() && m_elements.back() == nullptr)
m_elements.pop_back();
return removed;
}
void PlayerHud::clear()
{
m_elements.clear();
}
u16 Player::getMaxHotbarItemcount()
{
InventoryList *mainlist = inventory.getList("main");
return mainlist ? std::min(mainlist->getSize(), (u32) hud_hotbar_itemcount) : 0;
}
void PlayerControl::setMovementFromKeys()
{
float x = right - left;
float y = up - down;
if (x != 0 || y != 0) {
movement_direction = std::atan2(x, y);
movement_speed = std::min(1.0f, sqrtf(x*x + y*y));
}
}
static u32 convert_direction_bit(float angle, float direction, int bit)
{
constexpr float angular_threshold = 3.0f/8.0f * M_PI;
const auto diff = std::abs(angle - direction);
const auto mindiff = std::min<float>(diff, 2*M_PI - diff);
return ((u32)(mindiff <= angular_threshold) << bit);
}
u32 PlayerControl::getKeysPressed() const
{
u32 keypress_bits =
( (u32)(jump & 1) << 4) |
( (u32)(aux1 & 1) << 5) |
( (u32)(sneak & 1) << 6) |
( (u32)(dig & 1) << 7) |
( (u32)(place & 1) << 8) |
( (u32)(zoom & 1) << 9)
;
if (isMoving()) {
keypress_bits |=
convert_direction_bit(movement_direction, 0, 0) |
convert_direction_bit(movement_direction, M_PI, 1) |
convert_direction_bit(movement_direction, -M_PI_2, 2) |
convert_direction_bit(movement_direction, M_PI_2, 3);
}
return keypress_bits;
}
void PlayerControl::unpackKeysPressed(u32 keypress_bits)
{
up = keypress_bits & (1 << 0);
down = keypress_bits & (1 << 1);
left = keypress_bits & (1 << 2);
right = keypress_bits & (1 << 3);
jump = keypress_bits & (1 << 4);
aux1 = keypress_bits & (1 << 5);
sneak = keypress_bits & (1 << 6);
dig = keypress_bits & (1 << 7);
place = keypress_bits & (1 << 8);
zoom = keypress_bits & (1 << 9);
}
v2f PlayerControl::getMovement() const
{
return v2f(std::sin(movement_direction), std::cos(movement_direction)) * movement_speed;
}
static auto tie(const PlayerPhysicsOverride &o)
{
return std::tie(
o.speed, o.jump, o.gravity, o.sneak, o.sneak_glitch, o.new_move, o.speed_climb,
o.speed_crouch, o.liquid_fluidity, o.liquid_fluidity_smooth, o.liquid_sink,
o.acceleration_default, o.acceleration_air, o.speed_fast, o.acceleration_fast,
o.speed_walk
);
}
bool PlayerPhysicsOverride::operator==(const PlayerPhysicsOverride &other) const
{
return tie(*this) == tie(other);
}