LocalPlayer api lua

This commit is contained in:
Vincent Glize 2017-04-08 12:26:45 +02:00 committed by Auke Kok
parent 58d83a7bb2
commit 8ad3dad137
7 changed files with 640 additions and 2 deletions

View File

@ -691,6 +691,8 @@ Call these functions only at load time!
### Player ### Player
* `minetest.get_wielded_item()` * `minetest.get_wielded_item()`
* Returns the itemstack the local player is holding * Returns the itemstack the local player is holding
* `minetest.localplayer`
* returns LocalPlayer handle. See LocalPlayer below.
### Client Environment ### Client Environment
* `minetest.get_player_names()` * `minetest.get_player_names()`
@ -712,7 +714,7 @@ Call these functions only at load time!
* `minetest.write_json(data[, styled])`: returns a string or `nil` and an error message * `minetest.write_json(data[, styled])`: returns a string or `nil` and an error message
* Convert a Lua table into a JSON string * Convert a Lua table into a JSON string
* styled: Outputs in a human-readable format if this is set, defaults to false * styled: Outputs in a human-readable format if this is set, defaults to false
* Unserializable things like functions and userdata will cause an error. * Unserializable things like functions and userdata are saved as null.
* **Warning**: JSON is more strict than the Lua table format. * **Warning**: JSON is more strict than the Lua table format.
1. You can only use strings and positive integers of at least one as keys. 1. You can only use strings and positive integers of at least one as keys.
2. You can not mix string and integer keys. 2. You can not mix string and integer keys.
@ -779,6 +781,118 @@ An interface to manipulate minimap on client UI
* `get_mode()`: returns the current minimap mode * `get_mode()`: returns the current minimap mode
* `toggle_shape()`: toggles minimap shape to round or square. * `toggle_shape()`: toggles minimap shape to round or square.
### LocalPlayer
An interface to retrieve information about the player. The player is
not accessible until the client is fully done loading and therefore
not at module init time.
To get the localplayer handle correctly, use `on_connect()` as follows:
```lua
local localplayer
minetest.register_on_connect(function()
localplayer = minetest.localplayer
end)
```
Methods:
* `get_pos()`
* returns current player current position
* `get_velocity()`
* returns player speed vector
* `get_hp()`
* returns player HP
* `got_teleported()`
* returns true if player was teleported
* `is_attached()`
* returns true if player is attached
* `is_touching_ground()`
* returns true if player touching ground
* `is_in_liquid()`
* returns true if player is in a liquid (This oscillates so that the player jumps a bit above the surface)
* `is_in_liquid_stable()`
* returns true if player is in a stable liquid (This is more stable and defines the maximum speed of the player)
* `get_liquid_viscosity()`
* returns liquid viscosity (Gets the viscosity of liquid to calculate friction)
* `is_climbing()`
* returns true if player is climbing
* `swimming_vertical()`
* returns true if player is swimming in vertical
* `get_physics_override()`
* returns:
```lua
{
speed = float,
jump = float,
gravity = float,
sneak = boolean,
sneak_glitch = boolean
}
```
* `get_override_pos()`
* returns override position
* `get_last_pos()`
* returns last player position before the current client step
* `get_last_velocity()`
* returns last player speed
* `get_breath()`
* returns the player's breath
* `get_look_dir()`
* returns look direction vector
* `get_look_horizontal()`
* returns look horizontal angle
* `get_look_vertical()`
* returns look vertical angle
* `get_eye_pos()`
* returns the player's eye position
* `get_eye_offset()`
* returns the player's eye shift vector
* `get_movement_acceleration()`
* returns acceleration of the player in different environments:
```lua
{
fast = float,
air = float,
default = float,
}
```
* `get_movement_speed()`
* returns player's speed in different environments:
```lua
{
walk = float,
jump = float,
crouch = float,
fast = float,
climb = float,
}
```
* `get_movement()`
* returns player's movement in different environments:
```lua
{
liquid_fluidity = float,
liquid_sink = float,
liquid_fluidity_smooth = float,
gravity = float,
}
```
* `get_last_look_horizontal()`:
* returns last look horizontal angle
* `get_last_look_vertical()`:
* returns last look vertical angle
* `get_key_pressed()`:
* returns last key typed by the player
### Settings ### Settings
An interface to read config files in the format of `minetest.conf`. An interface to read config files in the format of `minetest.conf`.

View File

@ -1865,8 +1865,10 @@ void Client::afterContentReceived(IrrlichtDevice *device)
m_state = LC_Ready; m_state = LC_Ready;
sendReady(); sendReady();
if (g_settings->getBool("enable_client_modding")) if (g_settings->getBool("enable_client_modding")) {
m_script->on_client_ready(m_env.getLocalPlayer());
m_script->on_connect(); m_script->on_connect();
}
text = wgettext("Done!"); text = wgettext("Done!");
draw_load_screen(text, device, guienv, 0, 100); draw_load_screen(text, device, guienv, 0, 100);

View File

@ -29,6 +29,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "lua_api/l_util.h" #include "lua_api/l_util.h"
#include "lua_api/l_item.h" #include "lua_api/l_item.h"
#include "lua_api/l_nodemeta.h" #include "lua_api/l_nodemeta.h"
#include "lua_api/l_localplayer.h"
ClientScripting::ClientScripting(Client *client): ClientScripting::ClientScripting(Client *client):
ScriptApiBase() ScriptApiBase()
@ -69,4 +70,11 @@ void ClientScripting::InitializeModApi(lua_State *L, int top)
StorageRef::Register(L); StorageRef::Register(L);
LuaMinimap::Register(L); LuaMinimap::Register(L);
NodeMetaRef::RegisterClient(L); NodeMetaRef::RegisterClient(L);
LuaLocalPlayer::Register(L);
}
void ClientScripting::on_client_ready(LocalPlayer *localplayer)
{
lua_State *L = getStack();
LuaLocalPlayer::create(L, localplayer);
} }

View File

@ -26,6 +26,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "cpp_api/s_security.h" #include "cpp_api/s_security.h"
class Client; class Client;
class LocalPlayer;
class ClientScripting: class ClientScripting:
virtual public ScriptApiBase, virtual public ScriptApiBase,
public ScriptApiSecurity, public ScriptApiSecurity,
@ -33,6 +34,7 @@ class ClientScripting:
{ {
public: public:
ClientScripting(Client *client); ClientScripting(Client *client);
void on_client_ready(LocalPlayer *localplayer);
private: private:
virtual void InitializeModApi(lua_State *L, int top); virtual void InitializeModApi(lua_State *L, int top);

View File

@ -28,4 +28,5 @@ set(client_SCRIPT_LUA_API_SRCS
${CMAKE_CURRENT_SOURCE_DIR}/l_minimap.cpp ${CMAKE_CURRENT_SOURCE_DIR}/l_minimap.cpp
${CMAKE_CURRENT_SOURCE_DIR}/l_storage.cpp ${CMAKE_CURRENT_SOURCE_DIR}/l_storage.cpp
${CMAKE_CURRENT_SOURCE_DIR}/l_sound.cpp ${CMAKE_CURRENT_SOURCE_DIR}/l_sound.cpp
${CMAKE_CURRENT_SOURCE_DIR}/l_localplayer.cpp
PARENT_SCOPE) PARENT_SCOPE)

View File

@ -0,0 +1,416 @@
/*
Minetest
Copyright (C) 2017 Dumbeldor, Vincent Glize <vincent.glize@live.fr>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include "script/common/c_converter.h"
#include "l_localplayer.h"
#include "l_internal.h"
LuaLocalPlayer::LuaLocalPlayer(LocalPlayer *m)
{
m_localplayer = m;
}
void LuaLocalPlayer::create(lua_State *L, LocalPlayer *m)
{
LuaLocalPlayer *o = new LuaLocalPlayer(m);
*(void **) (lua_newuserdata(L, sizeof(void *))) = o;
luaL_getmetatable(L, className);
lua_setmetatable(L, -2);
// Keep localplayer object stack id
int localplayer_object = lua_gettop(L);
lua_getglobal(L, "core");
luaL_checktype(L, -1, LUA_TTABLE);
int coretable = lua_gettop(L);
lua_pushvalue(L, localplayer_object);
lua_setfield(L, coretable, "localplayer");
}
int LuaLocalPlayer::l_get_velocity(lua_State *L)
{
LocalPlayer *player = getobject(L, 1);
push_v3f(L, player->getSpeed() / BS);
return 1;
}
int LuaLocalPlayer::l_get_hp(lua_State *L)
{
LocalPlayer *player = getobject(L, 1);
lua_pushinteger(L, player->hp);
return 1;
}
int LuaLocalPlayer::l_get_name(lua_State *L)
{
LocalPlayer *player = getobject(L, 1);
lua_pushstring(L, player->getName());
return 1;
}
int LuaLocalPlayer::l_is_teleported(lua_State *L)
{
LocalPlayer *player = getobject(L, 1);
lua_pushboolean(L, player->got_teleported);
return 1;
}
int LuaLocalPlayer::l_is_attached(lua_State *L)
{
LocalPlayer *player = getobject(L, 1);
lua_pushboolean(L, player->isAttached);
return 1;
}
int LuaLocalPlayer::l_is_touching_ground(lua_State *L)
{
LocalPlayer *player = getobject(L, 1);
lua_pushboolean(L, player->touching_ground);
return 1;
}
int LuaLocalPlayer::l_is_in_liquid(lua_State *L)
{
LocalPlayer *player = getobject(L, 1);
lua_pushboolean(L, player->in_liquid);
return 1;
}
int LuaLocalPlayer::l_is_in_liquid_stable(lua_State *L)
{
LocalPlayer *player = getobject(L, 1);
lua_pushboolean(L, player->in_liquid_stable);
return 1;
}
int LuaLocalPlayer::l_get_liquid_viscosity(lua_State *L)
{
LocalPlayer *player = getobject(L, 1);
lua_pushinteger(L, player->liquid_viscosity);
return 1;
}
int LuaLocalPlayer::l_is_climbing(lua_State *L)
{
LocalPlayer *player = getobject(L, 1);
lua_pushboolean(L, player->is_climbing);
return 1;
}
int LuaLocalPlayer::l_swimming_vertical(lua_State *L)
{
LocalPlayer *player = getobject(L, 1);
lua_pushboolean(L, player->swimming_vertical);
return 1;
}
int LuaLocalPlayer::l_get_physics_override(lua_State *L)
{
LocalPlayer *player = getobject(L, 1);
lua_newtable(L);
lua_pushnumber(L, player->physics_override_speed);
lua_setfield(L, -2, "speed");
lua_pushnumber(L, player->physics_override_jump);
lua_setfield(L, -2, "jump");
lua_pushnumber(L, player->physics_override_gravity);
lua_setfield(L, -2, "gravity");
lua_pushboolean(L, player->physics_override_sneak);
lua_setfield(L, -2, "sneak");
lua_pushboolean(L, player->physics_override_sneak_glitch);
lua_setfield(L, -2, "sneak_glitch");
return 1;
}
int LuaLocalPlayer::l_get_override_pos(lua_State *L)
{
LocalPlayer *player = getobject(L, 1);
push_v3f(L, player->overridePosition);
return 1;
}
int LuaLocalPlayer::l_get_last_pos(lua_State *L)
{
LocalPlayer *player = getobject(L, 1);
push_v3f(L, player->last_position / BS);
return 1;
}
int LuaLocalPlayer::l_get_last_velocity(lua_State *L)
{
LocalPlayer *player = getobject(L, 1);
push_v3f(L, player->last_speed);
return 1;
}
int LuaLocalPlayer::l_get_last_look_vertical(lua_State *L)
{
LocalPlayer *player = getobject(L, 1);
lua_pushnumber(L, -1.0 * player->last_pitch * core::DEGTORAD);
return 1;
}
int LuaLocalPlayer::l_get_last_look_horizontal(lua_State *L)
{
LocalPlayer *player = getobject(L, 1);
lua_pushnumber(L, (player->last_yaw + 90.) * core::DEGTORAD);
return 1;
}
int LuaLocalPlayer::l_get_key_pressed(lua_State *L)
{
LocalPlayer *player = getobject(L, 1);
lua_pushinteger(L, player->last_keyPressed);
return 1;
}
int LuaLocalPlayer::l_get_breath(lua_State *L)
{
LocalPlayer *player = getobject(L, 1);
lua_pushinteger(L, player->getBreath());
return 1;
}
int LuaLocalPlayer::l_get_look_dir(lua_State *L)
{
LocalPlayer *player = getobject(L, 1);
float pitch = -1.0 * player->getPitch() * core::DEGTORAD;
float yaw = (player->getYaw() + 90.) * core::DEGTORAD;
v3f v(cos(pitch) * cos(yaw), sin(pitch), cos(pitch) * sin(yaw));
push_v3f(L, v);
return 1;
}
int LuaLocalPlayer::l_get_look_horizontal(lua_State *L)
{
LocalPlayer *player = getobject(L, 1);
lua_pushnumber(L, (player->getYaw() + 90.) * core::DEGTORAD);
return 1;
}
int LuaLocalPlayer::l_get_look_vertical(lua_State *L)
{
LocalPlayer *player = getobject(L, 1);
lua_pushnumber(L, -1.0 * player->getPitch() * core::DEGTORAD);
return 1;
}
int LuaLocalPlayer::l_get_pos(lua_State *L)
{
LocalPlayer *player = getobject(L, 1);
push_v3f(L, player->getPosition() / BS);
return 1;
}
int LuaLocalPlayer::l_get_eye_pos(lua_State *L)
{
LocalPlayer *player = getobject(L, 1);
push_v3f(L, player->getEyePosition());
return 1;
}
int LuaLocalPlayer::l_get_eye_offset(lua_State *L)
{
LocalPlayer *player = getobject(L, 1);
push_v3f(L, player->getEyeOffset());
return 1;
}
int LuaLocalPlayer::l_get_movement_acceleration(lua_State *L)
{
LocalPlayer *player = getobject(L, 1);
lua_newtable(L);
lua_pushnumber(L, player->movement_acceleration_default);
lua_setfield(L, -2, "default");
lua_pushnumber(L, player->movement_acceleration_air);
lua_setfield(L, -2, "air");
lua_pushnumber(L, player->movement_acceleration_fast);
lua_setfield(L, -2, "fast");
return 1;
}
int LuaLocalPlayer::l_get_movement_speed(lua_State *L)
{
LocalPlayer *player = getobject(L, 1);
lua_newtable(L);
lua_pushnumber(L, player->movement_speed_walk);
lua_setfield(L, -2, "walk");
lua_pushnumber(L, player->movement_speed_crouch);
lua_setfield(L, -2, "crouch");
lua_pushnumber(L, player->movement_speed_fast);
lua_setfield(L, -2, "fast");
lua_pushnumber(L, player->movement_speed_climb);
lua_setfield(L, -2, "climb");
lua_pushnumber(L, player->movement_speed_jump);
lua_setfield(L, -2, "jump");
return 1;
}
int LuaLocalPlayer::l_get_movement(lua_State *L)
{
LocalPlayer *player = getobject(L, 1);
lua_newtable(L);
lua_pushnumber(L, player->movement_liquid_fluidity);
lua_setfield(L, -2, "liquid_fluidity");
lua_pushnumber(L, player->movement_liquid_fluidity_smooth);
lua_setfield(L, -2, "liquid_fluidity_smooth");
lua_pushnumber(L, player->movement_liquid_sink);
lua_setfield(L, -2, "liquid_sink");
lua_pushnumber(L, player->movement_gravity);
lua_setfield(L, -2, "gravity");
return 1;
}
LuaLocalPlayer *LuaLocalPlayer::checkobject(lua_State *L, int narg)
{
luaL_checktype(L, narg, LUA_TUSERDATA);
void *ud = luaL_checkudata(L, narg, className);
if (!ud)
luaL_typerror(L, narg, className);
return *(LuaLocalPlayer **) ud;
}
LocalPlayer *LuaLocalPlayer::getobject(LuaLocalPlayer *ref)
{
return ref->m_localplayer;
}
LocalPlayer *LuaLocalPlayer::getobject(lua_State *L, int narg)
{
LuaLocalPlayer *ref = checkobject(L, narg);
assert(ref);
LocalPlayer *player = getobject(ref);
assert(player);
return player;
}
int LuaLocalPlayer::gc_object(lua_State *L)
{
LuaLocalPlayer *o = *(LuaLocalPlayer **) (lua_touserdata(L, 1));
delete o;
return 0;
}
void LuaLocalPlayer::Register(lua_State *L)
{
lua_newtable(L);
int methodtable = lua_gettop(L);
luaL_newmetatable(L, className);
int metatable = lua_gettop(L);
lua_pushliteral(L, "__metatable");
lua_pushvalue(L, methodtable);
lua_settable(L, metatable); // hide metatable from lua getmetatable()
lua_pushliteral(L, "__index");
lua_pushvalue(L, methodtable);
lua_settable(L, metatable);
lua_pushliteral(L, "__gc");
lua_pushcfunction(L, gc_object);
lua_settable(L, metatable);
lua_pop(L, 1); // Drop metatable
luaL_openlib(L, 0, methods, 0); // fill methodtable
lua_pop(L, 1); // Drop methodtable
}
const char LuaLocalPlayer::className[] = "LocalPlayer";
const luaL_reg LuaLocalPlayer::methods[] = {
luamethod(LuaLocalPlayer, get_velocity),
luamethod(LuaLocalPlayer, get_hp),
luamethod(LuaLocalPlayer, get_name),
luamethod(LuaLocalPlayer, is_teleported),
luamethod(LuaLocalPlayer, is_attached),
luamethod(LuaLocalPlayer, is_touching_ground),
luamethod(LuaLocalPlayer, is_in_liquid),
luamethod(LuaLocalPlayer, is_in_liquid_stable),
luamethod(LuaLocalPlayer, get_liquid_viscosity),
luamethod(LuaLocalPlayer, is_climbing),
luamethod(LuaLocalPlayer, swimming_vertical),
luamethod(LuaLocalPlayer, get_physics_override),
luamethod(LuaLocalPlayer, get_override_pos),
luamethod(LuaLocalPlayer, get_last_pos),
luamethod(LuaLocalPlayer, get_last_velocity),
luamethod(LuaLocalPlayer, get_last_look_horizontal),
luamethod(LuaLocalPlayer, get_last_look_vertical),
luamethod(LuaLocalPlayer, get_key_pressed),
luamethod(LuaLocalPlayer, get_breath),
luamethod(LuaLocalPlayer, get_look_dir),
luamethod(LuaLocalPlayer, get_look_horizontal),
luamethod(LuaLocalPlayer, get_look_vertical),
luamethod(LuaLocalPlayer, get_pos),
luamethod(LuaLocalPlayer, get_eye_pos),
luamethod(LuaLocalPlayer, get_eye_offset),
luamethod(LuaLocalPlayer, get_movement_acceleration),
luamethod(LuaLocalPlayer, get_movement_speed),
luamethod(LuaLocalPlayer, get_movement),
{0, 0}
};

View File

@ -0,0 +1,95 @@
/*
Minetest
Copyright (C) 2017 Dumbeldor, Vincent Glize <vincent.glize@live.fr>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef MINETEST_L_LOCALPLAYER_H
#define MINETEST_L_LOCALPLAYER_H
#include "l_base.h"
class LocalPlayer;
class LuaLocalPlayer : public ModApiBase {
private:
static const char className[];
static const luaL_Reg methods[];
// garbage collector
static int gc_object(lua_State *L);
static int l_get_velocity(lua_State *L);
static int l_get_hp(lua_State *L);
static int l_get_name(lua_State *L);
static int l_is_teleported(lua_State *L);
static int l_is_attached(lua_State *L);
static int l_is_touching_ground(lua_State *L);
static int l_is_in_liquid(lua_State *L);
static int l_is_in_liquid_stable(lua_State *L);
static int l_get_liquid_viscosity(lua_State *L);
static int l_is_climbing(lua_State *L);
static int l_swimming_vertical(lua_State *L);
static int l_get_physics_override(lua_State *L);
static int l_get_override_pos(lua_State *L);
static int l_get_last_pos(lua_State *L);
static int l_get_last_velocity(lua_State *L);
static int l_get_last_look_vertical(lua_State *L);
static int l_get_last_look_horizontal(lua_State *L);
static int l_get_key_pressed(lua_State *L);
static int l_get_breath(lua_State *L);
static int l_get_look_dir(lua_State *L);
static int l_get_look_horizontal(lua_State *L);
static int l_get_look_vertical(lua_State *L);
static int l_get_pos(lua_State *L);
static int l_get_eye_pos(lua_State *L);
static int l_get_eye_offset(lua_State *L);
static int l_get_movement_acceleration(lua_State *L);
static int l_get_movement_speed(lua_State *L);
static int l_get_movement(lua_State *L);
LocalPlayer *m_localplayer;
public:
LuaLocalPlayer(LocalPlayer *m);
~LuaLocalPlayer() {}
static void create(lua_State *L, LocalPlayer *m);
static LuaLocalPlayer *checkobject(lua_State *L, int narg);
static LocalPlayer *getobject(LuaLocalPlayer *ref);
static LocalPlayer *getobject(lua_State *L, int narg);
static void Register(lua_State *L);
};
#endif //MINETEST_L_LOCALPLAYER_H