Scripting WIP

This commit is contained in:
Perttu Ahola 2011-11-11 19:33:17 +02:00
parent ee8b6d3444
commit bfc68d3151
22 changed files with 1212 additions and 187 deletions

@ -94,6 +94,8 @@ configure_file(
)
set(common_SRCS
scriptapi.cpp
script.cpp
log.cpp
content_sao.cpp
mapgen.cpp

@ -23,13 +23,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#define endSceneX(d){d->draw2DLine(v2s32(0,0),v2s32(1,0),\
video::SColor(255,30,30,30));d->endScene();}
#include <irrTypes.h>
#include <vector2d.h>
#include <vector3d.h>
#include <irrMap.h>
#include <irrList.h>
#include <irrArray.h>
#include <aabbox3d.h>
#include "irrlichttypes.h"
#ifndef SERVER
#include <SColor.h>
#include <IMesh.h>
@ -43,26 +38,6 @@ video::SColor(255,30,30,30));d->endScene();}
#include <IGUIElement.h>
#include <IGUIEnvironment.h>
#endif
using namespace irr;
typedef core::vector3df v3f;
typedef core::vector3d<s16> v3s16;
typedef core::vector3d<s32> v3s32;
typedef core::vector2d<f32> v2f;
typedef core::vector2d<s16> v2s16;
typedef core::vector2d<s32> v2s32;
typedef core::vector2d<u32> v2u32;
typedef core::vector2d<f32> v2f32;
#ifdef _MSC_VER
// Windows
typedef unsigned long long u64;
#else
// Posix
#include <stdint.h>
typedef uint64_t u64;
//typedef unsigned long long u64;
#endif
#endif

@ -1264,3 +1264,152 @@ void MobV2CAO::setLooks(const std::string &looks)
selection_size.X);
}
/*
LuaEntityCAO
*/
// Prototype
LuaEntityCAO proto_LuaEntityCAO;
LuaEntityCAO::LuaEntityCAO():
ClientActiveObject(0),
m_selection_box(-BS/3.,0.0,-BS/3., BS/3.,BS*2./3.,BS/3.),
m_node(NULL),
m_position(v3f(0,10*BS,0))
{
ClientActiveObject::registerType(getType(), create);
}
LuaEntityCAO::~LuaEntityCAO()
{
}
ClientActiveObject* LuaEntityCAO::create()
{
return new LuaEntityCAO();
}
void LuaEntityCAO::addToScene(scene::ISceneManager *smgr)
{
if(m_node != NULL)
return;
video::IVideoDriver* driver = smgr->getVideoDriver();
scene::SMesh *mesh = new scene::SMesh();
scene::IMeshBuffer *buf = new scene::SMeshBuffer();
video::SColor c(255,255,255,255);
video::S3DVertex vertices[4] =
{
/*video::S3DVertex(-BS/2,-BS/4,0, 0,0,0, c, 0,1),
video::S3DVertex(BS/2,-BS/4,0, 0,0,0, c, 1,1),
video::S3DVertex(BS/2,BS/4,0, 0,0,0, c, 1,0),
video::S3DVertex(-BS/2,BS/4,0, 0,0,0, c, 0,0),*/
video::S3DVertex(BS/3.,0,0, 0,0,0, c, 0,1),
video::S3DVertex(-BS/3.,0,0, 0,0,0, c, 1,1),
video::S3DVertex(-BS/3.,0+BS*2./3.,0, 0,0,0, c, 1,0),
video::S3DVertex(BS/3.,0+BS*2./3.,0, 0,0,0, c, 0,0),
};
u16 indices[] = {0,1,2,2,3,0};
buf->append(vertices, 4, indices, 6);
// Set material
buf->getMaterial().setFlag(video::EMF_LIGHTING, false);
buf->getMaterial().setFlag(video::EMF_BACK_FACE_CULLING, false);
//buf->getMaterial().setTexture(0, NULL);
// Initialize with the stick texture
buf->getMaterial().setTexture
(0, driver->getTexture(getTexturePath("mese.png").c_str()));
buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false);
buf->getMaterial().setFlag(video::EMF_FOG_ENABLE, true);
buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
// Add to mesh
mesh->addMeshBuffer(buf);
buf->drop();
m_node = smgr->addMeshSceneNode(mesh, NULL);
mesh->drop();
// Set it to use the materials of the meshbuffers directly.
// This is needed for changing the texture in the future
m_node->setReadOnlyMaterials(true);
updateNodePos();
}
void LuaEntityCAO::removeFromScene()
{
if(m_node == NULL)
return;
m_node->remove();
m_node = NULL;
}
void LuaEntityCAO::updateLight(u8 light_at_pos)
{
if(m_node == NULL)
return;
u8 li = decode_light(light_at_pos);
video::SColor color(255,li,li,li);
setMeshVerticesColor(m_node->getMesh(), color);
}
v3s16 LuaEntityCAO::getLightPosition()
{
return floatToInt(m_position, BS);
}
void LuaEntityCAO::updateNodePos()
{
if(m_node == NULL)
return;
m_node->setPosition(m_position);
}
void LuaEntityCAO::step(float dtime, ClientEnvironment *env)
{
if(m_node)
{
/*v3f rot = m_node->getRotation();
rot.Y += dtime * 120;
m_node->setRotation(rot);*/
LocalPlayer *player = env->getLocalPlayer();
assert(player);
v3f rot = m_node->getRotation();
rot.Y = 180.0 - (player->getYaw());
m_node->setRotation(rot);
}
}
void LuaEntityCAO::processMessage(const std::string &data)
{
infostream<<"LuaEntityCAO: Got message"<<std::endl;
std::istringstream is(data, std::ios::binary);
// command
u8 cmd = readU8(is);
if(cmd == 0)
{
// pos
m_position = readV3F1000(is);
updateNodePos();
}
}
void LuaEntityCAO::initialize(const std::string &data)
{
infostream<<"LuaEntityCAO: Got init data"<<std::endl;
{
std::istringstream is(data, std::ios::binary);
// version
u8 version = readU8(is);
// check version
if(version != 0)
return;
// pos
m_position = readV3F1000(is);
}
updateNodePos();
}

@ -376,6 +376,46 @@ private:
Settings *m_properties;
};
/*
LuaEntityCAO
*/
class LuaEntityCAO : public ClientActiveObject
{
public:
LuaEntityCAO();
virtual ~LuaEntityCAO();
u8 getType() const
{
return ACTIVEOBJECT_TYPE_LUAENTITY;
}
static ClientActiveObject* create();
void addToScene(scene::ISceneManager *smgr);
void removeFromScene();
void updateLight(u8 light_at_pos);
v3s16 getLightPosition();
void updateNodePos();
void step(float dtime, ClientEnvironment *env);
void processMessage(const std::string &data);
void initialize(const std::string &data);
core::aabbox3d<f32>* getSelectionBox()
{return &m_selection_box;}
v3f getPosition()
{return m_position;}
private:
core::aabbox3d<f32> m_selection_box;
scene::IMeshSceneNode *m_node;
v3f m_position;
};
#endif

@ -80,16 +80,16 @@ std::string item_craft_get_image_name(const std::string &subname)
}
ServerActiveObject* item_craft_create_object(const std::string &subname,
ServerEnvironment *env, u16 id, v3f pos)
ServerEnvironment *env, v3f pos)
{
if(subname == "rat")
{
ServerActiveObject *obj = new RatSAO(env, id, pos);
ServerActiveObject *obj = new RatSAO(env, pos);
return obj;
}
else if(subname == "firefly")
{
ServerActiveObject *obj = new FireflySAO(env, id, pos);
ServerActiveObject *obj = new FireflySAO(env, pos);
return obj;
}

@ -33,7 +33,7 @@ InventoryItem* item_material_create_cook_result(content_t content);
std::string item_craft_get_image_name(const std::string &subname);
ServerActiveObject* item_craft_create_object(const std::string &subname,
ServerEnvironment *env, u16 id, v3f pos);
ServerEnvironment *env, v3f pos);
s16 item_craft_get_drop_count(const std::string &subname);
bool item_craft_is_cookable(const std::string &subname);
InventoryItem* item_craft_create_cook_result(const std::string &subname);

@ -27,5 +27,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#define ACTIVEOBJECT_TYPE_FIREFLY 5
#define ACTIVEOBJECT_TYPE_MOBV2 6
#define ACTIVEOBJECT_TYPE_LUAENTITY 7
#endif

@ -49,20 +49,20 @@ void accelerate_xz(v3f &speed, v3f target_speed, f32 max_increase)
*/
// Prototype
TestSAO proto_TestSAO(NULL, 0, v3f(0,0,0));
TestSAO proto_TestSAO(NULL, v3f(0,0,0));
TestSAO::TestSAO(ServerEnvironment *env, u16 id, v3f pos):
ServerActiveObject(env, id, pos),
TestSAO::TestSAO(ServerEnvironment *env, v3f pos):
ServerActiveObject(env, pos),
m_timer1(0),
m_age(0)
{
ServerActiveObject::registerType(getType(), create);
}
ServerActiveObject* TestSAO::create(ServerEnvironment *env, u16 id, v3f pos,
ServerActiveObject* TestSAO::create(ServerEnvironment *env, v3f pos,
const std::string &data)
{
return new TestSAO(env, id, pos);
return new TestSAO(env, pos);
}
void TestSAO::step(float dtime, bool send_recommended)
@ -107,11 +107,11 @@ void TestSAO::step(float dtime, bool send_recommended)
*/
// Prototype
ItemSAO proto_ItemSAO(NULL, 0, v3f(0,0,0), "");
ItemSAO proto_ItemSAO(NULL, v3f(0,0,0), "");
ItemSAO::ItemSAO(ServerEnvironment *env, u16 id, v3f pos,
ItemSAO::ItemSAO(ServerEnvironment *env, v3f pos,
const std::string inventorystring):
ServerActiveObject(env, id, pos),
ServerActiveObject(env, pos),
m_inventorystring(inventorystring),
m_speed_f(0,0,0),
m_last_sent_position(0,0,0)
@ -119,7 +119,7 @@ ItemSAO::ItemSAO(ServerEnvironment *env, u16 id, v3f pos,
ServerActiveObject::registerType(getType(), create);
}
ServerActiveObject* ItemSAO::create(ServerEnvironment *env, u16 id, v3f pos,
ServerActiveObject* ItemSAO::create(ServerEnvironment *env, v3f pos,
const std::string &data)
{
std::istringstream is(data, std::ios::binary);
@ -133,7 +133,7 @@ ServerActiveObject* ItemSAO::create(ServerEnvironment *env, u16 id, v3f pos,
std::string inventorystring = deSerializeString(is);
infostream<<"ItemSAO::create(): Creating item \""
<<inventorystring<<"\""<<std::endl;
return new ItemSAO(env, id, pos, inventorystring);
return new ItemSAO(env, pos, inventorystring);
}
void ItemSAO::step(float dtime, bool send_recommended)
@ -260,10 +260,10 @@ void ItemSAO::rightClick(Player *player)
*/
// Prototype
RatSAO proto_RatSAO(NULL, 0, v3f(0,0,0));
RatSAO proto_RatSAO(NULL, v3f(0,0,0));
RatSAO::RatSAO(ServerEnvironment *env, u16 id, v3f pos):
ServerActiveObject(env, id, pos),
RatSAO::RatSAO(ServerEnvironment *env, v3f pos):
ServerActiveObject(env, pos),
m_is_active(false),
m_speed_f(0,0,0)
{
@ -278,7 +278,7 @@ RatSAO::RatSAO(ServerEnvironment *env, u16 id, v3f pos):
m_touching_ground = false;
}
ServerActiveObject* RatSAO::create(ServerEnvironment *env, u16 id, v3f pos,
ServerActiveObject* RatSAO::create(ServerEnvironment *env, v3f pos,
const std::string &data)
{
std::istringstream is(data, std::ios::binary);
@ -289,7 +289,7 @@ ServerActiveObject* RatSAO::create(ServerEnvironment *env, u16 id, v3f pos,
// check if version is supported
if(version != 0)
return NULL;
return new RatSAO(env, id, pos);
return new RatSAO(env, pos);
}
void RatSAO::step(float dtime, bool send_recommended)
@ -447,10 +447,10 @@ InventoryItem* RatSAO::createPickedUpItem()
*/
// Prototype
Oerkki1SAO proto_Oerkki1SAO(NULL, 0, v3f(0,0,0));
Oerkki1SAO proto_Oerkki1SAO(NULL, v3f(0,0,0));
Oerkki1SAO::Oerkki1SAO(ServerEnvironment *env, u16 id, v3f pos):
ServerActiveObject(env, id, pos),
Oerkki1SAO::Oerkki1SAO(ServerEnvironment *env, v3f pos):
ServerActiveObject(env, pos),
m_is_active(false),
m_speed_f(0,0,0)
{
@ -467,7 +467,7 @@ Oerkki1SAO::Oerkki1SAO(ServerEnvironment *env, u16 id, v3f pos):
m_after_jump_timer = 0;
}
ServerActiveObject* Oerkki1SAO::create(ServerEnvironment *env, u16 id, v3f pos,
ServerActiveObject* Oerkki1SAO::create(ServerEnvironment *env, v3f pos,
const std::string &data)
{
std::istringstream is(data, std::ios::binary);
@ -478,7 +478,7 @@ ServerActiveObject* Oerkki1SAO::create(ServerEnvironment *env, u16 id, v3f pos,
// check if version is supported
if(version != 0)
return NULL;
Oerkki1SAO *o = new Oerkki1SAO(env, id, pos);
Oerkki1SAO *o = new Oerkki1SAO(env, pos);
o->m_hp = hp;
return o;
}
@ -739,10 +739,10 @@ void Oerkki1SAO::doDamage(u16 d)
*/
// Prototype
FireflySAO proto_FireflySAO(NULL, 0, v3f(0,0,0));
FireflySAO proto_FireflySAO(NULL, v3f(0,0,0));
FireflySAO::FireflySAO(ServerEnvironment *env, u16 id, v3f pos):
ServerActiveObject(env, id, pos),
FireflySAO::FireflySAO(ServerEnvironment *env, v3f pos):
ServerActiveObject(env, pos),
m_is_active(false),
m_speed_f(0,0,0)
{
@ -757,7 +757,7 @@ FireflySAO::FireflySAO(ServerEnvironment *env, u16 id, v3f pos):
m_touching_ground = false;
}
ServerActiveObject* FireflySAO::create(ServerEnvironment *env, u16 id, v3f pos,
ServerActiveObject* FireflySAO::create(ServerEnvironment *env, v3f pos,
const std::string &data)
{
std::istringstream is(data, std::ios::binary);
@ -768,7 +768,7 @@ ServerActiveObject* FireflySAO::create(ServerEnvironment *env, u16 id, v3f pos,
// check if version is supported
if(version != 0)
return NULL;
return new FireflySAO(env, id, pos);
return new FireflySAO(env, pos);
}
void FireflySAO::step(float dtime, bool send_recommended)
@ -918,11 +918,11 @@ InventoryItem* FireflySAO::createPickedUpItem()
*/
// Prototype
MobV2SAO proto_MobV2SAO(NULL, 0, v3f(0,0,0), NULL);
MobV2SAO proto_MobV2SAO(NULL, v3f(0,0,0), NULL);
MobV2SAO::MobV2SAO(ServerEnvironment *env, u16 id, v3f pos,
MobV2SAO::MobV2SAO(ServerEnvironment *env, v3f pos,
Settings *init_properties):
ServerActiveObject(env, id, pos),
ServerActiveObject(env, pos),
m_move_type("ground_nodes"),
m_speed(0,0,0),
m_last_sent_position(0,0,0),
@ -961,13 +961,13 @@ MobV2SAO::~MobV2SAO()
delete m_properties;
}
ServerActiveObject* MobV2SAO::create(ServerEnvironment *env, u16 id, v3f pos,
ServerActiveObject* MobV2SAO::create(ServerEnvironment *env, v3f pos,
const std::string &data)
{
std::istringstream is(data, std::ios::binary);
Settings properties;
properties.parseConfigLines(is, "MobArgsEnd");
MobV2SAO *o = new MobV2SAO(env, id, pos, &properties);
MobV2SAO *o = new MobV2SAO(env, pos, &properties);
return o;
}
@ -1174,7 +1174,7 @@ void MobV2SAO::step(float dtime, bool send_recommended)
properties.set("player_hit_damage", "9");
properties.set("player_hit_distance", "2");
properties.set("player_hit_interval", "1");
ServerActiveObject *obj = new MobV2SAO(m_env, 0,
ServerActiveObject *obj = new MobV2SAO(m_env,
pos, &properties);
//m_env->addActiveObjectAsStatic(obj);
m_env->addActiveObject(obj);
@ -1490,3 +1490,95 @@ void MobV2SAO::doDamage(u16 d)
}
/*
LuaEntitySAO
*/
#include "scriptapi.h"
// Prototype
LuaEntitySAO proto_LuaEntitySAO(NULL, v3f(0,0,0), "_prototype", "");
LuaEntitySAO::LuaEntitySAO(ServerEnvironment *env, v3f pos,
const std::string &name, const std::string &state):
ServerActiveObject(env, pos),
m_init_name(name),
m_init_state(state),
m_registered(false)
{
if(env == NULL){
ServerActiveObject::registerType(getType(), create);
return;
}
}
LuaEntitySAO::~LuaEntitySAO()
{
if(m_registered){
lua_State *L = m_env->getLua();
scriptapi_luaentity_deregister(L, m_id);
}
}
void LuaEntitySAO::addedToEnvironment(u16 id)
{
ServerActiveObject::addedToEnvironment(id);
// Create entity by name and state
m_registered = true;
lua_State *L = m_env->getLua();
scriptapi_luaentity_register(L, id, m_init_name.c_str(), m_init_state.c_str());
}
ServerActiveObject* LuaEntitySAO::create(ServerEnvironment *env, v3f pos,
const std::string &data)
{
std::istringstream is(data, std::ios::binary);
// read version
u8 version = readU8(is);
// check if version is supported
if(version != 0)
return NULL;
// read name
std::string name = deSerializeString(is);
// read state
std::string state = deSerializeLongString(is);
// create object
infostream<<"LuaEntitySAO::create(name=\""<<name<<"\" state=\""
<<state<<"\")"<<std::endl;
return new LuaEntitySAO(env, pos, name, state);
}
void LuaEntitySAO::step(float dtime, bool send_recommended)
{
if(m_registered){
lua_State *L = m_env->getLua();
scriptapi_luaentity_step(L, m_id, dtime, send_recommended);
}
}
std::string LuaEntitySAO::getClientInitializationData()
{
std::ostringstream os(std::ios::binary);
// version
writeU8(os, 0);
// pos
writeV3F1000(os, m_base_position);
return os.str();
}
std::string LuaEntitySAO::getStaticData()
{
infostream<<__FUNCTION_NAME<<std::endl;
std::ostringstream os(std::ios::binary);
// version
writeU8(os, 0);
// name
os<<serializeString(m_init_name);
// state
std::string state = scriptapi_luaentity_get_state(L, m_id);
os<<serializeString(state);
return os.str();
}

@ -26,10 +26,10 @@ with this program; if not, write to the Free Software Foundation, Inc.,
class TestSAO : public ServerActiveObject
{
public:
TestSAO(ServerEnvironment *env, u16 id, v3f pos);
TestSAO(ServerEnvironment *env, v3f pos);
u8 getType() const
{return ACTIVEOBJECT_TYPE_TEST;}
static ServerActiveObject* create(ServerEnvironment *env, u16 id, v3f pos,
static ServerActiveObject* create(ServerEnvironment *env, v3f pos,
const std::string &data);
void step(float dtime, bool send_recommended);
private:
@ -40,11 +40,11 @@ private:
class ItemSAO : public ServerActiveObject
{
public:
ItemSAO(ServerEnvironment *env, u16 id, v3f pos,
ItemSAO(ServerEnvironment *env, v3f pos,
const std::string inventorystring);
u8 getType() const
{return ACTIVEOBJECT_TYPE_ITEM;}
static ServerActiveObject* create(ServerEnvironment *env, u16 id, v3f pos,
static ServerActiveObject* create(ServerEnvironment *env, v3f pos,
const std::string &data);
void step(float dtime, bool send_recommended);
std::string getClientInitializationData();
@ -62,10 +62,10 @@ private:
class RatSAO : public ServerActiveObject
{
public:
RatSAO(ServerEnvironment *env, u16 id, v3f pos);
RatSAO(ServerEnvironment *env, v3f pos);
u8 getType() const
{return ACTIVEOBJECT_TYPE_RAT;}
static ServerActiveObject* create(ServerEnvironment *env, u16 id, v3f pos,
static ServerActiveObject* create(ServerEnvironment *env, v3f pos,
const std::string &data);
void step(float dtime, bool send_recommended);
std::string getClientInitializationData();
@ -87,10 +87,10 @@ private:
class Oerkki1SAO : public ServerActiveObject
{
public:
Oerkki1SAO(ServerEnvironment *env, u16 id, v3f pos);
Oerkki1SAO(ServerEnvironment *env, v3f pos);
u8 getType() const
{return ACTIVEOBJECT_TYPE_OERKKI1;}
static ServerActiveObject* create(ServerEnvironment *env, u16 id, v3f pos,
static ServerActiveObject* create(ServerEnvironment *env, v3f pos,
const std::string &data);
void step(float dtime, bool send_recommended);
std::string getClientInitializationData();
@ -119,10 +119,10 @@ private:
class FireflySAO : public ServerActiveObject
{
public:
FireflySAO(ServerEnvironment *env, u16 id, v3f pos);
FireflySAO(ServerEnvironment *env, v3f pos);
u8 getType() const
{return ACTIVEOBJECT_TYPE_FIREFLY;}
static ServerActiveObject* create(ServerEnvironment *env, u16 id, v3f pos,
static ServerActiveObject* create(ServerEnvironment *env, v3f pos,
const std::string &data);
void step(float dtime, bool send_recommended);
std::string getClientInitializationData();
@ -146,12 +146,12 @@ class Settings;
class MobV2SAO : public ServerActiveObject
{
public:
MobV2SAO(ServerEnvironment *env, u16 id, v3f pos,
MobV2SAO(ServerEnvironment *env, v3f pos,
Settings *init_properties);
virtual ~MobV2SAO();
u8 getType() const
{return ACTIVEOBJECT_TYPE_MOBV2;}
static ServerActiveObject* create(ServerEnvironment *env, u16 id, v3f pos,
static ServerActiveObject* create(ServerEnvironment *env, v3f pos,
const std::string &data);
std::string getStaticData();
std::string getClientInitializationData();
@ -195,5 +195,27 @@ private:
Settings *m_properties;
};
struct LuaState;
class LuaEntitySAO : public ServerActiveObject
{
public:
LuaEntitySAO(ServerEnvironment *env, v3f pos,
const std::string &name, const std::string &state);
~LuaEntitySAO();
u8 getType() const
{return ACTIVEOBJECT_TYPE_LUAENTITY;}
virtual void addedToEnvironment(u16 id);
static ServerActiveObject* create(ServerEnvironment *env, v3f pos,
const std::string &data);
void step(float dtime, bool send_recommended);
std::string getClientInitializationData();
std::string getStaticData();
private:
std::string m_init_name;
std::string m_init_state;
bool m_registered;
};
#endif

@ -29,6 +29,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "settings.h"
#include "log.h"
#include "profiler.h"
#include "scriptapi.h"
#define PP(x) "("<<(x).X<<","<<(x).Y<<","<<(x).Z<<")"
@ -267,9 +268,9 @@ void ActiveBlockList::update(core::list<v3s16> &active_positions,
ServerEnvironment
*/
ServerEnvironment::ServerEnvironment(ServerMap *map, Server *server):
ServerEnvironment::ServerEnvironment(ServerMap *map, lua_State *L):
m_map(map),
m_server(server),
m_lua(L),
m_random_spawn_timer(3),
m_send_recommended_timer(0),
m_game_time(0),
@ -674,6 +675,8 @@ void ServerEnvironment::clearAllObjects()
obj->m_removed = true;
continue;
}
// Deregister in scripting api
scriptapi_rm_object_reference(m_lua, obj);
// Delete active object
delete obj;
// Id to be removed from m_active_objects
@ -1043,7 +1046,7 @@ void ServerEnvironment::step(float dtime)
n1.getContent() == CONTENT_AIR)
{
v3f pos = intToFloat(p1, BS);
ServerActiveObject *obj = new RatSAO(this, 0, pos);
ServerActiveObject *obj = new RatSAO(this, pos);
addActiveObject(obj);
}
}
@ -1071,21 +1074,21 @@ void ServerEnvironment::step(float dtime)
Settings properties;
getMob_dungeon_master(properties);
ServerActiveObject *obj = new MobV2SAO(
this, 0, pos, &properties);
this, pos, &properties);
addActiveObject(obj);
} else if(i == 2 || i == 3){
actionstream<<"Rats spawn at "
<<PP(p1)<<std::endl;
for(int j=0; j<3; j++){
ServerActiveObject *obj = new RatSAO(
this, 0, pos);
this, pos);
addActiveObject(obj);
}
} else {
actionstream<<"An oerkki spawns at "
<<PP(p1)<<std::endl;
ServerActiveObject *obj = new Oerkki1SAO(
this, 0, pos);
this, pos);
addActiveObject(obj);
}
}
@ -1228,18 +1231,18 @@ void ServerEnvironment::step(float dtime)
Create a ServerActiveObject
*/
//TestSAO *obj = new TestSAO(this, 0, pos);
//ServerActiveObject *obj = new ItemSAO(this, 0, pos, "CraftItem Stick 1");
//ServerActiveObject *obj = new RatSAO(this, 0, pos);
//ServerActiveObject *obj = new Oerkki1SAO(this, 0, pos);
//ServerActiveObject *obj = new FireflySAO(this, 0, pos);
//TestSAO *obj = new TestSAO(this, pos);
//ServerActiveObject *obj = new ItemSAO(this, pos, "CraftItem Stick 1");
//ServerActiveObject *obj = new RatSAO(this, pos);
//ServerActiveObject *obj = new Oerkki1SAO(this, pos);
//ServerActiveObject *obj = new FireflySAO(this, pos);
infostream<<"Server: Spawning MobV2SAO at "
<<"("<<pos.X<<","<<pos.Y<<","<<pos.Z<<")"<<std::endl;
Settings properties;
getMob_dungeon_master(properties);
ServerActiveObject *obj = new MobV2SAO(this, 0, pos, &properties);
ServerActiveObject *obj = new MobV2SAO(this, pos, &properties);
addActiveObject(obj);
}
#endif
@ -1493,6 +1496,11 @@ u16 ServerEnvironment::addActiveObjectRaw(ServerActiveObject *object,
<<"could not find block for storing id="<<object->getId()
<<" statically"<<std::endl;
}
// Post-initialize object
object->addedToEnvironment(object->getId());
// Register reference in scripting api
scriptapi_add_object_reference(m_lua, object);
return object->getId();
}
@ -1544,6 +1552,9 @@ void ServerEnvironment::removeRemovedObjects()
if(obj->m_known_by_count > 0)
continue;
// Deregister in scripting api
scriptapi_rm_object_reference(m_lua, obj);
// Delete
delete obj;
// Id to be removed from m_active_objects
@ -1815,6 +1826,10 @@ void ServerEnvironment::deactivateFarObjects(bool force_delete)
verbosestream<<"ServerEnvironment::deactivateFarObjects(): "
<<"object id="<<id<<" is not known by clients"
<<"; deleting"<<std::endl;
// Deregister in scripting api
scriptapi_rm_object_reference(m_lua, obj);
// Delete active object
delete obj;
// Id to be removed from m_active_objects

@ -41,6 +41,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
class Server;
class ActiveBlockModifier;
class ServerActiveObject;
typedef struct lua_State lua_State;
class Environment
{
@ -126,7 +127,7 @@ private:
class ServerEnvironment : public Environment
{
public:
ServerEnvironment(ServerMap *map, Server *server);
ServerEnvironment(ServerMap *map, lua_State *L);
~ServerEnvironment();
Map & getMap()
@ -139,13 +140,11 @@ public:
return *m_map;
}
Server * getServer()
lua_State* getLua()
{
return m_server;
return m_lua;
}
void step(f32 dtime);
/*
Save players
*/
@ -222,7 +221,9 @@ public:
// Clear all objects, loading and going through every MapBlock
void clearAllObjects();
void step(f32 dtime);
private:
/*
@ -269,8 +270,8 @@ private:
// The map
ServerMap *m_map;
// Pointer to server (which is handling this environment)
Server *m_server;
// Lua state
lua_State *m_lua;
// Active object list
core::map<u16, ServerActiveObject*> m_active_objects;
// Outgoing network message buffer for active objects

@ -136,7 +136,7 @@ ServerActiveObject* InventoryItem::createSAO(ServerEnvironment *env, u16 id, v3f
Create an ItemSAO
*/
// Create object
ServerActiveObject *obj = new ItemSAO(env, 0, pos, getItemString());
ServerActiveObject *obj = new ItemSAO(env, pos, getItemString());
return obj;
}
@ -174,7 +174,7 @@ video::ITexture * CraftItem::getImage() const
ServerActiveObject* CraftItem::createSAO(ServerEnvironment *env, u16 id, v3f pos)
{
// Special cases
ServerActiveObject *obj = item_craft_create_object(m_subname, env, id, pos);
ServerActiveObject *obj = item_craft_create_object(m_subname, env, pos);
if(obj)
return obj;
// Default

52
src/irrlichttypes.h Normal file

@ -0,0 +1,52 @@
/*
Minetest-c55
Copyright (C) 2010-2011 celeron55, Perttu Ahola <celeron55@gmail.com>
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, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef IRRLICHTTYPES_HEADER
#define IRRLICHTTYPES_HEADER
#include <irrTypes.h>
#include <vector2d.h>
#include <vector3d.h>
#include <irrMap.h>
#include <irrList.h>
#include <irrArray.h>
#include <aabbox3d.h>
using namespace irr;
typedef core::vector3df v3f;
typedef core::vector3d<s16> v3s16;
typedef core::vector3d<s32> v3s32;
typedef core::vector2d<f32> v2f;
typedef core::vector2d<s16> v2s16;
typedef core::vector2d<s32> v2s32;
typedef core::vector2d<u32> v2u32;
typedef core::vector2d<f32> v2f32;
#ifdef _MSC_VER
// Windows
typedef unsigned long long u64;
#else
// Posix
#include <stdint.h>
typedef uint64_t u64;
//typedef unsigned long long u64;
#endif
#endif

@ -56,9 +56,10 @@ void sigint_handler(int sig)
dstream<<DTIME<<"INFO: sigint_handler(): "
<<"Ctrl-C pressed, shutting down."<<std::endl;
dstream<<DTIME<<"INFO: sigint_handler(): "
// Comment out for less clutter when testing scripts
/*dstream<<DTIME<<"INFO: sigint_handler(): "
<<"Printing debug stacks"<<std::endl;
debug_stacks_print();
debug_stacks_print();*/
g_killed = true;
}
@ -91,9 +92,10 @@ void signal_handler_init(void)
{
dstream<<DTIME<<"INFO: event_handler(): "
<<"Ctrl+C, Close Event, Logoff Event or Shutdown Event, shutting down."<<std::endl;
dstream<<DTIME<<"INFO: event_handler(): "
// Comment out for less clutter when testing scripts
/*dstream<<DTIME<<"INFO: event_handler(): "
<<"Printing debug stacks"<<std::endl;
debug_stacks_print();
debug_stacks_print();*/
g_killed = true;
}

130
src/script.cpp Normal file

@ -0,0 +1,130 @@
/*
Minetest-c55
Copyright (C) 2011 celeron55, Perttu Ahola <celeron55@gmail.com>
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, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include "script.h"
#include <cstdarg>
#include <cstring>
#include <cstdio>
#include <cstdlib>
#include "log.h"
#include <iostream>
extern "C" {
#include <lua.h>
#include <lualib.h>
#include <lauxlib.h>
}
void script_error(lua_State *L, const char *fmt, ...)
{
va_list argp;
va_start(argp, fmt);
vfprintf(stderr, fmt, argp);
va_end(argp);
lua_close(L);
exit(EXIT_FAILURE);
}
void script_call_va(lua_State *L, const char *func, const char *sig, ...)
{
va_list vl;
int narg, nres; /* number of arguments and results */
va_start(vl, sig);
lua_getglobal(L, func); /* push function */
for (narg = 0; *sig; narg++) {
/* repeat for each argument */
/* check stack space */
luaL_checkstack(L, 1, "too many arguments");
switch (*sig++) {
case 'd': /* double argument */
lua_pushnumber(L, va_arg(vl, double));
break;
case 'i': /* int argument */
lua_pushinteger(L, va_arg(vl, int));
break;
case 's': /* string argument */
lua_pushstring(L, va_arg(vl, char *));
break;
case '>': /* end of arguments */
goto endargs;
default:
script_error(L, "invalid option (%c)", *(sig - 1));
}
}
endargs:
nres = strlen(sig); /* number of expected results */
if (lua_pcall(L, narg, nres, 0) != 0) /* do the call */
script_error(L, "error calling '%s': %s", func, lua_tostring(L, -1));
nres = -nres; /* stack index of first result */
while (*sig) { /* repeat for each result */
switch (*sig++) {
case 'd': /* double result */
if (!lua_isnumber(L, nres))
script_error(L, "wrong result type");
*va_arg(vl, double *) = lua_tonumber(L, nres);
break;
case 'i': /* int result */
if (!lua_isnumber(L, nres))
script_error(L, "wrong result type");
*va_arg(vl, int *) = lua_tointeger(L, nres);
break;
case 's': /* string result */
if (!lua_isstring(L, nres))
script_error(L, "wrong result type");
*va_arg(vl, const char **) = lua_tostring(L, nres);
break;
default:
script_error(L, "invalid option (%c)", *(sig - 1));
}
nres++;
}
va_end(vl);
}
bool script_load(lua_State *L, const char *path)
{
infostream<<"Loading and running script from "<<path<<std::endl;
int ret = luaL_loadfile(L, path) || lua_pcall(L, 0, 0, 0);
if(ret){
errorstream<<"Failed to load and run script from "<<path<<": "<<lua_tostring(L, -1)<<std::endl;
lua_pop(L, 1); // Pop error message from stack
return false;
}
return true;
}
lua_State* script_init()
{
lua_State *L = luaL_newstate();
luaL_openlibs(L);
return L;
}
lua_State* script_deinit(lua_State *L)
{
lua_close(L);
}

33
src/script.h Normal file

@ -0,0 +1,33 @@
/*
Minetest-c55
Copyright (C) 2011 celeron55, Perttu Ahola <celeron55@gmail.com>
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, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef SCRIPT_HEADER
#define SCRIPT_HEADER
typedef struct lua_State lua_State;
//#include <string>
lua_State* script_init();
lua_State* script_deinit(lua_State *L);
void script_error(lua_State *L, const char *fmt, ...);
void script_call_va(lua_State *L, const char *func, const char *sig, ...);
bool script_load(lua_State *L, const char *path);
#endif

422
src/scriptapi.cpp Normal file

@ -0,0 +1,422 @@
/*
Minetest-c55
Copyright (C) 2011 celeron55, Perttu Ahola <celeron55@gmail.com>
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, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include "scriptapi.h"
#include <iostream>
extern "C" {
#include <lua.h>
#include <lualib.h>
#include <lauxlib.h>
}
#include "log.h"
#include "server.h"
#include "porting.h"
#include "filesys.h"
#include "serverobject.h"
#include "script.h"
//#include "luna.h"
static void stackDump(lua_State *L, std::ostream &o)
{
int i;
int top = lua_gettop(L);
for (i = 1; i <= top; i++) { /* repeat for each level */
int t = lua_type(L, i);
switch (t) {
case LUA_TSTRING: /* strings */
o<<"\""<<lua_tostring(L, i)<<"\"";
break;
case LUA_TBOOLEAN: /* booleans */
o<<(lua_toboolean(L, i) ? "true" : "false");
break;
case LUA_TNUMBER: /* numbers */ {
char buf[10];
snprintf(buf, 10, "%g", lua_tonumber(L, i));
o<<buf;
break; }
default: /* other values */
o<<lua_typename(L, t);
break;
}
o<<" ";
}
o<<std::endl;
}
static void realitycheck(lua_State *L)
{
int top = lua_gettop(L);
if(top >= 30){
dstream<<"Stack is over 30:"<<std::endl;
stackDump(L, dstream);
script_error(L, "Stack is over 30 (reality check)");
}
}
// Register new object prototype (must be based on entity)
static int l_register_object(lua_State *L)
{
const char *name = luaL_checkstring(L, 1);
luaL_checkany(L, 2);
infostream<<"register_object: "<<name<<std::endl;
// Get the minetest table
lua_getglobal(L, "minetest");
// Get field "registered_objects"
lua_getfield(L, -1, "registered_objects");
luaL_checktype(L, -1, LUA_TTABLE);
int objectstable = lua_gettop(L);
// Object is in param 2
lua_pushvalue(L, 2); // Copy object to top of stack
lua_setfield(L, objectstable, name); // registered_objects[name] = object
return 0; /* number of results */
}
static int l_new_entity(lua_State *L)
{
/* o = o or {}
setmetatable(o, self)
self.__index = self
return o */
if(lua_isnil(L, -1))
lua_newtable(L);
luaL_checktype(L, -1, LUA_TTABLE);
luaL_getmetatable(L, "minetest.entity");
lua_pushvalue(L, -1); // duplicate metatable
lua_setfield(L, -2, "__index");
lua_setmetatable(L, -2);
// return table
return 1;
}
static const struct luaL_Reg minetest_f [] = {
{"register_object", l_register_object},
{"new_entity", l_new_entity},
{NULL, NULL}
};
static int l_entity_set_deleted(lua_State *L)
{
return 0;
}
static const struct luaL_Reg minetest_entity_m [] = {
{"set_deleted", l_entity_set_deleted},
{NULL, NULL}
};
class ObjectRef
{
private:
ServerActiveObject *m_object;
static const char className[];
static const luaL_reg methods[];
static ObjectRef *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 *(ObjectRef**)ud; // unbox pointer
}
// Exported functions
static int l_remove(lua_State *L)
{
ObjectRef *o = checkobject(L, 1);
ServerActiveObject *co = o->m_object;
if(co == NULL) return 0;
infostream<<"ObjectRef::l_remove(): id="<<co->getId()<<std::endl;
co->m_removed = true;
return 0;
}
static int gc_object(lua_State *L) {
//ObjectRef *o = checkobject(L, 1);
ObjectRef *o = *(ObjectRef **)(lua_touserdata(L, 1));
//infostream<<"ObjectRef::gc_object: o="<<o<<std::endl;
delete o;
return 0;
}
public:
ObjectRef(ServerActiveObject *object):
m_object(object)
{
infostream<<"ObjectRef created for id="<<m_object->getId()<<std::endl;
}
~ObjectRef()
{
if(m_object)
infostream<<"ObjectRef destructing for id="<<m_object->getId()<<std::endl;
else
infostream<<"ObjectRef destructing for id=unknown"<<std::endl;
}
// Creates an ObjectRef and leaves it on top of stack
// Not callable from Lua; all references are created on the C side.
static void create(lua_State *L, ServerActiveObject *object)
{
ObjectRef *o = new ObjectRef(object);
//infostream<<"ObjectRef::create: o="<<o<<std::endl;
*(void **)(lua_newuserdata(L, sizeof(void *))) = o;
luaL_getmetatable(L, className);
lua_setmetatable(L, -2);
}
static void set_null(lua_State *L)
{
ObjectRef *o = checkobject(L, -1);
ServerActiveObject *co = o->m_object;
if(co == NULL)
return;
o->m_object = NULL;
}
static void 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
// Cannot be created from Lua
//lua_register(L, className, create_object);
}
};
const char ObjectRef::className[] = "ObjectRef";
#define method(class, name) {#name, class::l_##name}
const luaL_reg ObjectRef::methods[] = {
method(ObjectRef, remove),
{0,0}
};
void scriptapi_export(lua_State *L, Server *server)
{
realitycheck(L);
assert(lua_checkstack(L, 20));
infostream<<"scriptapi_export"<<std::endl;
// Register global functions in table minetest
lua_newtable(L);
luaL_register(L, NULL, minetest_f);
lua_setglobal(L, "minetest");
// Get the main minetest table
lua_getglobal(L, "minetest");
// Add registered_objects table in minetest
lua_newtable(L);
lua_setfield(L, -2, "registered_objects");
// Add object_refs table in minetest
lua_newtable(L);
lua_setfield(L, -2, "object_refs");
// Add luaentities table in minetest
lua_newtable(L);
lua_setfield(L, -2, "luaentities");
// Load and run some base Lua stuff
/*script_load(L, (porting::path_data + DIR_DELIM + "scripts"
+ DIR_DELIM + "base.lua").c_str());*/
// Create entity reference metatable
luaL_newmetatable(L, "minetest.entity_reference");
lua_pop(L, 1);
// Create entity prototype
luaL_newmetatable(L, "minetest.entity");
// metatable.__index = metatable
lua_pushvalue(L, -1); // Duplicate metatable
lua_setfield(L, -2, "__index");
// Put functions in metatable
luaL_register(L, NULL, minetest_entity_m);
// Put other stuff in metatable
// Entity C reference
ObjectRef::Register(L);
}
void scriptapi_luaentity_register(lua_State *L, u16 id, const char *name,
const char *init_state)
{
realitycheck(L);
assert(lua_checkstack(L, 20));
infostream<<"scriptapi_luaentity_register: id="<<id<<std::endl;
// Create object as a dummy string (TODO: Create properly)
lua_pushstring(L, "dummy object string");
int object = lua_gettop(L);
// Get minetest.luaentities table
lua_getglobal(L, "minetest");
lua_getfield(L, -1, "luaentities");
luaL_checktype(L, -1, LUA_TTABLE);
int objectstable = lua_gettop(L);
// luaentities[id] = object
lua_pushnumber(L, id); // Push id
lua_pushvalue(L, object); // Copy object to top of stack
lua_settable(L, objectstable);
lua_pop(L, 3); // pop luaentities, minetest and the object
}
void scriptapi_luaentity_deregister(lua_State *L, u16 id)
{
realitycheck(L);
assert(lua_checkstack(L, 20));
infostream<<"scriptapi_luaentity_deregister: id="<<id<<std::endl;
// Get minetest.luaentities table
lua_getglobal(L, "minetest");
lua_getfield(L, -1, "luaentities");
luaL_checktype(L, -1, LUA_TTABLE);
int objectstable = lua_gettop(L);
/*// Get luaentities[id]
lua_pushnumber(L, cobj->getId()); // Push id
lua_gettable(L, objectstable);
// Object is at stack top
lua_pop(L, 1); // pop object*/
// Set luaentities[id] = nil
lua_pushnumber(L, cobj->getId()); // Push id
lua_pushnil(L);
lua_settable(L, objectstable);
lua_pop(L, 2); // pop luaentities, minetest
}
void scriptapi_luaentity_step(lua_State *L, u16 id,
float dtime, bool send_recommended)
{
realitycheck(L);
assert(lua_checkstack(L, 20));
infostream<<"scriptapi_luaentity_step: id="<<id<<std::endl;
// Get minetest.luaentities table
lua_getglobal(L, "minetest");
lua_getfield(L, -1, "luaentities");
luaL_checktype(L, -1, LUA_TTABLE);
int objectstable = lua_gettop(L);
// Get luaentities[id]
lua_pushnumber(L, cobj->getId()); // Push id
lua_gettable(L, objectstable);
// TODO: Call step function
lua_pop(L, 1); // pop object
lua_pop(L, 2); // pop luaentities, minetest
}
std::string scriptapi_luaentity_get_state(lua_State *L, u16 id)
{
realitycheck(L);
assert(lua_checkstack(L, 20));
infostream<<"scriptapi_luaentity_get_state: id="<<id<<std::endl;
return "";
}
void scriptapi_add_object_reference(lua_State *L, ServerActiveObject *cobj)
{
realitycheck(L);
assert(lua_checkstack(L, 20));
infostream<<"scriptapi_add_object_reference: id="<<cobj->getId()<<std::endl;
// Create object on stack
ObjectRef::create(L, cobj); // Puts ObjectRef (as userdata) on stack
int object = lua_gettop(L);
// Get minetest.object_refs table
lua_getglobal(L, "minetest");
lua_getfield(L, -1, "object_refs");
luaL_checktype(L, -1, LUA_TTABLE);
int objectstable = lua_gettop(L);
// object_refs[id] = object
lua_pushnumber(L, cobj->getId()); // Push id
lua_pushvalue(L, object); // Copy object to top of stack
lua_settable(L, objectstable);
// pop object_refs, minetest and the object
lua_pop(L, 3);
}
void scriptapi_rm_object_reference(lua_State *L, ServerActiveObject *cobj)
{
realitycheck(L);
assert(lua_checkstack(L, 20));
infostream<<"scriptapi_rm_object_reference: id="<<cobj->getId()<<std::endl;
// Get minetest.object_refs table
lua_getglobal(L, "minetest");
lua_getfield(L, -1, "object_refs");
luaL_checktype(L, -1, LUA_TTABLE);
int objectstable = lua_gettop(L);
// Get object_refs[id]
lua_pushnumber(L, cobj->getId()); // Push id
lua_gettable(L, objectstable);
// Set object reference to NULL
ObjectRef::set_null(L);
lua_pop(L, 1); // pop object
// Set object_refs[id] = nil
lua_pushnumber(L, cobj->getId()); // Push id
lua_pushnil(L);
lua_settable(L, objectstable);
// pop object_refs, minetest
lua_pop(L, 2);
}

43
src/scriptapi.h Normal file

@ -0,0 +1,43 @@
/*
Minetest-c55
Copyright (C) 2011 celeron55, Perttu Ahola <celeron55@gmail.com>
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, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef SCRIPTAPI_HEADER
#define SCRIPTAPI_HEADER
#include "irrlichttypes.h"
#include <string>
class Server;
class ServerActiveObject;
typedef struct lua_State lua_State;
void scriptapi_export(lua_State *L, Server *server);
void scriptapi_add_object_reference(lua_State *L, ServerActiveObject *cobj);
void scriptapi_rm_object_reference(lua_State *L, ServerActiveObject *cobj);
void scriptapi_luaentity_register(lua_State *L, u16 id, const char *name,
const char *init_state);
void scriptapi_luaentity_deregister(lua_State *L, u16 id);
void scriptapi_luaentity_step(lua_State *L, u16 id,
float dtime, bool send_recommended);
std::string scriptapi_luaentity_get_state(lua_State *L, u16 id);
#endif

@ -39,6 +39,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "settings.h"
#include "profiler.h"
#include "log.h"
#include "script.h"
#include "scriptapi.h"
#define PP(x) "("<<(x).X<<","<<(x).Y<<","<<(x).Z<<")"
@ -185,7 +187,7 @@ void * EmergeThread::Thread()
<<"("<<p.X<<","<<p.Y<<","<<p.Z<<") "
<<"only_from_disk="<<only_from_disk<<std::endl;
ServerMap &map = ((ServerMap&)m_server->m_env.getMap());
ServerMap &map = ((ServerMap&)m_server->m_env->getMap());
//core::map<v3s16, MapBlock*> changed_blocks;
//core::map<v3s16, MapBlock*> lighting_invalidated_blocks;
@ -250,7 +252,7 @@ void * EmergeThread::Thread()
MapEditEventIgnorer ign(&m_server->m_ignore_map_edit_events);
// Activate objects and stuff
m_server->m_env.activateBlock(block, 3600);
m_server->m_env->activateBlock(block, 3600);
}
}
else
@ -371,7 +373,7 @@ void RemoteClient::GetNextBlocks(Server *server, float dtime,
//TimeTaker timer("RemoteClient::GetNextBlocks");
Player *player = server->m_env.getPlayer(peer_id);
Player *player = server->m_env->getPlayer(peer_id);
assert(player != NULL);
@ -572,7 +574,7 @@ void RemoteClient::GetNextBlocks(Server *server, float dtime,
MAP_BLOCKSIZE*p.Z);
// Get ground height in nodes
s16 gh = server->m_env.getServerMap().findGroundLevel(
s16 gh = server->m_env->getServerMap().findGroundLevel(
p2d_nodes_center);
// If differs a lot, don't generate
@ -611,7 +613,7 @@ void RemoteClient::GetNextBlocks(Server *server, float dtime,
/*
Check if map has this block
*/
MapBlock *block = server->m_env.getMap().getBlockNoCreateNoEx(p);
MapBlock *block = server->m_env->getMap().getBlockNoCreateNoEx(p);
bool surely_not_found_on_disk = false;
bool block_is_invalid = false;
@ -640,7 +642,7 @@ void RemoteClient::GetNextBlocks(Server *server, float dtime,
#if 0
v2s16 p2d(p.X, p.Z);
ServerMap *map = (ServerMap*)(&server->m_env.getMap());
ServerMap *map = (ServerMap*)(&server->m_env->getMap());
v2s16 chunkpos = map->sector_to_chunk(p2d);
if(map->chunkNonVolatile(chunkpos) == false)
block_is_invalid = true;
@ -802,7 +804,7 @@ void RemoteClient::SendObjectData(
*/
// Get connected players
core::list<Player*> players = server->m_env.getPlayers(true);
core::list<Player*> players = server->m_env->getPlayers(true);
// Write player count
u16 playercount = players.size();
@ -948,10 +950,12 @@ Server::Server(
std::string mapsavedir,
std::string configpath
):
m_env(new ServerMap(mapsavedir), this),
m_env(NULL),
m_con(PROTOCOL_ID, 512, CONNECTION_TIMEOUT, this),
m_authmanager(mapsavedir+DIR_DELIM+"auth.txt"),
m_banmanager(mapsavedir+DIR_DELIM+"ipban.txt"),
m_lua(NULL),
//m_scriptapi(NULL),
m_thread(this),
m_emergethread(this),
m_time_counter(0),
@ -973,20 +977,38 @@ Server::Server(
m_con_mutex.Init();
m_step_dtime_mutex.Init();
m_step_dtime = 0.0;
JMutexAutoLock envlock(m_env_mutex);
JMutexAutoLock conlock(m_con_mutex);
// Initialize scripting
infostream<<"Server: Initializing scripting"<<std::endl;
m_lua = script_init();
assert(m_lua);
// Export API
scriptapi_export(m_lua, this);
// Load and run scripts
script_load(m_lua, (porting::path_data + DIR_DELIM + "scripts"
+ DIR_DELIM + "default.lua").c_str());
// Initialize Environment
m_env = new ServerEnvironment(new ServerMap(mapsavedir), m_lua);
// Register us to receive map edit events
m_env.getMap().addEventReceiver(this);
m_env->getMap().addEventReceiver(this);
// If file exists, load environment metadata
if(fs::PathExists(m_mapsavedir+DIR_DELIM+"env_meta.txt"))
{
infostream<<"Server: Loading environment metadata"<<std::endl;
m_env.loadMeta(m_mapsavedir);
m_env->loadMeta(m_mapsavedir);
}
// Load players
infostream<<"Server: Loading players"<<std::endl;
m_env.deSerializePlayers(m_mapsavedir);
m_env->deSerializePlayers(m_mapsavedir);
}
Server::~Server()
@ -1029,13 +1051,13 @@ Server::~Server()
Save players
*/
infostream<<"Server: Saving players"<<std::endl;
m_env.serializePlayers(m_mapsavedir);
m_env->serializePlayers(m_mapsavedir);
/*
Save environment metadata
*/
infostream<<"Server: Saving environment metadata"<<std::endl;
m_env.saveMeta(m_mapsavedir);
m_env->saveMeta(m_mapsavedir);
}
/*
@ -1058,13 +1080,20 @@ Server::~Server()
{
u16 peer_id = i.getNode()->getKey();
JMutexAutoLock envlock(m_env_mutex);
m_env.removePlayer(peer_id);
m_env->removePlayer(peer_id);
}*/
// Delete client
delete i.getNode()->getValue();
}
}
// Delete Environment
delete m_env;
// Deinitialize scripting
infostream<<"Server: Deinitializing scripting"<<std::endl;
script_deinit(m_lua);
}
void Server::start(unsigned short port)
@ -1173,7 +1202,7 @@ void Server::AsyncRunStep()
u32 units = (u32)(m_time_counter*speed);
m_time_counter -= (f32)units / speed;
m_env.setTimeOfDay((m_env.getTimeOfDay() + units) % 24000);
m_env->setTimeOfDay((m_env->getTimeOfDay() + units) % 24000);
//infostream<<"Server: m_time_of_day = "<<m_time_of_day.get()<<std::endl;
@ -1194,10 +1223,10 @@ void Server::AsyncRunStep()
i.atEnd() == false; i++)
{
RemoteClient *client = i.getNode()->getValue();
//Player *player = m_env.getPlayer(client->peer_id);
//Player *player = m_env->getPlayer(client->peer_id);
SharedBuffer<u8> data = makePacket_TOCLIENT_TIME_OF_DAY(
m_env.getTimeOfDay());
m_env->getTimeOfDay());
// Send as reliable
m_con.Send(client->peer_id, 0, data, true);
}
@ -1209,7 +1238,7 @@ void Server::AsyncRunStep()
// Step environment
ScopeProfiler sp(g_profiler, "SEnv step");
ScopeProfiler sp2(g_profiler, "SEnv step avg", SPT_AVG);
m_env.step(dtime);
m_env->step(dtime);
}
const float map_timer_and_unload_dtime = 5.15;
@ -1218,7 +1247,7 @@ void Server::AsyncRunStep()
JMutexAutoLock lock(m_env_mutex);
// Run Map's timers and unload unused data
ScopeProfiler sp(g_profiler, "Server: map timer and unload");
m_env.getMap().timerUpdate(map_timer_and_unload_dtime,
m_env->getMap().timerUpdate(map_timer_and_unload_dtime,
g_settings->getFloat("server_unload_unused_data_timeout"));
}
@ -1239,13 +1268,13 @@ void Server::AsyncRunStep()
ScopeProfiler sp(g_profiler, "Server: liquid transform");
core::map<v3s16, MapBlock*> modified_blocks;
m_env.getMap().transformLiquids(modified_blocks);
m_env->getMap().transformLiquids(modified_blocks);
#if 0
/*
Update lighting
*/
core::map<v3s16, MapBlock*> lighting_modified_blocks;
ServerMap &map = ((ServerMap&)m_env.getMap());
ServerMap &map = ((ServerMap&)m_env->getMap());
map.updateLighting(modified_blocks, lighting_modified_blocks);
// Add blocks modified by lighting to modified_blocks
@ -1295,7 +1324,7 @@ void Server::AsyncRunStep()
{
//u16 peer_id = i.getNode()->getKey();
RemoteClient *client = i.getNode()->getValue();
Player *player = m_env.getPlayer(client->peer_id);
Player *player = m_env->getPlayer(client->peer_id);
if(player==NULL)
continue;
infostream<<"* "<<player->getName()<<"\t";
@ -1326,7 +1355,7 @@ void Server::AsyncRunStep()
i.atEnd() == false; i++)
{
RemoteClient *client = i.getNode()->getValue();
Player *player = m_env.getPlayer(client->peer_id);
Player *player = m_env->getPlayer(client->peer_id);
if(player==NULL)
{
// This can happen if the client timeouts somehow
@ -1339,9 +1368,9 @@ void Server::AsyncRunStep()
core::map<u16, bool> removed_objects;
core::map<u16, bool> added_objects;
m_env.getRemovedActiveObjects(pos, radius,
m_env->getRemovedActiveObjects(pos, radius,
client->m_known_objects, removed_objects);
m_env.getAddedActiveObjects(pos, radius,
m_env->getAddedActiveObjects(pos, radius,
client->m_known_objects, added_objects);
// Ignore if nothing happened
@ -1364,7 +1393,7 @@ void Server::AsyncRunStep()
{
// Get object
u16 id = i.getNode()->getKey();
ServerActiveObject* obj = m_env.getActiveObject(id);
ServerActiveObject* obj = m_env->getActiveObject(id);
// Add to data buffer for sending
writeU16((u8*)buf, i.getNode()->getKey());
@ -1386,7 +1415,7 @@ void Server::AsyncRunStep()
{
// Get object
u16 id = i.getNode()->getKey();
ServerActiveObject* obj = m_env.getActiveObject(id);
ServerActiveObject* obj = m_env->getActiveObject(id);
// Get object type
u8 type = ACTIVEOBJECT_TYPE_INVALID;
@ -1452,7 +1481,7 @@ void Server::AsyncRunStep()
}
}
m_env.setKnownActiveObjects(whatever);
m_env->setKnownActiveObjects(whatever);
#endif
}
@ -1473,7 +1502,7 @@ void Server::AsyncRunStep()
// Get active object messages from environment
for(;;)
{
ActiveObjectMessage aom = m_env.getActiveObjectMessage();
ActiveObjectMessage aom = m_env->getActiveObjectMessage();
if(aom.id == 0)
break;
@ -1662,7 +1691,7 @@ void Server::AsyncRunStep()
{
v3s16 p = i.getNode()->getKey();
modified_blocks2.insert(p,
m_env.getMap().getBlockNoCreateNoEx(p));
m_env->getMap().getBlockNoCreateNoEx(p));
}
// Set blocks not sent
for(core::list<u16>::Iterator
@ -1749,15 +1778,15 @@ void Server::AsyncRunStep()
JMutexAutoLock lock(m_env_mutex);
/*// Unload unused data (delete from memory)
m_env.getMap().unloadUnusedData(
m_env->getMap().unloadUnusedData(
g_settings->getFloat("server_unload_unused_sectors_timeout"));
*/
/*u32 deleted_count = m_env.getMap().unloadUnusedData(
/*u32 deleted_count = m_env->getMap().unloadUnusedData(
g_settings->getFloat("server_unload_unused_sectors_timeout"));
*/
// Save only changed parts
m_env.getMap().save(true);
m_env->getMap().save(true);
/*if(deleted_count > 0)
{
@ -1766,10 +1795,10 @@ void Server::AsyncRunStep()
}*/
// Save players
m_env.serializePlayers(m_mapsavedir);
m_env->serializePlayers(m_mapsavedir);
// Save environment metadata
m_env.saveMeta(m_mapsavedir);
m_env->saveMeta(m_mapsavedir);
}
}
}
@ -1811,7 +1840,7 @@ void Server::Receive()
<<" has apparently closed connection. "
<<"Removing player."<<std::endl;
m_env.removePlayer(peer_id);*/
m_env->removePlayer(peer_id);*/
}
}
@ -2026,7 +2055,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
writeU16(&reply[0], TOCLIENT_INIT);
writeU8(&reply[2], deployed);
writeV3S16(&reply[2+1], floatToInt(player->getPosition()+v3f(0,BS/2,0), BS));
writeU64(&reply[2+1+6], m_env.getServerMap().getSeed());
writeU64(&reply[2+1+6], m_env->getServerMap().getSeed());
// Send as reliable
m_con.Send(peer_id, 0, reply, true);
@ -2063,7 +2092,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
// Send player items to all players
SendPlayerItems();
Player *player = m_env.getPlayer(peer_id);
Player *player = m_env->getPlayer(peer_id);
// Send HP
SendPlayerHP(player);
@ -2071,7 +2100,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
// Send time of day
{
SharedBuffer<u8> data = makePacket_TOCLIENT_TIME_OF_DAY(
m_env.getTimeOfDay());
m_env->getTimeOfDay());
m_con.Send(peer_id, 0, data, true);
}
@ -2081,7 +2110,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
// Send information about joining in chat
{
std::wstring name = L"unknown";
Player *player = m_env.getPlayer(peer_id);
Player *player = m_env->getPlayer(peer_id);
if(player != NULL)
name = narrow_to_wide(player->getName());
@ -2117,7 +2146,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
if(client->serialization_version == SER_FMT_VER_INVALID)
continue;
// Get player
Player *player = m_env.getPlayer(client->peer_id);
Player *player = m_env->getPlayer(client->peer_id);
if(!player)
continue;
// Get name of player
@ -2139,7 +2168,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
return;
}
Player *player = m_env.getPlayer(peer_id);
Player *player = m_env->getPlayer(peer_id);
if(player == NULL){
infostream<<"Server::ProcessData(): Cancelling: "
@ -2247,7 +2276,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
u16 id = readS16(&data[3]);
u16 item_i = readU16(&data[5]);
ServerActiveObject *obj = m_env.getActiveObject(id);
ServerActiveObject *obj = m_env->getActiveObject(id);
if(obj == NULL)
{
@ -2421,7 +2450,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
try
{
MapNode n = m_env.getMap().getNode(p_under);
MapNode n = m_env->getMap().getNode(p_under);
// Get mineral
mineral = n.getMineral();
// Get material at position
@ -2442,7 +2471,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
if(cannot_remove_node == false)
{
// Get node metadata
NodeMetadata *meta = m_env.getMap().getNodeMetadata(p_under);
NodeMetadata *meta = m_env->getMap().getNodeMetadata(p_under);
if(meta && meta->nodeRemovalDisabled() == true)
{
infostream<<"Server: Not finishing digging: "
@ -2608,7 +2637,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
{
MapEditEventIgnorer ign(&m_ignore_map_edit_events);
m_env.getMap().removeNodeAndUpdate(p_under, modified_blocks);
m_env->getMap().removeNodeAndUpdate(p_under, modified_blocks);
}
/*
Set blocks not sent to far players
@ -2649,7 +2678,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
{
try{
// Don't add a node if this is not a free space
MapNode n2 = m_env.getMap().getNode(p_over);
MapNode n2 = m_env->getMap().getNode(p_over);
bool no_enough_privs =
((getPlayerPrivs(player) & PRIV_BUILD)==0);
if(no_enough_privs)
@ -2750,7 +2779,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
MapEditEventIgnorer ign(&m_ignore_map_edit_events);
std::string p_name = std::string(player->getName());
m_env.getMap().addNodeAndUpdate(p_over, n, modified_blocks, p_name);
m_env->getMap().addNodeAndUpdate(p_over, n, modified_blocks, p_name);
}
/*
Set blocks not sent to far players
@ -2792,7 +2821,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
Check that the block is loaded so that the item
can properly be added to the static list too
*/
MapBlock *block = m_env.getMap().getBlockNoCreateNoEx(blockpos);
MapBlock *block = m_env->getMap().getBlockNoCreateNoEx(blockpos);
if(block==NULL)
{
infostream<<"Error while placing object: "
@ -2823,7 +2852,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
/*
Create the object
*/
ServerActiveObject *obj = item->createSAO(&m_env, 0, pos);
ServerActiveObject *obj = item->createSAO(m_env, 0, pos);
if(obj == NULL)
{
@ -2837,7 +2866,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
<<" at "<<PP(p_over)<<std::endl;
// Add the object to the environment
m_env.addActiveObject(obj);
m_env->addActiveObject(obj);
infostream<<"Placed object"<<std::endl;
@ -2924,7 +2953,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
text += (char)buf[0];
}
NodeMetadata *meta = m_env.getMap().getNodeMetadata(p);
NodeMetadata *meta = m_env->getMap().getNodeMetadata(p);
if(!meta)
return;
if(meta->typeId() != CONTENT_SIGN_WALL)
@ -2936,7 +2965,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
<<" at "<<PP(p)<<std::endl;
v3s16 blockpos = getNodeBlockPos(p);
MapBlock *block = m_env.getMap().getBlockNoCreateNoEx(blockpos);
MapBlock *block = m_env->getMap().getBlockNoCreateNoEx(blockpos);
if(block)
{
block->setChangedFlag();
@ -3052,7 +3081,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
p.X = stoi(fn.next(","));
p.Y = stoi(fn.next(","));
p.Z = stoi(fn.next(","));
NodeMetadata *meta = m_env.getMap().getNodeMetadata(p);
NodeMetadata *meta = m_env->getMap().getNodeMetadata(p);
if(meta && meta->typeId() == CONTENT_LOCKABLE_CHEST) {
LockingChestNodeMetadata *lcm = (LockingChestNodeMetadata*)meta;
if (lcm->getOwner() != player->getName())
@ -3070,7 +3099,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
p.X = stoi(fn.next(","));
p.Y = stoi(fn.next(","));
p.Z = stoi(fn.next(","));
NodeMetadata *meta = m_env.getMap().getNodeMetadata(p);
NodeMetadata *meta = m_env->getMap().getNodeMetadata(p);
if(meta && meta->typeId() == CONTENT_LOCKABLE_CHEST) {
LockingChestNodeMetadata *lcm = (LockingChestNodeMetadata*)meta;
if (lcm->getOwner() != player->getName())
@ -3153,7 +3182,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
str_split(message, L' '),
paramstring,
this,
&m_env,
m_env,
player,
privs);
@ -3356,7 +3385,7 @@ Inventory* Server::getInventory(InventoryContext *c, std::string id)
p.X = stoi(fn.next(","));
p.Y = stoi(fn.next(","));
p.Z = stoi(fn.next(","));
NodeMetadata *meta = m_env.getMap().getNodeMetadata(p);
NodeMetadata *meta = m_env->getMap().getNodeMetadata(p);
if(meta)
return meta->getInventory();
infostream<<"nodemeta at ("<<p.X<<","<<p.Y<<","<<p.Z<<"): "
@ -3389,7 +3418,7 @@ void Server::inventoryModified(InventoryContext *c, std::string id)
p.Z = stoi(fn.next(","));
v3s16 blockpos = getNodeBlockPos(p);
NodeMetadata *meta = m_env.getMap().getNodeMetadata(p);
NodeMetadata *meta = m_env->getMap().getNodeMetadata(p);
if(meta)
meta->inventoryModified();
@ -3415,7 +3444,7 @@ core::list<PlayerInfo> Server::getPlayerInfo()
core::list<PlayerInfo> list;
core::list<Player*> players = m_env.getPlayers();
core::list<Player*> players = m_env->getPlayers();
core::list<Player*>::Iterator i;
for(i = players.begin();
@ -3559,7 +3588,7 @@ void Server::SendPlayerInfos()
//JMutexAutoLock envlock(m_env_mutex);
// Get connected players
core::list<Player*> players = m_env.getPlayers(true);
core::list<Player*> players = m_env->getPlayers(true);
u32 player_count = players.getSize();
u32 datasize = 2+(2+PLAYERNAME_SIZE)*player_count;
@ -3593,7 +3622,7 @@ void Server::SendInventory(u16 peer_id)
{
DSTACK(__FUNCTION_NAME);
Player* player = m_env.getPlayer(peer_id);
Player* player = m_env->getPlayer(peer_id);
assert(player);
/*
@ -3650,7 +3679,7 @@ void Server::SendPlayerItems()
DSTACK(__FUNCTION_NAME);
std::ostringstream os(std::ios_base::binary);
core::list<Player *> players = m_env.getPlayers(true);
core::list<Player *> players = m_env->getPlayers(true);
writeU16(os, TOCLIENT_PLAYERITEM);
writeU16(os, players.size());
@ -3779,7 +3808,7 @@ void Server::sendRemoveNode(v3s16 p, u16 ignore_id,
if(far_players)
{
// Get player
Player *player = m_env.getPlayer(client->peer_id);
Player *player = m_env->getPlayer(client->peer_id);
if(player)
{
// If player is far away, only set modified blocks not sent
@ -3820,7 +3849,7 @@ void Server::sendAddNode(v3s16 p, MapNode n, u16 ignore_id,
if(far_players)
{
// Get player
Player *player = m_env.getPlayer(client->peer_id);
Player *player = m_env->getPlayer(client->peer_id);
if(player)
{
// If player is far away, only set modified blocks not sent
@ -3960,7 +3989,7 @@ void Server::SendBlocks(float dtime)
MapBlock *block = NULL;
try
{
block = m_env.getMap().getBlockNoCreate(q.pos);
block = m_env->getMap().getBlockNoCreate(q.pos);
}
catch(InvalidPositionException &e)
{
@ -4019,7 +4048,7 @@ void Server::HandlePlayerHP(Player *player, s16 damage)
void Server::RespawnPlayer(Player *player)
{
v3f pos = findSpawnPos(m_env.getServerMap());
v3f pos = findSpawnPos(m_env->getServerMap());
player->setPosition(pos);
player->hp = 20;
SendMovePlayer(player);
@ -4030,7 +4059,7 @@ void Server::UpdateCrafting(u16 peer_id)
{
DSTACK(__FUNCTION_NAME);
Player* player = m_env.getPlayer(peer_id);
Player* player = m_env->getPlayer(peer_id);
assert(player);
/*
@ -4096,7 +4125,7 @@ std::wstring Server::getStatusString()
if(client->serialization_version == SER_FMT_VER_INVALID)
continue;
// Get player
Player *player = m_env.getPlayer(client->peer_id);
Player *player = m_env->getPlayer(client->peer_id);
// Get name of player
std::wstring name = L"unknown";
if(player != NULL)
@ -4105,7 +4134,7 @@ std::wstring Server::getStatusString()
os<<name<<L",";
}
os<<L"}";
if(((ServerMap*)(&m_env.getMap()))->isSavingEnabled() == false)
if(((ServerMap*)(&m_env->getMap()))->isSavingEnabled() == false)
os<<std::endl<<L"# Server: "<<" WARNING: Map saving is disabled.";
if(g_settings->get("motd") != "")
os<<std::endl<<L"# Server: "<<narrow_to_wide(g_settings->get("motd"));
@ -4121,7 +4150,7 @@ void Server::saveConfig()
void Server::notifyPlayer(const char *name, const std::wstring msg)
{
Player *player = m_env.getPlayer(name);
Player *player = m_env->getPlayer(name);
if(!player)
return;
SendChatMessage(player->peer_id, std::wstring(L"Server: -!- ")+msg);
@ -4200,7 +4229,7 @@ Player *Server::emergePlayer(const char *name, const char *password, u16 peer_id
/*
Try to get an existing player
*/
Player *player = m_env.getPlayer(name);
Player *player = m_env->getPlayer(name);
if(player != NULL)
{
// If player is already connected, cancel
@ -4230,7 +4259,7 @@ Player *Server::emergePlayer(const char *name, const char *password, u16 peer_id
/*
If player with the wanted peer_id already exists, cancel.
*/
if(m_env.getPlayer(peer_id) != NULL)
if(m_env->getPlayer(peer_id) != NULL)
{
infostream<<"emergePlayer(): Player with wrong name but same"
" peer_id already exists"<<std::endl;
@ -4258,7 +4287,7 @@ Player *Server::emergePlayer(const char *name, const char *password, u16 peer_id
infostream<<"Server: Finding spawn place for player \""
<<player->getName()<<"\""<<std::endl;
v3f pos = findSpawnPos(m_env.getServerMap());
v3f pos = findSpawnPos(m_env->getServerMap());
player->setPosition(pos);
@ -4266,7 +4295,7 @@ Player *Server::emergePlayer(const char *name, const char *password, u16 peer_id
Add player to environment
*/
m_env.addPlayer(player);
m_env->addPlayer(player);
/*
Add stuff to inventory
@ -4337,7 +4366,7 @@ void Server::handlePeerChange(PeerChange &c)
{
// Get object
u16 id = i.getNode()->getKey();
ServerActiveObject* obj = m_env.getActiveObject(id);
ServerActiveObject* obj = m_env->getActiveObject(id);
if(obj && obj->m_known_by_count > 0)
obj->m_known_by_count--;
@ -4346,7 +4375,7 @@ void Server::handlePeerChange(PeerChange &c)
// Collect information about leaving in chat
std::wstring message;
{
Player *player = m_env.getPlayer(c.peer_id);
Player *player = m_env->getPlayer(c.peer_id);
if(player != NULL)
{
std::wstring name = narrow_to_wide(player->getName());
@ -4360,12 +4389,12 @@ void Server::handlePeerChange(PeerChange &c)
/*// Delete player
{
m_env.removePlayer(c.peer_id);
m_env->removePlayer(c.peer_id);
}*/
// Set player client disconnected
{
Player *player = m_env.getPlayer(c.peer_id);
Player *player = m_env->getPlayer(c.peer_id);
if(player != NULL)
player->peer_id = 0;
@ -4384,7 +4413,7 @@ void Server::handlePeerChange(PeerChange &c)
if(client->serialization_version == SER_FMT_VER_INVALID)
continue;
// Get player
Player *player = m_env.getPlayer(client->peer_id);
Player *player = m_env->getPlayer(client->peer_id);
if(!player)
continue;
// Get name of player

@ -29,6 +29,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "inventory.h"
#include "auth.h"
#include "ban.h"
struct LuaState;
typedef struct lua_State lua_State;
/*
Some random functions
@ -391,7 +393,7 @@ public:
// Environment must be locked when called
void setTimeOfDay(u32 time)
{
m_env.setTimeOfDay(time);
m_env->setTimeOfDay(time);
m_time_of_day_send_timer = 0;
}
@ -476,6 +478,9 @@ public:
// Envlock and conlock should be locked when calling this
void notifyPlayer(const char *name, const std::wstring msg);
void notifyPlayers(const std::wstring msg);
// Envlock and conlock should be locked when using Lua
lua_State *getLua(){ return m_lua; }
private:
@ -543,7 +548,7 @@ private:
// When called, environment mutex should be locked
std::string getPlayerName(u16 peer_id)
{
Player *player = m_env.getPlayer(peer_id);
Player *player = m_env->getPlayer(peer_id);
if(player == NULL)
return "[id="+itos(peer_id);
return player->getName();
@ -582,7 +587,7 @@ private:
// environment shall be locked first.
// Environment
ServerEnvironment m_env;
ServerEnvironment *m_env;
JMutex m_env_mutex;
// Connection
@ -596,6 +601,10 @@ private:
// Bann checking
BanManager m_banmanager;
// Scripting
// Envlock and conlock should be locked when using Lua
lua_State *m_lua;
/*
Threads

@ -21,8 +21,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include <fstream>
#include "inventory.h"
ServerActiveObject::ServerActiveObject(ServerEnvironment *env, u16 id, v3f pos):
ActiveObject(id),
ServerActiveObject::ServerActiveObject(ServerEnvironment *env, v3f pos):
ActiveObject(0),
m_known_by_count(0),
m_removed(false),
m_pending_deactivation(false),
@ -37,6 +37,11 @@ ServerActiveObject::~ServerActiveObject()
{
}
void ServerActiveObject::addedToEnvironment(u16 id)
{
setId(id);
}
ServerActiveObject* ServerActiveObject::create(u8 type,
ServerEnvironment *env, u16 id, v3f pos,
const std::string &data)
@ -53,7 +58,7 @@ ServerActiveObject* ServerActiveObject::create(u8 type,
}
Factory f = n->getValue();
ServerActiveObject *object = (*f)(env, id, pos, data);
ServerActiveObject *object = (*f)(env, pos, data);
return object;
}

@ -51,9 +51,11 @@ public:
NOTE: m_env can be NULL, but step() isn't called if it is.
Prototypes are used that way.
*/
ServerActiveObject(ServerEnvironment *env, u16 id, v3f pos);
ServerActiveObject(ServerEnvironment *env, v3f pos);
virtual ~ServerActiveObject();
virtual void addedToEnvironment(u16 id);
// Create a certain type of ServerActiveObject
static ServerActiveObject* create(u8 type,
ServerEnvironment *env, u16 id, v3f pos,
@ -160,7 +162,7 @@ public:
protected:
// Used for creating objects based on type
typedef ServerActiveObject* (*Factory)
(ServerEnvironment *env, u16 id, v3f pos,
(ServerEnvironment *env, v3f pos,
const std::string &data);
static void registerType(u16 type, Factory f);