aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/content_abm.cpp115
-rw-r--r--src/content_cao.cpp1509
-rw-r--r--src/content_sao.cpp1738
-rw-r--r--src/content_sao.h182
-rw-r--r--src/itemgroup.h39
-rw-r--r--src/luaentity_common.cpp10
-rw-r--r--src/luaentity_common.h6
-rw-r--r--src/scriptapi.cpp53
-rw-r--r--src/scriptapi.h4
-rw-r--r--src/server.cpp15
-rw-r--r--src/serverobject.h10
-rw-r--r--src/serverremoteplayer.cpp20
-rw-r--r--src/serverremoteplayer.h5
13 files changed, 463 insertions, 3243 deletions
diff --git a/src/content_abm.cpp b/src/content_abm.cpp
index 63867b78b..3a92796a4 100644
--- a/src/content_abm.cpp
+++ b/src/content_abm.cpp
@@ -88,119 +88,6 @@ public:
}
};
-class SpawnRatsAroundTreesABM : public ActiveBlockModifier
-{
-private:
-public:
- virtual std::set<std::string> getTriggerContents()
- {
- std::set<std::string> s;
- s.insert("tree");
- s.insert("jungletree");
- return s;
- }
- virtual float getTriggerInterval()
- { return 10.0; }
- virtual u32 getTriggerChance()
- { return 200; }
- virtual void trigger(ServerEnvironment *env, v3s16 p, MapNode n,
- u32 active_object_count, u32 active_object_count_wider)
- {
- if(active_object_count_wider != 0)
- return;
-
- INodeDefManager *ndef = env->getGameDef()->ndef();
- ServerMap *map = &env->getServerMap();
-
- v3s16 p1 = p + v3s16(myrand_range(-2, 2),
- 0, myrand_range(-2, 2));
- MapNode n1 = map->getNodeNoEx(p1);
- MapNode n1b = map->getNodeNoEx(p1+v3s16(0,-1,0));
- if(n1b.getContent() == ndef->getId("dirt_with_grass") &&
- n1.getContent() == CONTENT_AIR)
- {
- v3f pos = intToFloat(p1, BS);
- ServerActiveObject *obj = new RatSAO(env, pos);
- env->addActiveObject(obj);
- }
- }
-};
-
-static void getMob_dungeon_master(Settings &properties)
-{
- properties.set("looks", "dungeon_master");
- properties.setFloat("yaw", 1.57);
- properties.setFloat("hp", 30);
- properties.setBool("bright_shooting", true);
- properties.set("shoot_type", "fireball");
- properties.set("shoot_y", "0.7");
- properties.set("player_hit_damage", "1");
- properties.set("player_hit_distance", "1.0");
- properties.set("player_hit_interval", "0.5");
- properties.setBool("mindless_rage", myrand_range(0,100)==0);
-}
-
-class SpawnInCavesABM : public ActiveBlockModifier
-{
-private:
-public:
- virtual std::set<std::string> getTriggerContents()
- {
- std::set<std::string> s;
- s.insert("stone");
- s.insert("mossycobble");
- return s;
- }
- virtual float getTriggerInterval()
- { return 2.0; }
- virtual u32 getTriggerChance()
- { return 1000; }
- virtual void trigger(ServerEnvironment *env, v3s16 p, MapNode n,
- u32 active_object_count, u32 active_object_count_wider)
- {
- if(active_object_count_wider != 0)
- return;
-
- INodeDefManager *ndef = env->getGameDef()->ndef();
- ServerMap *map = &env->getServerMap();
-
- v3s16 p1 = p + v3s16(0,1,0);
- MapNode n1a = map->getNodeNoEx(p1+v3s16(0,0,0));
- if(n1a.getLightBlend(env->getDayNightRatio(), ndef) <= 3){
- MapNode n1b = map->getNodeNoEx(p1+v3s16(0,1,0));
- if(n1a.getContent() == CONTENT_AIR &&
- n1b.getContent() == CONTENT_AIR)
- {
- v3f pos = intToFloat(p1, BS);
- int i = myrand()%5;
- if(i == 0 || i == 1){
- actionstream<<"A dungeon master spawns at "
- <<PP(p1)<<std::endl;
- Settings properties;
- getMob_dungeon_master(properties);
- ServerActiveObject *obj = new MobV2SAO(
- env, pos, &properties);
- env->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(
- env, pos);
- env->addActiveObject(obj);
- }
- } else {
- actionstream<<"An oerkki spawns at "
- <<PP(p1)<<std::endl;
- ServerActiveObject *obj = new Oerkki1SAO(
- env, pos);
- env->addActiveObject(obj);
- }
- }
- }
- }
-};
-
class MakeTreesFromSaplingsABM : public ActiveBlockModifier
{
private:
@@ -261,8 +148,6 @@ void add_legacy_abms(ServerEnvironment *env, INodeDefManager *nodedef)
{
env->addActiveBlockModifier(new GrowGrassABM());
env->addActiveBlockModifier(new RemoveGrassABM());
- env->addActiveBlockModifier(new SpawnRatsAroundTreesABM());
- env->addActiveBlockModifier(new SpawnInCavesABM());
env->addActiveBlockModifier(new MakeTreesFromSaplingsABM());
}
diff --git a/src/content_cao.cpp b/src/content_cao.cpp
index 3c30a0819..d6289a1b9 100644
--- a/src/content_cao.cpp
+++ b/src/content_cao.cpp
@@ -116,6 +116,18 @@ struct SmoothTranslator
}
};
+/*
+ Other stuff
+*/
+
+static void setBillboardTextureMatrix(scene::IBillboardSceneNode *bill,
+ float txs, float tys, int col, int row)
+{
+ video::SMaterial& material = bill->getMaterial(0);
+ core::matrix4& matrix = material.getTextureMatrix(0);
+ matrix.setTextureTranslate(txs*col, tys*row);
+ matrix.setTextureScale(txs, tys);
+}
/*
TestCAO
@@ -199,1483 +211,6 @@ private:
};
/*
- RatCAO
-*/
-
-class RatCAO : public ClientActiveObject
-{
-public:
- RatCAO(IGameDef *gamedef, ClientEnvironment *env);
- virtual ~RatCAO();
-
- u8 getType() const
- {
- return ACTIVEOBJECT_TYPE_RAT;
- }
-
- static ClientActiveObject* create(IGameDef *gamedef, ClientEnvironment *env);
-
- void addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc,
- IrrlichtDevice *irr);
- 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 pos_translator.vect_show;}
- //{return m_position;}
-
-private:
- core::aabbox3d<f32> m_selection_box;
- scene::IMeshSceneNode *m_node;
- v3f m_position;
- float m_yaw;
- SmoothTranslator pos_translator;
-};
-
-/*
- Oerkki1CAO
-*/
-
-class Oerkki1CAO : public ClientActiveObject
-{
-public:
- Oerkki1CAO(IGameDef *gamedef, ClientEnvironment *env);
- virtual ~Oerkki1CAO();
-
- u8 getType() const
- {
- return ACTIVEOBJECT_TYPE_OERKKI1;
- }
-
- static ClientActiveObject* create(IGameDef *gamedef, ClientEnvironment *env);
-
- void addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc,
- IrrlichtDevice *irr);
- 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 pos_translator.vect_show;}
- //{return m_position;}
-
- // If returns true, punch will not be sent to the server
- bool directReportPunch(const std::string &toolname, v3f dir);
-
-private:
- IntervalLimiter m_attack_interval;
- core::aabbox3d<f32> m_selection_box;
- scene::IMeshSceneNode *m_node;
- v3f m_position;
- float m_yaw;
- SmoothTranslator pos_translator;
- float m_damage_visual_timer;
- bool m_damage_texture_enabled;
-};
-
-/*
- FireflyCAO
-*/
-
-class FireflyCAO : public ClientActiveObject
-{
-public:
- FireflyCAO(IGameDef *gamedef, ClientEnvironment *env);
- virtual ~FireflyCAO();
-
- u8 getType() const
- {
- return ACTIVEOBJECT_TYPE_FIREFLY;
- }
-
- static ClientActiveObject* create(IGameDef *gamedef, ClientEnvironment *env);
-
- void addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc,
- IrrlichtDevice *irr);
- 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;
- float m_yaw;
- SmoothTranslator pos_translator;
-};
-
-static void setBillboardTextureMatrix(scene::IBillboardSceneNode *bill,
- float txs, float tys, int col, int row)
-{
- video::SMaterial& material = bill->getMaterial(0);
- core::matrix4& matrix = material.getTextureMatrix(0);
- matrix.setTextureTranslate(txs*col, tys*row);
- matrix.setTextureScale(txs, tys);
-}
-
-/*
- MobV2CAO
-*/
-
-class MobV2CAO : public ClientActiveObject
-{
-public:
- MobV2CAO(IGameDef *gamedef, ClientEnvironment *env);
- virtual ~MobV2CAO();
-
- u8 getType() const
- {
- return ACTIVEOBJECT_TYPE_MOBV2;
- }
-
- static ClientActiveObject* create(IGameDef *gamedef, ClientEnvironment *env);
-
- void addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc,
- IrrlichtDevice *irr);
- 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 pos_translator.vect_show;}
- //{return m_position;}
- bool doShowSelectionBox(){return false;}
-
- // If returns true, punch will not be sent to the server
- bool directReportPunch(const std::string &toolname, v3f dir);
-
-private:
- void setLooks(const std::string &looks);
-
- IntervalLimiter m_attack_interval;
- core::aabbox3d<f32> m_selection_box;
- scene::IBillboardSceneNode *m_node;
- v3f m_position;
- std::string m_texture_name;
- float m_yaw;
- SmoothTranslator pos_translator;
- bool m_walking;
- float m_walking_unset_timer;
- float m_walk_timer;
- int m_walk_frame;
- float m_damage_visual_timer;
- u8 m_last_light;
- bool m_shooting;
- float m_shooting_unset_timer;
- v2f m_sprite_size;
- float m_sprite_y;
- bool m_bright_shooting;
- std::string m_sprite_type;
- int m_simple_anim_frames;
- float m_simple_anim_frametime;
- bool m_lock_full_brightness;
- int m_player_hit_damage;
- float m_player_hit_distance;
- float m_player_hit_interval;
- float m_player_hit_timer;
-
- Settings *m_properties;
-};
-
-/*
- TestCAO
-*/
-
-// Prototype
-TestCAO proto_TestCAO(NULL, NULL);
-
-TestCAO::TestCAO(IGameDef *gamedef, ClientEnvironment *env):
- ClientActiveObject(0, gamedef, env),
- m_node(NULL),
- m_position(v3f(0,10*BS,0))
-{
- ClientActiveObject::registerType(getType(), create);
-}
-
-TestCAO::~TestCAO()
-{
-}
-
-ClientActiveObject* TestCAO::create(IGameDef *gamedef, ClientEnvironment *env)
-{
- return new TestCAO(gamedef, env);
-}
-
-void TestCAO::addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc,
- IrrlichtDevice *irr)
-{
- 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),
- };
- 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, tsrc->getTextureRaw("rat.png"));
- 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();
- updateNodePos();
-}
-
-void TestCAO::removeFromScene()
-{
- if(m_node == NULL)
- return;
-
- m_node->remove();
- m_node = NULL;
-}
-
-void TestCAO::updateLight(u8 light_at_pos)
-{
-}
-
-v3s16 TestCAO::getLightPosition()
-{
- return floatToInt(m_position, BS);
-}
-
-void TestCAO::updateNodePos()
-{
- if(m_node == NULL)
- return;
-
- m_node->setPosition(m_position);
- //m_node->setRotation(v3f(0, 45, 0));
-}
-
-void TestCAO::step(float dtime, ClientEnvironment *env)
-{
- if(m_node)
- {
- v3f rot = m_node->getRotation();
- //infostream<<"dtime="<<dtime<<", rot.Y="<<rot.Y<<std::endl;
- rot.Y += dtime * 180;
- m_node->setRotation(rot);
- }
-}
-
-void TestCAO::processMessage(const std::string &data)
-{
- infostream<<"TestCAO: Got data: "<<data<<std::endl;
- std::istringstream is(data, std::ios::binary);
- u16 cmd;
- is>>cmd;
- if(cmd == 0)
- {
- v3f newpos;
- is>>newpos.X;
- is>>newpos.Y;
- is>>newpos.Z;
- m_position = newpos;
- updateNodePos();
- }
-}
-
-/*
- ItemCAO
-*/
-
-#include "inventory.h"
-
-// Prototype
-ItemCAO proto_ItemCAO(NULL, NULL);
-
-ItemCAO::ItemCAO(IGameDef *gamedef, ClientEnvironment *env):
- ClientActiveObject(0, gamedef, env),
- 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))
-{
- if(!gamedef && !env)
- {
- ClientActiveObject::registerType(getType(), create);
- }
-}
-
-ItemCAO::~ItemCAO()
-{
-}
-
-ClientActiveObject* ItemCAO::create(IGameDef *gamedef, ClientEnvironment *env)
-{
- return new ItemCAO(gamedef, env);
-}
-
-void ItemCAO::addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc,
- IrrlichtDevice *irr)
-{
- 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);
- // Initialize with a generated placeholder texture
- buf->getMaterial().setTexture(0, tsrc->getTextureRaw(""));
- 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();
- updateNodePos();
-
- /*
- Update image of node
- */
-
- updateTexture();
-}
-
-void ItemCAO::removeFromScene()
-{
- if(m_node == NULL)
- return;
-
- m_node->remove();
- m_node = NULL;
-}
-
-void ItemCAO::updateLight(u8 light_at_pos)
-{
- if(m_node == NULL)
- return;
-
- u8 li = decode_light(light_at_pos);
- video::SColor color(255,li,li,li);
- setMeshColor(m_node->getMesh(), color);
-}
-
-v3s16 ItemCAO::getLightPosition()
-{
- return floatToInt(m_position, BS);
-}
-
-void ItemCAO::updateNodePos()
-{
- if(m_node == NULL)
- return;
-
- m_node->setPosition(m_position);
-}
-
-void ItemCAO::updateInfoText()
-{
- try{
- IItemDefManager *idef = m_gamedef->idef();
- ItemStack item;
- item.deSerialize(m_itemstring, idef);
- if(item.isKnown(idef))
- m_infotext = item.getDefinition(idef).description;
- else
- m_infotext = "Unknown item: '" + m_itemstring + "'";
- if(item.count >= 2)
- m_infotext += " (" + itos(item.count) + ")";
- }
- catch(SerializationError &e)
- {
- m_infotext = "Unknown item: '" + m_itemstring + "'";
- }
-}
-
-void ItemCAO::updateTexture()
-{
- if(m_node == NULL)
- return;
-
- // Create an inventory item to see what is its image
- std::istringstream is(m_itemstring, std::ios_base::binary);
- video::ITexture *texture = NULL;
- try{
- IItemDefManager *idef = m_gamedef->idef();
- ItemStack item;
- item.deSerialize(is, idef);
- texture = item.getDefinition(idef).inventory_texture;
- }
- catch(SerializationError &e)
- {
- infostream<<"WARNING: "<<__FUNCTION_NAME
- <<": error deSerializing itemstring \""
- <<m_itemstring<<std::endl;
- }
-
- // Set meshbuffer texture
- m_node->getMaterial(0).setTexture(0, texture);
-}
-
-
-void ItemCAO::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 ItemCAO::processMessage(const std::string &data)
-{
- //infostream<<"ItemCAO: 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();
- }
- if(cmd == 1)
- {
- // itemstring
- m_itemstring = deSerializeString(is);
- updateInfoText();
- updateTexture();
- }
-}
-
-void ItemCAO::initialize(const std::string &data)
-{
- infostream<<"ItemCAO: 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);
- // itemstring
- m_itemstring = deSerializeString(is);
- }
-
- updateNodePos();
- updateInfoText();
-}
-
-/*
- RatCAO
-*/
-
-#include "inventory.h"
-
-// Prototype
-RatCAO proto_RatCAO(NULL, NULL);
-
-RatCAO::RatCAO(IGameDef *gamedef, ClientEnvironment *env):
- ClientActiveObject(0, gamedef, env),
- m_selection_box(-BS/3.,0.0,-BS/3., BS/3.,BS/2.,BS/3.),
- m_node(NULL),
- m_position(v3f(0,10*BS,0)),
- m_yaw(0)
-{
- ClientActiveObject::registerType(getType(), create);
-}
-
-RatCAO::~RatCAO()
-{
-}
-
-ClientActiveObject* RatCAO::create(IGameDef *gamedef, ClientEnvironment *env)
-{
- return new RatCAO(gamedef, env);
-}
-
-void RatCAO::addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc,
- IrrlichtDevice *irr)
-{
- 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,0,0, 0,0,0, c, 0,1),
- video::S3DVertex(BS/2,0,0, 0,0,0, c, 1,1),
- video::S3DVertex(BS/2,BS/2,0, 0,0,0, c, 1,0),
- video::S3DVertex(-BS/2,BS/2,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);
- buf->getMaterial().setTexture(0, tsrc->getTextureRaw("rat.png"));
- 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 RatCAO::removeFromScene()
-{
- if(m_node == NULL)
- return;
-
- m_node->remove();
- m_node = NULL;
-}
-
-void RatCAO::updateLight(u8 light_at_pos)
-{
- if(m_node == NULL)
- return;
-
- u8 li = decode_light(light_at_pos);
- video::SColor color(255,li,li,li);
- setMeshColor(m_node->getMesh(), color);
-}
-
-v3s16 RatCAO::getLightPosition()
-{
- return floatToInt(m_position+v3f(0,BS*0.5,0), BS);
-}
-
-void RatCAO::updateNodePos()
-{
- if(m_node == NULL)
- return;
-
- //m_node->setPosition(m_position);
- m_node->setPosition(pos_translator.vect_show);
-
- v3f rot = m_node->getRotation();
- rot.Y = 180.0 - m_yaw;
- m_node->setRotation(rot);
-}
-
-void RatCAO::step(float dtime, ClientEnvironment *env)
-{
- pos_translator.translate(dtime);
- updateNodePos();
-}
-
-void RatCAO::processMessage(const std::string &data)
-{
- //infostream<<"RatCAO: Got message"<<std::endl;
- std::istringstream is(data, std::ios::binary);
- // command
- u8 cmd = readU8(is);
- if(cmd == 0)
- {
- // pos
- m_position = readV3F1000(is);
- pos_translator.update(m_position);
- // yaw
- m_yaw = readF1000(is);
- updateNodePos();
- }
-}
-
-void RatCAO::initialize(const std::string &data)
-{
- //infostream<<"RatCAO: 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);
- pos_translator.init(m_position);
- }
-
- updateNodePos();
-}
-
-/*
- Oerkki1CAO
-*/
-
-#include "inventory.h"
-
-// Prototype
-Oerkki1CAO proto_Oerkki1CAO(NULL, NULL);
-
-Oerkki1CAO::Oerkki1CAO(IGameDef *gamedef, ClientEnvironment *env):
- ClientActiveObject(0, gamedef, env),
- m_selection_box(-BS/3.,0.0,-BS/3., BS/3.,BS*2.,BS/3.),
- m_node(NULL),
- m_position(v3f(0,10*BS,0)),
- m_yaw(0),
- m_damage_visual_timer(0),
- m_damage_texture_enabled(false)
-{
- ClientActiveObject::registerType(getType(), create);
-}
-
-Oerkki1CAO::~Oerkki1CAO()
-{
-}
-
-ClientActiveObject* Oerkki1CAO::create(IGameDef *gamedef, ClientEnvironment *env)
-{
- return new Oerkki1CAO(gamedef, env);
-}
-
-void Oerkki1CAO::addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc,
- IrrlichtDevice *irr)
-{
- 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,0,0, 0,0,0, c, 0,1),
- video::S3DVertex(BS/2+BS,0,0, 0,0,0, c, 1,1),
- video::S3DVertex(BS/2+BS,BS*2,0, 0,0,0, c, 1,0),
- video::S3DVertex(-BS/2-BS,BS*2,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);
- buf->getMaterial().setTexture(0, tsrc->getTextureRaw("oerkki1.png"));
- 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 Oerkki1CAO::removeFromScene()
-{
- if(m_node == NULL)
- return;
-
- m_node->remove();
- m_node = NULL;
-}
-
-void Oerkki1CAO::updateLight(u8 light_at_pos)
-{
- if(m_node == NULL)
- return;
-
- if(light_at_pos <= 2)
- {
- m_node->setVisible(false);
- return;
- }
-
- m_node->setVisible(true);
-
- u8 li = decode_light(light_at_pos);
- video::SColor color(255,li,li,li);
- setMeshColor(m_node->getMesh(), color);
-}
-
-v3s16 Oerkki1CAO::getLightPosition()
-{
- return floatToInt(m_position+v3f(0,BS*1.5,0), BS);
-}
-
-void Oerkki1CAO::updateNodePos()
-{
- if(m_node == NULL)
- return;
-
- //m_node->setPosition(m_position);
- m_node->setPosition(pos_translator.vect_show);
-
- v3f rot = m_node->getRotation();
- rot.Y = 180.0 - m_yaw + 90.0;
- m_node->setRotation(rot);
-}
-
-void Oerkki1CAO::step(float dtime, ClientEnvironment *env)
-{
- ITextureSource *tsrc = m_gamedef->tsrc();
-
- pos_translator.translate(dtime);
- updateNodePos();
-
- LocalPlayer *player = env->getLocalPlayer();
- assert(player);
-
- v3f playerpos = player->getPosition();
- v2f playerpos_2d(playerpos.X,playerpos.Z);
- v2f objectpos_2d(m_position.X,m_position.Z);
-
- if(fabs(m_position.Y - playerpos.Y) < 1.5*BS &&
- objectpos_2d.getDistanceFrom(playerpos_2d) < 1.5*BS)
- {
- if(m_attack_interval.step(dtime, 0.5))
- {
- env->damageLocalPlayer(2);
- }
- }
-
- if(m_damage_visual_timer > 0)
- {
- if(!m_damage_texture_enabled)
- {
- // Enable damage texture
- if(m_node)
- {
- /*video::IVideoDriver* driver =
- m_node->getSceneManager()->getVideoDriver();*/
-
- scene::IMesh *mesh = m_node->getMesh();
- if(mesh == NULL)
- return;
-
- u16 mc = mesh->getMeshBufferCount();
- for(u16 j=0; j<mc; j++)
- {
- scene::IMeshBuffer *buf = mesh->getMeshBuffer(j);
- buf->getMaterial().setTexture(0,
- tsrc->getTextureRaw("oerkki1_damaged.png"));
- }
- }
- m_damage_texture_enabled = true;
- }
- m_damage_visual_timer -= dtime;
- }
- else
- {
- if(m_damage_texture_enabled)
- {
- // Disable damage texture
- if(m_node)
- {
- /*video::IVideoDriver* driver =
- m_node->getSceneManager()->getVideoDriver();*/
-
- scene::IMesh *mesh = m_node->getMesh();
- if(mesh == NULL)
- return;
-
- u16 mc = mesh->getMeshBufferCount();
- for(u16 j=0; j<mc; j++)
- {
- scene::IMeshBuffer *buf = mesh->getMeshBuffer(j);
- buf->getMaterial().setTexture(0,
- tsrc->getTextureRaw("oerkki1.png"));
- }
- }
- m_damage_texture_enabled = false;
- }
- }
-}
-
-void Oerkki1CAO::processMessage(const std::string &data)
-{
- //infostream<<"Oerkki1CAO: Got message"<<std::endl;
- std::istringstream is(data, std::ios::binary);
- // command
- u8 cmd = readU8(is);
- if(cmd == 0)
- {
- // pos
- m_position = readV3F1000(is);
- pos_translator.update(m_position);
- // yaw
- m_yaw = readF1000(is);
- updateNodePos();
- }
- else if(cmd == 1)
- {
- //u16 damage = readU8(is);
- m_damage_visual_timer = 1.0;
- }
-}
-
-void Oerkki1CAO::initialize(const std::string &data)
-{
- //infostream<<"Oerkki1CAO: 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);
- pos_translator.init(m_position);
- }
-
- updateNodePos();
-}
-
-bool Oerkki1CAO::directReportPunch(const std::string &toolname, v3f dir)
-{
- m_damage_visual_timer = 1.0;
-
- m_position += dir * BS;
- pos_translator.sharpen();
- pos_translator.update(m_position);
- updateNodePos();
-
- return false;
-}
-
-/*
- FireflyCAO
-*/
-
-// Prototype
-FireflyCAO proto_FireflyCAO(NULL, NULL);
-
-FireflyCAO::FireflyCAO(IGameDef *gamedef, ClientEnvironment *env):
- ClientActiveObject(0, gamedef, env),
- m_selection_box(-BS/3.,0.0,-BS/3., BS/3.,BS/2.,BS/3.),
- m_node(NULL),
- m_position(v3f(0,10*BS,0)),
- m_yaw(0)
-{
- ClientActiveObject::registerType(getType(), create);
-}
-
-FireflyCAO::~FireflyCAO()
-{
-}
-
-ClientActiveObject* FireflyCAO::create(IGameDef *gamedef, ClientEnvironment *env)
-{
- return new FireflyCAO(gamedef, env);
-}
-
-void FireflyCAO::addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc,
- IrrlichtDevice *irr)
-{
- 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(0,0,0, 0,0,0, c, 0,1),
- video::S3DVertex(BS/2,0,0, 0,0,0, c, 1,1),
- video::S3DVertex(BS/2,BS/2,0, 0,0,0, c, 1,0),
- video::S3DVertex(0,BS/2,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);
- buf->getMaterial().setTexture(0, tsrc->getTextureRaw("firefly.png"));
- 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 FireflyCAO::removeFromScene()
-{
- if(m_node == NULL)
- return;
-
- m_node->remove();
- m_node = NULL;
-}
-
-void FireflyCAO::updateLight(u8 light_at_pos)
-{
- if(m_node == NULL)
- return;
-
- u8 li = 255;
- video::SColor color(255,li,li,li);
- setMeshColor(m_node->getMesh(), color);
-}
-
-v3s16 FireflyCAO::getLightPosition()
-{
- return floatToInt(m_position+v3f(0,BS*0.5,0), BS);
-}
-
-void FireflyCAO::updateNodePos()
-{
- if(m_node == NULL)
- return;
-
- //m_node->setPosition(m_position);
- m_node->setPosition(pos_translator.vect_show);
-
- v3f rot = m_node->getRotation();
- rot.Y = 180.0 - m_yaw;
- m_node->setRotation(rot);
-}
-
-void FireflyCAO::step(float dtime, ClientEnvironment *env)
-{
- pos_translator.translate(dtime);
- updateNodePos();
-}
-
-void FireflyCAO::processMessage(const std::string &data)
-{
- //infostream<<"FireflyCAO: Got message"<<std::endl;
- std::istringstream is(data, std::ios::binary);
- // command
- u8 cmd = readU8(is);
- if(cmd == 0)
- {
- // pos
- m_position = readV3F1000(is);
- pos_translator.update(m_position);
- // yaw
- m_yaw = readF1000(is);
- updateNodePos();
- }
-}
-
-void FireflyCAO::initialize(const std::string &data)
-{
- //infostream<<"FireflyCAO: 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);
- pos_translator.init(m_position);
- }
-
- updateNodePos();
-}
-
-/*
- MobV2CAO
-*/
-
-// Prototype
-MobV2CAO proto_MobV2CAO(NULL, NULL);
-
-MobV2CAO::MobV2CAO(IGameDef *gamedef, ClientEnvironment *env):
- ClientActiveObject(0, gamedef, env),
- m_selection_box(-0.4*BS,-0.4*BS,-0.4*BS, 0.4*BS,0.8*BS,0.4*BS),
- m_node(NULL),
- m_position(v3f(0,10*BS,0)),
- m_yaw(0),
- m_walking(false),
- m_walking_unset_timer(0),
- m_walk_timer(0),
- m_walk_frame(0),
- m_damage_visual_timer(0),
- m_last_light(0),
- m_shooting(0),
- m_shooting_unset_timer(0),
- m_sprite_size(BS,BS),
- m_sprite_y(0),
- m_bright_shooting(false),
- m_lock_full_brightness(false),
- m_player_hit_timer(0)
-{
- ClientActiveObject::registerType(getType(), create);
-
- m_properties = new Settings;
-}
-
-MobV2CAO::~MobV2CAO()
-{
- delete m_properties;
-}
-
-ClientActiveObject* MobV2CAO::create(IGameDef *gamedef, ClientEnvironment *env)
-{
- return new MobV2CAO(gamedef, env);
-}
-
-void MobV2CAO::addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc,
- IrrlichtDevice *irr)
-{
- if(m_node != NULL)
- return;
-
- /*infostream<<"MobV2CAO::addToScene using texture_name="<<
- m_texture_name<<std::endl;*/
- std::string texture_string = m_texture_name +
- "^[makealpha:128,0,0^[makealpha:128,128,0";
-
- scene::IBillboardSceneNode *bill = smgr->addBillboardSceneNode(
- NULL, v2f(1, 1), v3f(0,0,0), -1);
- bill->setMaterialTexture(0, tsrc->getTextureRaw(texture_string));
- bill->setMaterialFlag(video::EMF_LIGHTING, false);
- bill->setMaterialFlag(video::EMF_BILINEAR_FILTER, false);
- bill->setMaterialType(video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF);
- bill->setMaterialFlag(video::EMF_FOG_ENABLE, true);
- bill->setColor(video::SColor(255,0,0,0));
- bill->setVisible(false); /* Set visible when brightness is known */
- bill->setSize(m_sprite_size);
- if(m_sprite_type == "humanoid_1"){
- const float txp = 1./192;
- const float txs = txp*32;
- const float typ = 1./240;
- const float tys = typ*48;
- setBillboardTextureMatrix(bill, txs, tys, 0, 0);
- } else if(m_sprite_type == "simple"){
- const float txs = 1.0;
- const float tys = 1.0 / m_simple_anim_frames;
- setBillboardTextureMatrix(bill, txs, tys, 0, 0);
- } else {
- infostream<<"MobV2CAO: Unknown sprite type \""<<m_sprite_type<<"\""
- <<std::endl;
- }
-
- m_node = bill;
-
- updateNodePos();
-}
-
-void MobV2CAO::removeFromScene()
-{
- if(m_node == NULL)
- return;
-
- m_node->remove();
- m_node = NULL;
-}
-
-void MobV2CAO::updateLight(u8 light_at_pos)
-{
- if(m_lock_full_brightness)
- light_at_pos = 15;
-
- m_last_light = light_at_pos;
-
- if(m_node == NULL)
- return;
-
- if(m_damage_visual_timer > 0)
- return;
-
- if(m_shooting && m_bright_shooting)
- return;
-
- /*if(light_at_pos <= 2){
- m_node->setVisible(false);
- return;
- }*/
-
- m_node->setVisible(true);
-
- u8 li = decode_light(light_at_pos);
- video::SColor color(255,li,li,li);
- m_node->setColor(color);
-}
-
-v3s16 MobV2CAO::getLightPosition()
-{
- return floatToInt(m_position+v3f(0,0,0), BS);
-}
-
-void MobV2CAO::updateNodePos()
-{
- if(m_node == NULL)
- return;
-
- m_node->setPosition(pos_translator.vect_show + v3f(0,m_sprite_y,0));
-}
-
-void MobV2CAO::step(float dtime, ClientEnvironment *env)
-{
- scene::IBillboardSceneNode *bill = m_node;
- if(!bill)
- return;
-
- pos_translator.translate(dtime);
-
- if(m_sprite_type == "humanoid_1"){
- scene::ICameraSceneNode* camera = m_node->getSceneManager()->getActiveCamera();
- if(!camera)
- return;
- v3f cam_to_mob = m_node->getAbsolutePosition() - camera->getAbsolutePosition();
- cam_to_mob.normalize();
- int col = 0;
- if(cam_to_mob.Y > 0.75)
- col = 5;
- else if(cam_to_mob.Y < -0.75)
- col = 4;
- else{
- float mob_dir = atan2(cam_to_mob.Z, cam_to_mob.X) / PI * 180.;
- float dir = mob_dir - m_yaw;
- dir = wrapDegrees_180(dir);
- //infostream<<"id="<<m_id<<" dir="<<dir<<std::endl;
- if(fabs(wrapDegrees_180(dir - 0)) <= 45.1)
- col = 2;
- else if(fabs(wrapDegrees_180(dir - 90)) <= 45.1)
- col = 3;
- else if(fabs(wrapDegrees_180(dir - 180)) <= 45.1)
- col = 0;
- else if(fabs(wrapDegrees_180(dir + 90)) <= 45.1)
- col = 1;
- else
- col = 4;
- }
-
- int row = 0;
- if(m_shooting){
- row = 3;
- } else if(m_walking){
- m_walk_timer += dtime;
- if(m_walk_timer >= 0.5){
- m_walk_frame = (m_walk_frame + 1) % 2;
- m_walk_timer = 0;
- }
- if(m_walk_frame == 0)
- row = 1;
- else
- row = 2;
- }
-
- const float txp = 1./192;
- const float txs = txp*32;
- const float typ = 1./240;
- const float tys = typ*48;
- setBillboardTextureMatrix(bill, txs, tys, col, row);
- } else if(m_sprite_type == "simple"){
- m_walk_timer += dtime;
- if(m_walk_timer >= m_simple_anim_frametime){
- m_walk_frame = (m_walk_frame + 1) % m_simple_anim_frames;
- m_walk_timer = 0;
- }
- int col = 0;
- int row = m_walk_frame;
- const float txs = 1.0;
- const float tys = 1.0 / m_simple_anim_frames;
- setBillboardTextureMatrix(bill, txs, tys, col, row);
- } else {
- infostream<<"MobV2CAO::step(): Unknown sprite type \""
- <<m_sprite_type<<"\""<<std::endl;
- }
-
- updateNodePos();
-
- /* Damage local player */
- if(m_player_hit_damage && m_player_hit_timer <= 0.0){
- LocalPlayer *player = env->getLocalPlayer();
- assert(player);
-
- v3f playerpos = player->getPosition();
- v2f playerpos_2d(playerpos.X,playerpos.Z);
- v2f objectpos_2d(m_position.X,m_position.Z);
-
- if(fabs(m_position.Y - playerpos.Y) < m_player_hit_distance*BS &&
- objectpos_2d.getDistanceFrom(playerpos_2d) < m_player_hit_distance*BS)
- {
- env->damageLocalPlayer(m_player_hit_damage);
- m_player_hit_timer = m_player_hit_interval;
- }
- }
-
- /* Run timers */
-
- m_player_hit_timer -= dtime;
-
- if(m_damage_visual_timer >= 0){
- m_damage_visual_timer -= dtime;
- if(m_damage_visual_timer <= 0){
- infostream<<"id="<<m_id<<" damage visual ended"<<std::endl;
- }
- }
-
- m_walking_unset_timer += dtime;
- if(m_walking_unset_timer >= 1.0){
- m_walking = false;
- }
-
- m_shooting_unset_timer -= dtime;
- if(m_shooting_unset_timer <= 0.0){
- if(m_bright_shooting){
- u8 li = decode_light(m_last_light);
- video::SColor color(255,li,li,li);
- bill->setColor(color);
- m_bright_shooting = false;
- }
- m_shooting = false;
- }
-
-}
-
-void MobV2CAO::processMessage(const std::string &data)
-{
- //infostream<<"MobV2CAO: Got message"<<std::endl;
- std::istringstream is(data, std::ios::binary);
- // command
- u8 cmd = readU8(is);
-
- // Move
- if(cmd == 0)
- {
- // pos
- m_position = readV3F1000(is);
- pos_translator.update(m_position);
- // yaw
- m_yaw = readF1000(is);
-
- m_walking = true;
- m_walking_unset_timer = 0;
-
- updateNodePos();
- }
- // Damage
- else if(cmd == 1)
- {
- //u16 damage = readU16(is);
-
- /*u8 li = decode_light(m_last_light);
- if(li >= 100)
- li = 30;
- else
- li = 255;*/
-
- /*video::SColor color(255,255,0,0);
- m_node->setColor(color);
-
- m_damage_visual_timer = 0.2;*/
- }
- // Trigger shooting
- else if(cmd == 2)
- {
- // length
- m_shooting_unset_timer = readF1000(is);
- // bright?
- m_bright_shooting = readU8(is);
- if(m_bright_shooting){
- u8 li = 255;
- video::SColor color(255,li,li,li);
- m_node->setColor(color);
- }
-
- m_shooting = true;
- }
-}
-
-void MobV2CAO::initialize(const std::string &data)
-{
- //infostream<<"MobV2CAO: Got init data"<<std::endl;
-
- {
- std::istringstream is(data, std::ios::binary);
- // version
- u8 version = readU8(is);
- // check version
- if(version != 0){
- infostream<<__FUNCTION_NAME<<": Invalid version"<<std::endl;
- return;
- }
-
- std::ostringstream tmp_os(std::ios::binary);
- decompressZlib(is, tmp_os);
- std::istringstream tmp_is(tmp_os.str(), std::ios::binary);
- m_properties->parseConfigLines(tmp_is, "MobArgsEnd");
-
- infostream<<"MobV2CAO::initialize(): got properties:"<<std::endl;
- m_properties->writeLines(infostream);
-
- m_properties->setDefault("looks", "dummy_default");
- m_properties->setDefault("yaw", "0");
- m_properties->setDefault("pos", "(0,0,0)");
- m_properties->setDefault("player_hit_damage", "0");
- m_properties->setDefault("player_hit_distance", "1.5");
- m_properties->setDefault("player_hit_interval", "1.5");
-
- setLooks(m_properties->get("looks"));
- m_yaw = m_properties->getFloat("yaw");
- m_position = m_properties->getV3F("pos");
- m_player_hit_damage = m_properties->getS32("player_hit_damage");
- m_player_hit_distance = m_properties->getFloat("player_hit_distance");
- m_player_hit_interval = m_properties->getFloat("player_hit_interval");
-
- pos_translator.init(m_position);
- }
-
- updateNodePos();
-}
-
-bool MobV2CAO::directReportPunch(const std::string &toolname, v3f dir)
-{
- video::SColor color(255,255,0,0);
- m_node->setColor(color);
-
- m_damage_visual_timer = 0.05;
-
- m_position += dir * BS;
- pos_translator.sharpen();
- pos_translator.update(m_position);
- updateNodePos();
-
- return false;
-}
-
-void MobV2CAO::setLooks(const std::string &looks)
-{
- v2f selection_size = v2f(0.4, 0.4) * BS;
- float selection_y = 0 * BS;
-
- if(looks == "dungeon_master"){
- m_texture_name = "dungeon_master.png";
- m_sprite_type = "humanoid_1";
- m_sprite_size = v2f(2, 3) * BS;
- m_sprite_y = 0.85 * BS;
- selection_size = v2f(0.4, 2.6) * BS;
- selection_y = -0.4 * BS;
- }
- else if(looks == "fireball"){
- m_texture_name = "fireball.png";
- m_sprite_type = "simple";
- m_sprite_size = v2f(1, 1) * BS;
- m_simple_anim_frames = 3;
- m_simple_anim_frametime = 0.1;
- m_lock_full_brightness = true;
- }
- else{
- m_texture_name = "stone.png";
- m_sprite_type = "simple";
- m_sprite_size = v2f(1, 1) * BS;
- m_simple_anim_frames = 3;
- m_simple_anim_frametime = 0.333;
- selection_size = v2f(0.4, 0.4) * BS;
- selection_y = 0 * BS;
- }
-
- m_selection_box = core::aabbox3d<f32>(
- -selection_size.X, selection_y, -selection_size.X,
- selection_size.X, selection_y+selection_size.Y,
- selection_size.X);
-}
-
-/*
LuaEntityCAO
*/
@@ -1691,6 +226,7 @@ private:
v3f m_velocity;
v3f m_acceleration;
float m_yaw;
+ s16 m_hp;
struct LuaEntityProperties *m_prop;
SmoothTranslator pos_translator;
// Spritesheet/animation stuff
@@ -1712,6 +248,7 @@ public:
m_velocity(v3f(0,0,0)),
m_acceleration(v3f(0,0,0)),
m_yaw(0),
+ m_hp(1),
m_prop(new LuaEntityProperties),
m_tx_size(1,1),
m_tx_basepos(0,0),
@@ -1733,12 +270,14 @@ public:
// version
u8 version = readU8(is);
// check version
- if(version != 0)
+ if(version != 1)
return;
// pos
m_position = readV3F1000(is);
// yaw
m_yaw = readF1000(is);
+ // hp
+ m_hp = readS16(is);
// properties
std::istringstream prop_is(deSerializeLongString(is), std::ios::binary);
m_prop->deSerialize(prop_is);
@@ -2000,7 +539,7 @@ public:
std::istringstream is(data, std::ios::binary);
// command
u8 cmd = readU8(is);
- if(cmd == 0) // update position
+ if(cmd == LUAENTITY_CMD_UPDATE_POSITION) // update position
{
// do_interpolate
bool do_interpolate = readU8(is);
@@ -2025,12 +564,12 @@ public:
}
updateNodePos();
}
- else if(cmd == 1) // set texture modification
+ else if(cmd == LUAENTITY_CMD_SET_TEXTURE_MOD) // set texture modification
{
std::string mod = deSerializeString(is);
updateTextures(mod);
}
- else if(cmd == 2) // set sprite
+ else if(cmd == LUAENTITY_CMD_SET_SPRITE) // set sprite
{
v2s16 p = readV2S16(is);
int num_frames = readU16(is);
@@ -2044,6 +583,14 @@ public:
updateTexturePos();
}
+ else if(cmd == LUAENTITY_CMD_PUNCHED)
+ {
+ s16 damage = readS16(is);
+ s16 result_hp = readS16(is);
+
+ m_hp = result_hp;
+ // TODO: Execute defined fast response
+ }
}
};
diff --git a/src/content_sao.cpp b/src/content_sao.cpp
index b7a6db906..5c03c9053 100644
--- a/src/content_sao.cpp
+++ b/src/content_sao.cpp
@@ -29,1508 +29,306 @@ with this program; if not, write to the Free Software Foundation, Inc.,
core::map<u16, ServerActiveObject::Factory> ServerActiveObject::m_types;
-/* Some helper functions */
-
-// Y is copied, X and Z change is limited
-void accelerate_xz(v3f &speed, v3f target_speed, f32 max_increase)
-{
- v3f d_wanted = target_speed - speed;
- d_wanted.Y = 0;
- f32 dl_wanted = d_wanted.getLength();
- f32 dl = dl_wanted;
- if(dl > max_increase)
- dl = max_increase;
-
- v3f d = d_wanted.normalize() * dl;
-
- speed.X += d.X;
- speed.Z += d.Z;
- speed.Y = target_speed.Y;
-}
-
/*
- TestSAO
+ DummyLoadSAO
*/
-// Prototype
-TestSAO proto_TestSAO(NULL, v3f(0,0,0));
-
-TestSAO::TestSAO(ServerEnvironment *env, v3f pos):
- ServerActiveObject(env, pos),
- m_timer1(0),
- m_age(0)
-{
- ServerActiveObject::registerType(getType(), create);
-}
-
-ServerActiveObject* TestSAO::create(ServerEnvironment *env, v3f pos,
- const std::string &data)
+class DummyLoadSAO : public ServerActiveObject
{
- return new TestSAO(env, pos);
-}
-
-void TestSAO::step(float dtime, bool send_recommended)
-{
- m_age += dtime;
- if(m_age > 10)
+public:
+ DummyLoadSAO(ServerEnvironment *env, v3f pos, u8 type):
+ ServerActiveObject(env, pos)
{
- m_removed = true;
- return;
+ ServerActiveObject::registerType(type, create);
}
-
- m_base_position.Y += dtime * BS * 2;
- if(m_base_position.Y > 8*BS)
- m_base_position.Y = 2*BS;
-
- if(send_recommended == false)
- return;
-
- m_timer1 -= dtime;
- if(m_timer1 < 0.0)
+ // Pretend to be the test object (to fool the client)
+ u8 getType() const
+ { return ACTIVEOBJECT_TYPE_TEST; }
+ // And never save to disk
+ bool isStaticAllowed() const
+ { return false; }
+
+ static ServerActiveObject* create(ServerEnvironment *env, v3f pos,
+ const std::string &data)
{
- m_timer1 += 0.125;
-
- std::string data;
-
- data += itos(0); // 0 = position
- data += " ";
- data += itos(m_base_position.X);
- data += " ";
- data += itos(m_base_position.Y);
- data += " ";
- data += itos(m_base_position.Z);
-
- ActiveObjectMessage aom(getId(), false, data);
- m_messages_out.push_back(aom);
+ return new DummyLoadSAO(env, pos, 0);
}
-}
-
-/*
- ItemSAO
-*/
-
-// Prototype
-ItemSAO proto_ItemSAO(NULL, v3f(0,0,0), "");
-
-ItemSAO::ItemSAO(ServerEnvironment *env, v3f pos,
- const std::string itemstring):
- ServerActiveObject(env, pos),
- m_itemstring(itemstring),
- m_itemstring_changed(false),
- m_speed_f(0,0,0),
- m_last_sent_position(0,0,0)
-{
- ServerActiveObject::registerType(getType(), create);
-}
-
-ServerActiveObject* ItemSAO::create(ServerEnvironment *env, v3f pos,
- const std::string &data)
-{
- std::istringstream is(data, std::ios::binary);
- char buf[1];
- // read version
- is.read(buf, 1);
- u8 version = buf[0];
- // check if version is supported
- if(version != 0)
- return NULL;
- std::string itemstring = deSerializeString(is);
- infostream<<"ItemSAO::create(): Creating item \""
- <<itemstring<<"\""<<std::endl;
- return new ItemSAO(env, pos, itemstring);
-}
-
-void ItemSAO::step(float dtime, bool send_recommended)
-{
- ScopeProfiler sp2(g_profiler, "ItemSAO::step avg", SPT_AVG);
-
- assert(m_env);
-
- const float interval = 0.2;
- if(m_move_interval.step(dtime, interval)==false)
- return;
- dtime = interval;
-
- core::aabbox3d<f32> box(-BS/3.,0.0,-BS/3., BS/3.,BS*2./3.,BS/3.);
- collisionMoveResult moveresult;
- // Apply gravity
- m_speed_f += v3f(0, -dtime*9.81*BS, 0);
- // Maximum movement without glitches
- f32 pos_max_d = BS*0.25;
- // Limit speed
- if(m_speed_f.getLength()*dtime > pos_max_d)
- m_speed_f *= pos_max_d / (m_speed_f.getLength()*dtime);
- v3f pos_f = getBasePosition();
- v3f pos_f_old = pos_f;
- IGameDef *gamedef = m_env->getGameDef();
- moveresult = collisionMoveSimple(&m_env->getMap(), gamedef,
- pos_max_d, box, dtime, pos_f, m_speed_f);
-
- if(send_recommended == false)
- return;
-
- if(pos_f.getDistanceFrom(m_last_sent_position) > 0.05*BS)
+ void step(float dtime, bool send_recommended)
{
- setBasePosition(pos_f);
- m_last_sent_position = pos_f;
-
- std::ostringstream os(std::ios::binary);
- // command (0 = update position)
- writeU8(os, 0);
- // pos
- writeV3F1000(os, m_base_position);
- // create message and add to list
- ActiveObjectMessage aom(getId(), false, os.str());
- m_messages_out.push_back(aom);
+ m_removed = true;
+ infostream<<"DummyLoadSAO step"<<std::endl;
}
- if(m_itemstring_changed)
- {
- m_itemstring_changed = false;
- std::ostringstream os(std::ios::binary);
- // command (1 = update itemstring)
- writeU8(os, 1);
- // itemstring
- os<<serializeString(m_itemstring);
- // create message and add to list
- ActiveObjectMessage aom(getId(), false, os.str());
- m_messages_out.push_back(aom);
- }
-}
+private:
+};
-std::string ItemSAO::getClientInitializationData()
-{
- std::ostringstream os(std::ios::binary);
- // version
- writeU8(os, 0);
- // pos
- writeV3F1000(os, m_base_position);
- // itemstring
- os<<serializeString(m_itemstring);
- return os.str();
-}
+// Prototype (registers item for deserialization)
+DummyLoadSAO proto1_DummyLoadSAO(NULL, v3f(0,0,0), ACTIVEOBJECT_TYPE_RAT);
+DummyLoadSAO proto2_DummyLoadSAO(NULL, v3f(0,0,0), ACTIVEOBJECT_TYPE_OERKKI1);
+DummyLoadSAO proto3_DummyLoadSAO(NULL, v3f(0,0,0), ACTIVEOBJECT_TYPE_FIREFLY);
+DummyLoadSAO proto4_DummyLoadSAO(NULL, v3f(0,0,0), ACTIVEOBJECT_TYPE_MOBV2);
-std::string ItemSAO::getStaticData()
-{
- infostream<<__FUNCTION_NAME<<std::endl;
- std::ostringstream os(std::ios::binary);
- // version
- writeU8(os, 0);
- // itemstring
- os<<serializeString(m_itemstring);
- return os.str();
-}
+/*
+ TestSAO
+*/
-ItemStack ItemSAO::createItemStack()
+class TestSAO : public ServerActiveObject
{
- try{
- IItemDefManager *idef = m_env->getGameDef()->idef();
- ItemStack item;
- item.deSerialize(m_itemstring, idef);
- infostream<<__FUNCTION_NAME<<": m_itemstring=\""<<m_itemstring
- <<"\" -> item=\""<<item.getItemString()<<"\""
- <<std::endl;
- return item;
- }
- catch(SerializationError &e)
+public:
+ TestSAO(ServerEnvironment *env, v3f pos):
+ ServerActiveObject(env, pos),
+ m_timer1(0),
+ m_age(0)
{
- infostream<<__FUNCTION_NAME<<": serialization error: "
- <<"m_itemstring=\""<<m_itemstring<<"\""<<std::endl;
- return ItemStack();
+ ServerActiveObject::registerType(getType(), create);
}
-}
-
-void ItemSAO::punch(ServerActiveObject *puncher, float time_from_last_punch)
-{
- // Allow removing items in creative mode
- if(g_settings->getBool("creative_mode") == true)
+ u8 getType() const
+ { return ACTIVEOBJECT_TYPE_TEST; }
+
+ static ServerActiveObject* create(ServerEnvironment *env, v3f pos,
+ const std::string &data)
{
- m_removed = true;
- return;
+ return new TestSAO(env, pos);
}
- ItemStack item = createItemStack();
- Inventory *inv = puncher->getInventory();
- if(inv != NULL)
+ void step(float dtime, bool send_recommended)
{
- std::string wieldlist = puncher->getWieldList();
- ItemStack leftover = inv->addItem(wieldlist, item);
- puncher->setInventoryModified();
- if(leftover.empty())
+ m_age += dtime;
+ if(m_age > 10)
{
m_removed = true;
+ return;
}
- else
- {
- m_itemstring = leftover.getItemString();
- m_itemstring_changed = true;
- }
- }
-}
-
-/*
- RatSAO
-*/
-// Prototype
-RatSAO proto_RatSAO(NULL, v3f(0,0,0));
+ m_base_position.Y += dtime * BS * 2;
+ if(m_base_position.Y > 8*BS)
+ m_base_position.Y = 2*BS;
-RatSAO::RatSAO(ServerEnvironment *env, v3f pos):
- ServerActiveObject(env, pos),
- m_is_active(false),
- m_speed_f(0,0,0)
-{
- ServerActiveObject::registerType(getType(), create);
-
- m_oldpos = v3f(0,0,0);
- m_last_sent_position = v3f(0,0,0);
- m_yaw = myrand_range(0,PI*2);
- m_counter1 = 0;
- m_counter2 = 0;
- m_age = 0;
- m_touching_ground = false;
-}
-
-ServerActiveObject* RatSAO::create(ServerEnvironment *env, v3f pos,
- const std::string &data)
-{
- std::istringstream is(data, std::ios::binary);
- char buf[1];
- // read version
- is.read(buf, 1);
- u8 version = buf[0];
- // check if version is supported
- if(version != 0)
- return NULL;
- return new RatSAO(env, pos);
-}
-
-void RatSAO::step(float dtime, bool send_recommended)
-{
- ScopeProfiler sp2(g_profiler, "RatSAO::step avg", SPT_AVG);
-
- assert(m_env);
-
- if(m_is_active == false)
- {
- if(m_inactive_interval.step(dtime, 0.5)==false)
+ if(send_recommended == false)
return;
- }
-
- /*
- The AI
- */
-
- /*m_age += dtime;
- if(m_age > 60)
- {
- // Die
- m_removed = true;
- return;
- }*/
-
- // Apply gravity
- m_speed_f.Y -= dtime*9.81*BS;
-
- /*
- Move around if some player is close
- */
- bool player_is_close = false;
- // Check connected players
- core::list<Player*> players = m_env->getPlayers(true);
- core::list<Player*>::Iterator i;
- for(i = players.begin();
- i != players.end(); i++)
- {
- Player *player = *i;
- v3f playerpos = player->getPosition();
- if(m_base_position.getDistanceFrom(playerpos) < BS*10.0)
- {
- player_is_close = true;
- break;
- }
- }
-
- m_is_active = player_is_close;
-
- if(player_is_close == false)
- {
- m_speed_f.X = 0;
- m_speed_f.Z = 0;
- }
- else
- {
- // Move around
- v3f dir(cos(m_yaw/180*PI),0,sin(m_yaw/180*PI));
- f32 speed = 2*BS;
- m_speed_f.X = speed * dir.X;
- m_speed_f.Z = speed * dir.Z;
-
- if(m_touching_ground && (m_oldpos - m_base_position).getLength()
- < dtime*speed/2)
- {
- m_counter1 -= dtime;
- if(m_counter1 < 0.0)
- {
- m_counter1 += 1.0;
- m_speed_f.Y = 5.0*BS;
- }
- }
+ m_timer1 -= dtime;
+ if(m_timer1 < 0.0)
{
- m_counter2 -= dtime;
- if(m_counter2 < 0.0)
- {
- m_counter2 += (float)(myrand()%100)/100*3.0;
- m_yaw += ((float)(myrand()%200)-100)/100*180;
- m_yaw = wrapDegrees(m_yaw);
- }
- }
- }
-
- m_oldpos = m_base_position;
-
- /*
- Move it, with collision detection
- */
-
- core::aabbox3d<f32> box(-BS/3.,0.0,-BS/3., BS/3.,BS*2./3.,BS/3.);
- collisionMoveResult moveresult;
- // Maximum movement without glitches
- f32 pos_max_d = BS*0.25;
- // Limit speed
- if(m_speed_f.getLength()*dtime > pos_max_d)
- m_speed_f *= pos_max_d / (m_speed_f.getLength()*dtime);
- v3f pos_f = getBasePosition();
- v3f pos_f_old = pos_f;
- IGameDef *gamedef = m_env->getGameDef();
- moveresult = collisionMoveSimple(&m_env->getMap(), gamedef,
- pos_max_d, box, dtime, pos_f, m_speed_f);
- m_touching_ground = moveresult.touching_ground;
-
- setBasePosition(pos_f);
+ m_timer1 += 0.125;
- if(send_recommended == false)
- return;
+ std::string data;
- if(pos_f.getDistanceFrom(m_last_sent_position) > 0.05*BS)
- {
- m_last_sent_position = pos_f;
+ data += itos(0); // 0 = position
+ data += " ";
+ data += itos(m_base_position.X);
+ data += " ";
+ data += itos(m_base_position.Y);
+ data += " ";
+ data += itos(m_base_position.Z);
- std::ostringstream os(std::ios::binary);
- // command (0 = update position)
- writeU8(os, 0);
- // pos
- writeV3F1000(os, m_base_position);
- // yaw
- writeF1000(os, m_yaw);
- // create message and add to list
- ActiveObjectMessage aom(getId(), false, os.str());
- m_messages_out.push_back(aom);
+ ActiveObjectMessage aom(getId(), false, data);
+ m_messages_out.push_back(aom);
+ }
}
-}
-
-std::string RatSAO::getClientInitializationData()
-{
- std::ostringstream os(std::ios::binary);
- // version
- writeU8(os, 0);
- // pos
- writeV3F1000(os, m_base_position);
- return os.str();
-}
-
-std::string RatSAO::getStaticData()
-{
- //infostream<<__FUNCTION_NAME<<std::endl;
- std::ostringstream os(std::ios::binary);
- // version
- writeU8(os, 0);
- return os.str();
-}
-void RatSAO::punch(ServerActiveObject *puncher, float time_from_last_punch)
-{
- // Allow removing rats in creative mode
- if(g_settings->getBool("creative_mode") == true)
- {
- m_removed = true;
- return;
- }
+private:
+ float m_timer1;
+ float m_age;
+};
- IItemDefManager *idef = m_env->getGameDef()->idef();
- ItemStack item("rat", 1, 0, "", idef);
- Inventory *inv = puncher->getInventory();
- if(inv != NULL)
- {
- std::string wieldlist = puncher->getWieldList();
- ItemStack leftover = inv->addItem(wieldlist, item);
- puncher->setInventoryModified();
- if(leftover.empty())
- m_removed = true;
- }
-}
+// Prototype (registers item for deserialization)
+TestSAO proto_TestSAO(NULL, v3f(0,0,0));
/*
- Oerkki1SAO
+ ItemSAO
*/
-// Prototype
-Oerkki1SAO proto_Oerkki1SAO(NULL, v3f(0,0,0));
-
-Oerkki1SAO::Oerkki1SAO(ServerEnvironment *env, v3f pos):
- ServerActiveObject(env, pos),
- m_is_active(false),
- m_speed_f(0,0,0)
-{
- ServerActiveObject::registerType(getType(), create);
-
- m_oldpos = v3f(0,0,0);
- m_last_sent_position = v3f(0,0,0);
- m_yaw = 0;
- m_counter1 = 0;
- m_counter2 = 0;
- m_age = 0;
- m_touching_ground = false;
- m_hp = 20;
- m_after_jump_timer = 0;
-}
-
-ServerActiveObject* Oerkki1SAO::create(ServerEnvironment *env, v3f pos,
- const std::string &data)
+class ItemSAO : public ServerActiveObject
{
- std::istringstream is(data, std::ios::binary);
- // read version
- u8 version = readU8(is);
- // read hp
- u8 hp = readU8(is);
- // check if version is supported
- if(version != 0)
- return NULL;
- Oerkki1SAO *o = new Oerkki1SAO(env, pos);
- o->m_hp = hp;
- return o;
-}
-
-void Oerkki1SAO::step(float dtime, bool send_recommended)
-{
- ScopeProfiler sp2(g_profiler, "Oerkki1SAO::step avg", SPT_AVG);
-
- assert(m_env);
-
- if(m_is_active == false)
+public:
+ u8 getType() const
+ { return ACTIVEOBJECT_TYPE_ITEM; }
+
+ float getMinimumSavedMovement()
+ { return 0.1*BS; }
+
+ static ServerActiveObject* create(ServerEnvironment *env, v3f pos,
+ const std::string &data)
+ {
+ std::istringstream is(data, std::ios::binary);
+ char buf[1];
+ // read version
+ is.read(buf, 1);
+ u8 version = buf[0];
+ // check if version is supported
+ if(version != 0)
+ return NULL;
+ std::string itemstring = deSerializeString(is);
+ infostream<<"create(): Creating item \""
+ <<itemstring<<"\""<<std::endl;
+ return new ItemSAO(env, pos, itemstring);
+ }
+
+ ItemSAO(ServerEnvironment *env, v3f pos,
+ const std::string itemstring):
+ ServerActiveObject(env, pos),
+ m_itemstring(itemstring),
+ m_itemstring_changed(false),
+ m_speed_f(0,0,0),
+ m_last_sent_position(0,0,0)
{
- if(m_inactive_interval.step(dtime, 0.5)==false)
- return;
+ ServerActiveObject::registerType(getType(), create);
}
- /*
- The AI
- */
-
- m_age += dtime;
- if(m_age > 120)
+ void step(float dtime, bool send_recommended)
{
- // Die
- m_removed = true;
- return;
- }
-
- m_after_jump_timer -= dtime;
-
- v3f old_speed = m_speed_f;
+ ScopeProfiler sp2(g_profiler, "step avg", SPT_AVG);
- // Apply gravity
- m_speed_f.Y -= dtime*9.81*BS;
+ assert(m_env);
- /*
- Move around if some player is close
- */
- bool player_is_close = false;
- bool player_is_too_close = false;
- v3f near_player_pos;
- // Check connected players
- core::list<Player*> players = m_env->getPlayers(true);
- core::list<Player*>::Iterator i;
- for(i = players.begin();
- i != players.end(); i++)
- {
- Player *player = *i;
- v3f playerpos = player->getPosition();
- f32 dist = m_base_position.getDistanceFrom(playerpos);
- if(dist < BS*0.6)
- {
- m_removed = true;
+ const float interval = 0.2;
+ if(m_move_interval.step(dtime, interval)==false)
return;
- player_is_too_close = true;
- near_player_pos = playerpos;
- }
- else if(dist < BS*15.0 && !player_is_too_close)
- {
- player_is_close = true;
- near_player_pos = playerpos;
- }
- }
-
- m_is_active = player_is_close;
-
- v3f target_speed = m_speed_f;
-
- if(!player_is_close)
- {
- target_speed = v3f(0,0,0);
- }
- else
- {
- // Move around
-
- v3f ndir = near_player_pos - m_base_position;
- ndir.Y = 0;
- ndir.normalize();
-
- f32 nyaw = 180./PI*atan2(ndir.Z,ndir.X);
- if(nyaw < m_yaw - 180)
- nyaw += 360;
- else if(nyaw > m_yaw + 180)
- nyaw -= 360;
- m_yaw = 0.95*m_yaw + 0.05*nyaw;
- m_yaw = wrapDegrees(m_yaw);
+ dtime = interval;
- f32 speed = 2*BS;
-
- if((m_touching_ground || m_after_jump_timer > 0.0)
- && !player_is_too_close)
- {
- v3f dir(cos(m_yaw/180*PI),0,sin(m_yaw/180*PI));
- target_speed.X = speed * dir.X;
- target_speed.Z = speed * dir.Z;
- }
+ core::aabbox3d<f32> box(-BS/3.,0.0,-BS/3., BS/3.,BS*2./3.,BS/3.);
+ collisionMoveResult moveresult;
+ // Apply gravity
+ m_speed_f += v3f(0, -dtime*9.81*BS, 0);
+ // Maximum movement without glitches
+ f32 pos_max_d = BS*0.25;
+ // Limit speed
+ if(m_speed_f.getLength()*dtime > pos_max_d)
+ m_speed_f *= pos_max_d / (m_speed_f.getLength()*dtime);
+ v3f pos_f = getBasePosition();
+ v3f pos_f_old = pos_f;
+ IGameDef *gamedef = m_env->getGameDef();
+ moveresult = collisionMoveSimple(&m_env->getMap(), gamedef,
+ pos_max_d, box, dtime, pos_f, m_speed_f);
+
+ if(send_recommended == false)
+ return;
- if(m_touching_ground && (m_oldpos - m_base_position).getLength()
- < dtime*speed/2)
+ if(pos_f.getDistanceFrom(m_last_sent_position) > 0.05*BS)
{
- m_counter1 -= dtime;
- if(m_counter1 < 0.0)
- {
- m_counter1 += 0.2;
- // Jump
- target_speed.Y = 5.0*BS;
- m_after_jump_timer = 1.0;
- }
+ setBasePosition(pos_f);
+ m_last_sent_position = pos_f;
+
+ std::ostringstream os(std::ios::binary);
+ // command (0 = update position)
+ writeU8(os, 0);
+ // pos
+ writeV3F1000(os, m_base_position);
+ // create message and add to list
+ ActiveObjectMessage aom(getId(), false, os.str());
+ m_messages_out.push_back(aom);
}
-
+ if(m_itemstring_changed)
{
- m_counter2 -= dtime;
- if(m_counter2 < 0.0)
- {
- m_counter2 += (float)(myrand()%100)/100*3.0;
- //m_yaw += ((float)(myrand()%200)-100)/100*180;
- m_yaw += ((float)(myrand()%200)-100)/100*90;
- m_yaw = wrapDegrees(m_yaw);
- }
+ m_itemstring_changed = false;
+
+ std::ostringstream os(std::ios::binary);
+ // command (1 = update itemstring)
+ writeU8(os, 1);
+ // itemstring
+ os<<serializeString(m_itemstring);
+ // create message and add to list
+ ActiveObjectMessage aom(getId(), false, os.str());
+ m_messages_out.push_back(aom);
}
}
-
- if((m_speed_f - target_speed).getLength() > BS*4 || player_is_too_close)
- accelerate_xz(m_speed_f, target_speed, dtime*BS*8);
- else
- accelerate_xz(m_speed_f, target_speed, dtime*BS*4);
-
- m_oldpos = m_base_position;
-
- /*
- Move it, with collision detection
- */
-
- core::aabbox3d<f32> box(-BS/3.,0.0,-BS/3., BS/3.,BS*5./3.,BS/3.);
- collisionMoveResult moveresult;
- // Maximum movement without glitches
- f32 pos_max_d = BS*0.25;
- /*// Limit speed
- if(m_speed_f.getLength()*dtime > pos_max_d)
- m_speed_f *= pos_max_d / (m_speed_f.getLength()*dtime);*/
- v3f pos_f = getBasePosition();
- v3f pos_f_old = pos_f;
- IGameDef *gamedef = m_env->getGameDef();
- moveresult = collisionMovePrecise(&m_env->getMap(), gamedef,
- pos_max_d, box, dtime, pos_f, m_speed_f);
- m_touching_ground = moveresult.touching_ground;
-
- // Do collision damage
- float tolerance = BS*30;
- float factor = BS*0.5;
- v3f speed_diff = old_speed - m_speed_f;
- // Increase effect in X and Z
- speed_diff.X *= 2;
- speed_diff.Z *= 2;
- float vel = speed_diff.getLength();
- if(vel > tolerance)
- {
- f32 damage_f = (vel - tolerance)/BS*factor;
- u16 damage = (u16)(damage_f+0.5);
- doDamage(damage);
- }
-
- setBasePosition(pos_f);
- if(send_recommended == false && m_speed_f.getLength() < 3.0*BS)
- return;
-
- if(pos_f.getDistanceFrom(m_last_sent_position) > 0.05*BS)
+ std::string getClientInitializationData()
{
- m_last_sent_position = pos_f;
-
std::ostringstream os(std::ios::binary);
- // command (0 = update position)
+ // version
writeU8(os, 0);
// pos
writeV3F1000(os, m_base_position);
- // yaw
- writeF1000(os, m_yaw);
- // create message and add to list
- ActiveObjectMessage aom(getId(), false, os.str());
- m_messages_out.push_back(aom);
- }
-}
-
-std::string Oerkki1SAO::getClientInitializationData()
-{
- std::ostringstream os(std::ios::binary);
- // version
- writeU8(os, 0);
- // pos
- writeV3F1000(os, m_base_position);
- return os.str();
-}
-
-std::string Oerkki1SAO::getStaticData()
-{
- //infostream<<__FUNCTION_NAME<<std::endl;
- std::ostringstream os(std::ios::binary);
- // version
- writeU8(os, 0);
- // hp
- writeU8(os, m_hp);
- return os.str();
-}
-
-void Oerkki1SAO::punch(ServerActiveObject *puncher, float time_from_last_punch)
-{
- if(!puncher)
- return;
-
- v3f dir = (getBasePosition() - puncher->getBasePosition()).normalize();
- m_speed_f += dir*12*BS;
-
- // "Material" groups of the object
- ItemGroupList groups;
- groups["snappy"] = 1;
- groups["choppy"] = 1;
- groups["fleshy"] = 3;
-
- IItemDefManager *idef = m_env->getGameDef()->idef();
- ItemStack punchitem = puncher->getWieldedItem();
- ToolCapabilities tp = punchitem.getToolCapabilities(idef);
-
- HitParams hit_params = getHitParams(groups, &tp,
- time_from_last_punch);
-
- doDamage(hit_params.hp);
- if(g_settings->getBool("creative_mode") == false)
- {
- punchitem.addWear(hit_params.wear, idef);
- puncher->setWieldedItem(punchitem);
- }
-}
-
-void Oerkki1SAO::doDamage(u16 d)
-{
- infostream<<"oerkki damage: "<<d<<std::endl;
-
- if(d < m_hp)
- {
- m_hp -= d;
- }
- else
- {
- // Die
- m_hp = 0;
- m_removed = true;
+ // itemstring
+ os<<serializeString(m_itemstring);
+ return os.str();
}
+ std::string getStaticData()
{
+ infostream<<__FUNCTION_NAME<<std::endl;
std::ostringstream os(std::ios::binary);
- // command (1 = damage)
- writeU8(os, 1);
- // amount
- writeU8(os, d);
- // create message and add to list
- ActiveObjectMessage aom(getId(), false, os.str());
- m_messages_out.push_back(aom);
- }
-}
-
-/*
- FireflySAO
-*/
-
-// Prototype
-FireflySAO proto_FireflySAO(NULL, v3f(0,0,0));
-
-FireflySAO::FireflySAO(ServerEnvironment *env, v3f pos):
- ServerActiveObject(env, pos),
- m_is_active(false),
- m_speed_f(0,0,0)
-{
- ServerActiveObject::registerType(getType(), create);
-
- m_oldpos = v3f(0,0,0);
- m_last_sent_position = v3f(0,0,0);
- m_yaw = 0;
- m_counter1 = 0;
- m_counter2 = 0;
- m_age = 0;
- m_touching_ground = false;
-}
-
-ServerActiveObject* FireflySAO::create(ServerEnvironment *env, v3f pos,
- const std::string &data)
-{
- std::istringstream is(data, std::ios::binary);
- char buf[1];
- // read version
- is.read(buf, 1);
- u8 version = buf[0];
- // check if version is supported
- if(version != 0)
- return NULL;
- return new FireflySAO(env, pos);
-}
-
-void FireflySAO::step(float dtime, bool send_recommended)
-{
- ScopeProfiler sp2(g_profiler, "FireflySAO::step avg", SPT_AVG);
-
- assert(m_env);
-
- if(m_is_active == false)
- {
- if(m_inactive_interval.step(dtime, 0.5)==false)
- return;
+ // version
+ writeU8(os, 0);
+ // itemstring
+ os<<serializeString(m_itemstring);
+ return os.str();
}
- /*
- The AI
- */
-
- // Apply (less) gravity
- m_speed_f.Y -= dtime*3*BS;
-
- /*
- Move around if some player is close
- */
- bool player_is_close = false;
- // Check connected players
- core::list<Player*> players = m_env->getPlayers(true);
- core::list<Player*>::Iterator i;
- for(i = players.begin();
- i != players.end(); i++)
+ ItemStack createItemStack()
{
- Player *player = *i;
- v3f playerpos = player->getPosition();
- if(m_base_position.getDistanceFrom(playerpos) < BS*10.0)
- {
- player_is_close = true;
- break;
+ try{
+ IItemDefManager *idef = m_env->getGameDef()->idef();
+ ItemStack item;
+ item.deSerialize(m_itemstring, idef);
+ infostream<<__FUNCTION_NAME<<": m_itemstring=\""<<m_itemstring
+ <<"\" -> item=\""<<item.getItemString()<<"\""
+ <<std::endl;
+ return item;
}
- }
-
- m_is_active = player_is_close;
-
- if(player_is_close == false)
- {
- m_speed_f.X = 0;
- m_speed_f.Z = 0;
- }
- else
- {
- // Move around
- v3f dir(cos(m_yaw/180*PI),0,sin(m_yaw/180*PI));
- f32 speed = BS/2;
- m_speed_f.X = speed * dir.X;
- m_speed_f.Z = speed * dir.Z;
-
- if(m_touching_ground && (m_oldpos - m_base_position).getLength()
- < dtime*speed/2)
+ catch(SerializationError &e)
{
- m_counter1 -= dtime;
- if(m_counter1 < 0.0)
- {
- m_counter1 += 1.0;
- m_speed_f.Y = 5.0*BS;
- }
+ infostream<<__FUNCTION_NAME<<": serialization error: "
+ <<"m_itemstring=\""<<m_itemstring<<"\""<<std::endl;
+ return ItemStack();
}
-
- {
- m_counter2 -= dtime;
- if(m_counter2 < 0.0)
- {
- m_counter2 += (float)(myrand()%100)/100*3.0;
- m_yaw += ((float)(myrand()%200)-100)/100*180;
- m_yaw = wrapDegrees(m_yaw);
- }
- }
- }
-
- m_oldpos = m_base_position;
-
- /*
- Move it, with collision detection
- */
-
- core::aabbox3d<f32> box(-BS/3.,-BS*2/3.0,-BS/3., BS/3.,BS*4./3.,BS/3.);
- collisionMoveResult moveresult;
- // Maximum movement without glitches
- f32 pos_max_d = BS*0.25;
- // Limit speed
- if(m_speed_f.getLength()*dtime > pos_max_d)
- m_speed_f *= pos_max_d / (m_speed_f.getLength()*dtime);
- v3f pos_f = getBasePosition();
- v3f pos_f_old = pos_f;
- IGameDef *gamedef = m_env->getGameDef();
- moveresult = collisionMoveSimple(&m_env->getMap(), gamedef,
- pos_max_d, box, dtime, pos_f, m_speed_f);
- m_touching_ground = moveresult.touching_ground;
-
- setBasePosition(pos_f);
-
- if(send_recommended == false)
- return;
-
- if(pos_f.getDistanceFrom(m_last_sent_position) > 0.05*BS)
- {
- m_last_sent_position = pos_f;
-
- std::ostringstream os(std::ios::binary);
- // command (0 = update position)
- writeU8(os, 0);
- // pos
- writeV3F1000(os, m_base_position);
- // yaw
- writeF1000(os, m_yaw);
- // create message and add to list
- ActiveObjectMessage aom(getId(), false, os.str());
- m_messages_out.push_back(aom);
- }
-}
-
-std::string FireflySAO::getClientInitializationData()
-{
- std::ostringstream os(std::ios::binary);
- // version
- writeU8(os, 0);
- // pos
- writeV3F1000(os, m_base_position);
- return os.str();
-}
-
-std::string FireflySAO::getStaticData()
-{
- //infostream<<__FUNCTION_NAME<<std::endl;
- std::ostringstream os(std::ios::binary);
- // version
- writeU8(os, 0);
- return os.str();
-}
-
-/*
- MobV2SAO
-*/
-
-// Prototype
-MobV2SAO proto_MobV2SAO(NULL, v3f(0,0,0), NULL);
-
-MobV2SAO::MobV2SAO(ServerEnvironment *env, v3f pos,
- Settings *init_properties):
- ServerActiveObject(env, pos),
- m_move_type("ground_nodes"),
- m_speed(0,0,0),
- m_last_sent_position(0,0,0),
- m_oldpos(0,0,0),
- m_yaw(0),
- m_counter1(0),
- m_counter2(0),
- m_age(0),
- m_touching_ground(false),
- m_hp(10),
- m_walk_around(false),
- m_walk_around_timer(0),
- m_next_pos_exists(false),
- m_shoot_reload_timer(0),
- m_shooting(false),
- m_shooting_timer(0),
- m_falling(false),
- m_disturb_timer(100000),
- m_random_disturb_timer(0),
- m_shoot_y(0)
-{
- ServerActiveObject::registerType(getType(), create);
-
- m_properties = new Settings();
- if(init_properties)
- m_properties->update(*init_properties);
-
- m_properties->setV3F("pos", pos);
-
- setPropertyDefaults();
- readProperties();
-}
-
-MobV2SAO::~MobV2SAO()
-{
- delete m_properties;
-}
-
-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, pos, &properties);
- return o;
-}
-
-std::string MobV2SAO::getStaticData()
-{
- updateProperties();
-
- std::ostringstream os(std::ios::binary);
- m_properties->writeLines(os);
- return os.str();
-}
-
-std::string MobV2SAO::getClientInitializationData()
-{
- //infostream<<__FUNCTION_NAME<<std::endl;
-
- updateProperties();
-
- std::ostringstream os(std::ios::binary);
-
- // version
- writeU8(os, 0);
-
- Settings client_properties;
-
- /*client_properties.set("version", "0");
- client_properties.updateValue(*m_properties, "pos");
- client_properties.updateValue(*m_properties, "yaw");
- client_properties.updateValue(*m_properties, "hp");*/
-
- // Just send everything for simplicity
- client_properties.update(*m_properties);
-
- std::ostringstream os2(std::ios::binary);
- client_properties.writeLines(os2);
- compressZlib(os2.str(), os);
-
- return os.str();
-}
-
-bool checkFreePosition(Map *map, v3s16 p0, v3s16 size)
-{
- for(int dx=0; dx<size.X; dx++)
- for(int dy=0; dy<size.Y; dy++)
- for(int dz=0; dz<size.Z; dz++){
- v3s16 dp(dx, dy, dz);
- v3s16 p = p0 + dp;
- MapNode n = map->getNodeNoEx(p);
- if(n.getContent() != CONTENT_AIR)
- return false;
}
- return true;
-}
-bool checkWalkablePosition(Map *map, v3s16 p0)
-{
- v3s16 p = p0 + v3s16(0,-1,0);
- MapNode n = map->getNodeNoEx(p);
- if(n.getContent() != CONTENT_AIR)
- return true;
- return false;
-}
-
-bool checkFreeAndWalkablePosition(Map *map, v3s16 p0, v3s16 size)
-{
- if(!checkFreePosition(map, p0, size))
- return false;
- if(!checkWalkablePosition(map, p0))
- return false;
- return true;
-}
-
-static void get_random_u32_array(u32 a[], u32 len)
-{
- u32 i, n;
- for(i=0; i<len; i++)
- a[i] = i;
- n = len;
- while(n > 1){
- u32 k = myrand() % n;
- n--;
- u32 temp = a[n];
- a[n] = a[k];
- a[k] = temp;
- }
-}
-
-#define PP(x) "("<<(x).X<<","<<(x).Y<<","<<(x).Z<<")"
-
-static void explodeSquare(Map *map, v3s16 p0, v3s16 size)
-{
- core::map<v3s16, MapBlock*> modified_blocks;
-
- for(int dx=0; dx<size.X; dx++)
- for(int dy=0; dy<size.Y; dy++)
- for(int dz=0; dz<size.Z; dz++){
- v3s16 dp(dx - size.X/2, dy - size.Y/2, dz - size.Z/2);
- v3s16 p = p0 + dp;
- MapNode n = map->getNodeNoEx(p);
- if(n.getContent() == CONTENT_IGNORE)
- continue;
- //map->removeNodeWithEvent(p);
- map->removeNodeAndUpdate(p, modified_blocks);
- }
-
- // Send a MEET_OTHER event
- MapEditEvent event;
- event.type = MEET_OTHER;
- for(core::map<v3s16, MapBlock*>::Iterator
- i = modified_blocks.getIterator();
- i.atEnd() == false; i++)
+ int punch(v3f dir,
+ const ToolCapabilities *toolcap,
+ ServerActiveObject *puncher,
+ float time_from_last_punch)
{
- v3s16 p = i.getNode()->getKey();
- event.modified_blocks.insert(p, true);
- }
- map->dispatchEvent(&event);
-}
-
-void MobV2SAO::step(float dtime, bool send_recommended)
-{
- ScopeProfiler sp2(g_profiler, "MobV2SAO::step avg", SPT_AVG);
-
- assert(m_env);
- Map *map = &m_env->getMap();
-
- m_age += dtime;
-
- if(m_die_age >= 0.0 && m_age >= m_die_age){
- m_removed = true;
- return;
- }
-
- m_random_disturb_timer += dtime;
- if(m_random_disturb_timer >= 5.0)
- {
- m_random_disturb_timer = 0;
- // Check connected players
- core::list<Player*> players = m_env->getPlayers(true);
- core::list<Player*>::Iterator i;
- for(i = players.begin();
- i != players.end(); i++)
+ // Directly delete item in creative mode
+ if(g_settings->getBool("creative_mode") == true)
{
- Player *player = *i;
- v3f playerpos = player->getPosition();
- f32 dist = m_base_position.getDistanceFrom(playerpos);
- if(dist < BS*16)
- {
- if(myrand_range(0,3) == 0){
- actionstream<<"Mob id="<<m_id<<" at "
- <<PP(m_base_position/BS)
- <<" got randomly disturbed by "
- <<player->getName()<<std::endl;
- m_disturbing_player = player->getName();
- m_disturb_timer = 0;
- break;
- }
- }
- }
- }
-
- Player *disturbing_player =
- m_env->getPlayer(m_disturbing_player.c_str());
- v3f disturbing_player_off = v3f(0,1,0);
- v3f disturbing_player_norm = v3f(0,1,0);
- float disturbing_player_distance = 1000000;
- float disturbing_player_dir = 0;
- if(disturbing_player){
- disturbing_player_off =
- disturbing_player->getPosition() - m_base_position;
- disturbing_player_distance = disturbing_player_off.getLength();
- disturbing_player_norm = disturbing_player_off;
- disturbing_player_norm.normalize();
- disturbing_player_dir = 180./PI*atan2(disturbing_player_norm.Z,
- disturbing_player_norm.X);
- }
-
- m_disturb_timer += dtime;
-
- if(!m_falling)
- {
- m_shooting_timer -= dtime;
- if(m_shooting_timer <= 0.0 && m_shooting){
- m_shooting = false;
-
- std::string shoot_type = m_properties->get("shoot_type");
- v3f shoot_pos(0,0,0);
- shoot_pos.Y += m_properties->getFloat("shoot_y") * BS;
- if(shoot_type == "fireball"){
- v3f dir(cos(m_yaw/180*PI),0,sin(m_yaw/180*PI));
- dir.Y = m_shoot_y;
- dir.normalize();
- v3f speed = dir * BS * 10.0;
- v3f pos = m_base_position + shoot_pos;
- infostream<<__FUNCTION_NAME<<": Mob id="<<m_id
- <<" shooting fireball from "<<PP(pos)
- <<" at speed "<<PP(speed)<<std::endl;
- Settings properties;
- properties.set("looks", "fireball");
- properties.setV3F("speed", speed);
- properties.setFloat("die_age", 5.0);
- properties.set("move_type", "constant_speed");
- properties.setFloat("hp", 1000);
- properties.set("lock_full_brightness", "true");
- properties.set("player_hit_damage", "9");
- properties.set("player_hit_distance", "2");
- properties.set("player_hit_interval", "1");
- ServerActiveObject *obj = new MobV2SAO(m_env,
- pos, &properties);
- //m_env->addActiveObjectAsStatic(obj);
- m_env->addActiveObject(obj);
- } else {
- infostream<<__FUNCTION_NAME<<": Mob id="<<m_id
- <<": Unknown shoot_type="<<shoot_type
- <<std::endl;
- }
+ m_removed = true;
+ return 0;
}
-
- m_shoot_reload_timer += dtime;
-
- float reload_time = 15.0;
- if(m_disturb_timer <= 15.0)
- reload_time = 3.0;
-
- bool shoot_without_player = false;
- if(m_properties->getBool("mindless_rage"))
- shoot_without_player = true;
-
- if(!m_shooting && m_shoot_reload_timer >= reload_time &&
- !m_next_pos_exists &&
- (m_disturb_timer <= 60.0 || shoot_without_player))
+
+ // Take item into inventory
+ ItemStack item = createItemStack();
+ Inventory *inv = puncher->getInventory();
+ if(inv != NULL)
{
- m_shoot_y = 0;
- if(m_disturb_timer < 60.0 && disturbing_player &&
- disturbing_player_distance < 16*BS &&
- fabs(disturbing_player_norm.Y) < 0.8){
- m_yaw = disturbing_player_dir;
- sendPosition();
- m_shoot_y += disturbing_player_norm.Y;
- } else {
- m_shoot_y = 0.01 * myrand_range(-30,10);
- }
- m_shoot_reload_timer = 0.0;
- m_shooting = true;
- m_shooting_timer = 1.5;
+ std::string wieldlist = puncher->getWieldList();
+ ItemStack leftover = inv->addItem(wieldlist, item);
+ puncher->setInventoryModified();
+ if(leftover.empty())
{
- std::ostringstream os(std::ios::binary);
- // command (2 = shooting)
- writeU8(os, 2);
- // time
- writeF1000(os, m_shooting_timer + 0.1);
- // bright?
- writeU8(os, true);
- // create message and add to list
- ActiveObjectMessage aom(getId(), false, os.str());
- m_messages_out.push_back(aom);
+ m_removed = true;
}
- }
- }
-
- if(m_move_type == "ground_nodes")
- {
- if(!m_shooting){
- m_walk_around_timer -= dtime;
- if(m_walk_around_timer <= 0.0){
- m_walk_around = !m_walk_around;
- if(m_walk_around)
- m_walk_around_timer = 0.1*myrand_range(10,50);
- else
- m_walk_around_timer = 0.1*myrand_range(30,70);
- }
- }
-
- /* Move */
- if(m_next_pos_exists){
- v3f pos_f = m_base_position;
- v3f next_pos_f = intToFloat(m_next_pos_i, BS);
-
- v3f v = next_pos_f - pos_f;
- m_yaw = atan2(v.Z, v.X) / PI * 180;
-
- v3f diff = next_pos_f - pos_f;
- v3f dir = diff;
- dir.normalize();
- float speed = BS * 0.5;
- if(m_falling)
- speed = BS * 3.0;
- dir *= dtime * speed;
- bool arrived = false;
- if(dir.getLength() > diff.getLength()){
- dir = diff;
- arrived = true;
- }
- pos_f += dir;
- m_base_position = pos_f;
-
- if((pos_f - next_pos_f).getLength() < 0.1 || arrived){
- m_next_pos_exists = false;
- }
- }
-
- v3s16 pos_i = floatToInt(m_base_position, BS);
- v3s16 size_blocks = v3s16(m_size.X+0.5,m_size.Y+0.5,m_size.X+0.5);
- v3s16 pos_size_off(0,0,0);
- if(m_size.X >= 2.5){
- pos_size_off.X = -1;
- pos_size_off.Y = -1;
- }
-
- if(!m_next_pos_exists){
- /* Check whether to drop down */
- if(checkFreePosition(map,
- pos_i + pos_size_off + v3s16(0,-1,0), size_blocks)){
- m_next_pos_i = pos_i + v3s16(0,-1,0);
- m_next_pos_exists = true;
- m_falling = true;
- } else {
- m_falling = false;
- }
- }
-
- if(m_walk_around)
- {
- if(!m_next_pos_exists){
- /* Find some position where to go next */
- v3s16 dps[3*3*3];
- int num_dps = 0;
- for(int dx=-1; dx<=1; dx++)
- for(int dy=-1; dy<=1; dy++)
- for(int dz=-1; dz<=1; dz++){
- if(dx == 0 && dy == 0)
- continue;
- if(dx != 0 && dz != 0 && dy != 0)
- continue;
- dps[num_dps++] = v3s16(dx,dy,dz);
- }
- u32 order[3*3*3];
- get_random_u32_array(order, num_dps);
- for(int i=0; i<num_dps; i++){
- v3s16 p = dps[order[i]] + pos_i;
- bool is_free = checkFreeAndWalkablePosition(map,
- p + pos_size_off, size_blocks);
- if(!is_free)
- continue;
- m_next_pos_i = p;
- m_next_pos_exists = true;
- break;
- }
+ else
+ {
+ m_itemstring = leftover.getItemString();
+ m_itemstring_changed = true;
}
}
- }
- else if(m_move_type == "constant_speed")
- {
- m_base_position += m_speed * dtime;
- v3s16 pos_i = floatToInt(m_base_position, BS);
- v3s16 size_blocks = v3s16(m_size.X+0.5,m_size.Y+0.5,m_size.X+0.5);
- v3s16 pos_size_off(0,0,0);
- if(m_size.X >= 2.5){
- pos_size_off.X = -1;
- pos_size_off.Y = -1;
- }
- bool free = checkFreePosition(map, pos_i + pos_size_off, size_blocks);
- if(!free){
- explodeSquare(map, pos_i, v3s16(3,3,3));
- m_removed = true;
- return;
- }
- }
- else
- {
- errorstream<<"MobV2SAO::step(): id="<<m_id<<" unknown move_type=\""
- <<m_move_type<<"\""<<std::endl;
+ return 0;
}
- if(send_recommended == false)
- return;
- if(m_base_position.getDistanceFrom(m_last_sent_position) > 0.05*BS)
- {
- sendPosition();
- }
-}
-
-void MobV2SAO::punch(ServerActiveObject *puncher, float time_from_last_punch)
-{
- if(!puncher)
- return;
-
- v3f dir = (getBasePosition() - puncher->getBasePosition()).normalize();
-
- // A quick hack; SAO description is player name for player
- std::string playername = puncher->getDescription();
-
- Map *map = &m_env->getMap();
-
- actionstream<<playername<<" punches mob id="<<m_id
- <<" at "<<PP(m_base_position/BS)<<std::endl;
-
- m_disturb_timer = 0;
- m_disturbing_player = playername;
- m_next_pos_exists = false; // Cancel moving immediately
-
- m_yaw = wrapDegrees_180(180./PI*atan2(dir.Z, dir.X) + 180.);
- v3f new_base_position = m_base_position + dir * BS;
- {
- v3s16 pos_i = floatToInt(new_base_position, BS);
- v3s16 size_blocks = v3s16(m_size.X+0.5,m_size.Y+0.5,m_size.X+0.5);
- v3s16 pos_size_off(0,0,0);
- if(m_size.X >= 2.5){
- pos_size_off.X = -1;
- pos_size_off.Y = -1;
- }
- bool free = checkFreePosition(map, pos_i + pos_size_off, size_blocks);
- if(free)
- m_base_position = new_base_position;
- }
- sendPosition();
-
-
- // "Material" groups of the object
- ItemGroupList groups;
- groups["snappy"] = 1;
- groups["choppy"] = 1;
- groups["fleshy"] = 3;
-
- IItemDefManager *idef = m_env->getGameDef()->idef();
- ItemStack punchitem = puncher->getWieldedItem();
- ToolCapabilities tp = punchitem.getToolCapabilities(idef);
-
- HitParams hit_params = getHitParams(groups, &tp,
- time_from_last_punch);
-
- doDamage(hit_params.hp);
- if(g_settings->getBool("creative_mode") == false)
- {
- punchitem.addWear(hit_params.wear, idef);
- puncher->setWieldedItem(punchitem);
- }
-}
+private:
+ std::string m_itemstring;
+ bool m_itemstring_changed;
+ v3f m_speed_f;
+ v3f m_last_sent_position;
+ IntervalLimiter m_move_interval;
+};
-bool MobV2SAO::isPeaceful()
-{
- return m_properties->getBool("is_peaceful");
-}
-
-void MobV2SAO::sendPosition()
-{
- m_last_sent_position = m_base_position;
-
- std::ostringstream os(std::ios::binary);
- // command (0 = update position)
- writeU8(os, 0);
- // pos
- writeV3F1000(os, m_base_position);
- // yaw
- writeF1000(os, m_yaw);
- // create message and add to list
- ActiveObjectMessage aom(getId(), false, os.str());
- m_messages_out.push_back(aom);
-}
-
-void MobV2SAO::setPropertyDefaults()
-{
- m_properties->setDefault("is_peaceful", "false");
- m_properties->setDefault("move_type", "ground_nodes");
- m_properties->setDefault("speed", "(0,0,0)");
- m_properties->setDefault("age", "0");
- m_properties->setDefault("yaw", "0");
- m_properties->setDefault("pos", "(0,0,0)");
- m_properties->setDefault("hp", "0");
- m_properties->setDefault("die_age", "-1");
- m_properties->setDefault("size", "(1,2)");
- m_properties->setDefault("shoot_type", "fireball");
- m_properties->setDefault("shoot_y", "0");
- m_properties->setDefault("mindless_rage", "false");
-}
-void MobV2SAO::readProperties()
-{
- m_move_type = m_properties->get("move_type");
- m_speed = m_properties->getV3F("speed");
- m_age = m_properties->getFloat("age");
- m_yaw = m_properties->getFloat("yaw");
- m_base_position = m_properties->getV3F("pos");
- m_hp = m_properties->getS32("hp");
- m_die_age = m_properties->getFloat("die_age");
- m_size = m_properties->getV2F("size");
-}
-void MobV2SAO::updateProperties()
-{
- m_properties->set("move_type", m_move_type);
- m_properties->setV3F("speed", m_speed);
- m_properties->setFloat("age", m_age);
- m_properties->setFloat("yaw", m_yaw);
- m_properties->setV3F("pos", m_base_position);
- m_properties->setS32("hp", m_hp);
- m_properties->setFloat("die_age", m_die_age);
- m_properties->setV2F("size", m_size);
-
- m_properties->setS32("version", 0);
-}
+// Prototype (registers item for deserialization)
+ItemSAO proto_ItemSAO(NULL, v3f(0,0,0), "");
-void MobV2SAO::doDamage(u16 d)
+ServerActiveObject* createItemSAO(ServerEnvironment *env, v3f pos,
+ const std::string itemstring)
{
- if(d > 0)
- actionstream<<"MobV2 ("<<m_hp<<"hp) takes "<<d<<"hp of damage"<<std::endl;
-
- if(d < m_hp)
- {
- m_hp -= d;
- }
- else
- {
- actionstream<<"A "<<(isPeaceful()?"peaceful":"non-peaceful")
- <<" mob id="<<m_id<<" dies at "<<PP(m_base_position)<<std::endl;
- // Die
- m_hp = 0;
- m_removed = true;
- }
-
- {
- std::ostringstream os(std::ios::binary);
- // command (1 = damage)
- writeU8(os, 1);
- // amount
- writeU16(os, d);
- // create message and add to list
- ActiveObjectMessage aom(getId(), false, os.str());
- m_messages_out.push_back(aom);
- }
+ return new ItemSAO(env, pos, itemstring);
}
-
/*
LuaEntitySAO
*/
@@ -1538,7 +336,7 @@ void MobV2SAO::doDamage(u16 d)
#include "scriptapi.h"
#include "luaentity_common.h"
-// Prototype
+// Prototype (registers item for deserialization)
LuaEntitySAO proto_LuaEntitySAO(NULL, v3f(0,0,0), "_prototype", "");
LuaEntitySAO::LuaEntitySAO(ServerEnvironment *env, v3f pos,
@@ -1548,6 +346,7 @@ LuaEntitySAO::LuaEntitySAO(ServerEnvironment *env, v3f pos,
m_init_state(state),
m_registered(false),
m_prop(new LuaEntityProperties),
+ m_hp(-1),
m_velocity(0,0,0),
m_acceleration(0,0,0),
m_yaw(0),
@@ -1562,6 +361,10 @@ LuaEntitySAO::LuaEntitySAO(ServerEnvironment *env, v3f pos,
ServerActiveObject::registerType(getType(), create);
return;
}
+
+ // Initialize something to armor groups
+ m_armor_groups["fleshy"] = 3;
+ m_armor_groups["snappy"] = 2;
}
LuaEntitySAO::~LuaEntitySAO()
@@ -1594,17 +397,34 @@ ServerActiveObject* LuaEntitySAO::create(ServerEnvironment *env, v3f pos,
std::istringstream is(data, std::ios::binary);
// read version
u8 version = readU8(is);
+ std::string name;
+ std::string state;
+ s16 hp = 1;
+ v3f velocity;
+ float yaw = 0;
// check if version is supported
- if(version != 0)
+ if(version == 0){
+ name = deSerializeString(is);
+ state = deSerializeLongString(is);
+ }
+ else if(version == 1){
+ name = deSerializeString(is);
+ state = deSerializeLongString(is);
+ hp = readS16(is);
+ velocity = readV3F1000(is);
+ yaw = readF1000(is);
+ }
+ else{
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);
+ LuaEntitySAO *sao = new LuaEntitySAO(env, pos, name, state);
+ sao->m_hp = hp;
+ sao->m_velocity = velocity;
+ sao->m_yaw = yaw;
+ return sao;
}
void LuaEntitySAO::step(float dtime, bool send_recommended)
@@ -1661,11 +481,13 @@ std::string LuaEntitySAO::getClientInitializationData()
{
std::ostringstream os(std::ios::binary);
// version
- writeU8(os, 0);
+ writeU8(os, 1);
// pos
writeV3F1000(os, m_base_position);
// yaw
writeF1000(os, m_yaw);
+ // hp
+ writeS16(os, m_hp);
// properties
std::ostringstream prop_os(std::ios::binary);
m_prop->serialize(prop_os);
@@ -1679,7 +501,7 @@ std::string LuaEntitySAO::getStaticData()
infostream<<__FUNCTION_NAME<<std::endl;
std::ostringstream os(std::ios::binary);
// version
- writeU8(os, 0);
+ writeU8(os, 1);
// name
os<<serializeString(m_init_name);
// state
@@ -1690,18 +512,52 @@ std::string LuaEntitySAO::getStaticData()
} else {
os<<serializeLongString(m_init_state);
}
+ // hp
+ writeS16(os, m_hp);
+ // velocity
+ writeV3F1000(os, m_velocity);
+ // yaw
+ writeF1000(os, m_yaw);
return os.str();
}
-void LuaEntitySAO::punch(ServerActiveObject *puncher, float time_from_last_punch)
+int LuaEntitySAO::punch(v3f dir,
+ const ToolCapabilities *toolcap,
+ ServerActiveObject *puncher,
+ float time_from_last_punch)
{
if(!m_registered){
// Delete unknown LuaEntities when punched
m_removed = true;
- return;
+ return 0;
}
lua_State *L = m_env->getLua();
- scriptapi_luaentity_punch(L, m_id, puncher, time_from_last_punch);
+ scriptapi_luaentity_punch(L, m_id, puncher,
+ time_from_last_punch, toolcap, dir);
+
+ HitParams hitparams = getHitParams(m_armor_groups, toolcap,
+ time_from_last_punch);
+
+ actionstream<<getDescription()<<" punched by "
+ <<puncher->getDescription()<<", damage "<<hitparams.hp
+ <<" HP"<<std::endl;
+
+ setHP(getHP() - hitparams.hp);
+
+ {
+ std::ostringstream os(std::ios::binary);
+ // command
+ writeU8(os, LUAENTITY_CMD_PUNCHED);
+ // damage
+ writeS16(os, hitparams.hp);
+ // result_hp
+ writeS16(os, getHP());
+ // create message and add to list
+ ActiveObjectMessage aom(getId(), true, os.str());
+ m_messages_out.push_back(aom);
+ }
+
+ return hitparams.wear;
}
void LuaEntitySAO::rightClick(ServerActiveObject *clicker)
@@ -1712,6 +568,17 @@ void LuaEntitySAO::rightClick(ServerActiveObject *clicker)
scriptapi_luaentity_rightclick(L, m_id, clicker);
}
+void LuaEntitySAO::setHP(s16 hp)
+{
+ if(hp < 0) hp = 0;
+ m_hp = hp;
+}
+
+s16 LuaEntitySAO::getHP()
+{
+ return m_hp;
+}
+
void LuaEntitySAO::setPos(v3f pos)
{
m_base_position = pos;
@@ -1730,6 +597,17 @@ float LuaEntitySAO::getMinimumSavedMovement()
return 0.1 * BS;
}
+std::string LuaEntitySAO::getDescription()
+{
+ std::ostringstream os(std::ios::binary);
+ os<<"LuaEntitySAO at (";
+ os<<(m_base_position.X/BS)<<",";
+ os<<(m_base_position.Y/BS)<<",";
+ os<<(m_base_position.Z/BS);
+ os<<")";
+ return std::string("LuaEntitySAO");
+}
+
void LuaEntitySAO::setVelocity(v3f velocity)
{
m_velocity = velocity;
@@ -1763,8 +641,8 @@ float LuaEntitySAO::getYaw()
void LuaEntitySAO::setTextureMod(const std::string &mod)
{
std::ostringstream os(std::ios::binary);
- // command (1 = set texture modification)
- writeU8(os, 1);
+ // command
+ writeU8(os, LUAENTITY_CMD_SET_TEXTURE_MOD);
// parameters
os<<serializeString(mod);
// create message and add to list
@@ -1776,8 +654,8 @@ void LuaEntitySAO::setSprite(v2s16 p, int num_frames, float framelength,
bool select_horiz_by_yawpitch)
{
std::ostringstream os(std::ios::binary);
- // command (2 = set sprite)
- writeU8(os, 2);
+ // command
+ writeU8(os, LUAENTITY_CMD_SET_SPRITE);
// parameters
writeV2S16(os, p);
writeU16(os, num_frames);
@@ -1806,8 +684,8 @@ void LuaEntitySAO::sendPosition(bool do_interpolate, bool is_movement_end)
float update_interval = m_env->getSendRecommendedInterval();
std::ostringstream os(std::ios::binary);
- // command (0 = update position)
- writeU8(os, 0);
+ // command
+ writeU8(os, LUAENTITY_CMD_UPDATE_POSITION);
// do_interpolate
writeU8(os, do_interpolate);
diff --git a/src/content_sao.h b/src/content_sao.h
index f0c9cea90..507631d2a 100644
--- a/src/content_sao.h
+++ b/src/content_sao.h
@@ -22,173 +22,16 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "serverobject.h"
#include "content_object.h"
+#include "itemgroup.h"
-class TestSAO : public ServerActiveObject
-{
-public:
- TestSAO(ServerEnvironment *env, v3f pos);
- u8 getType() const
- {return ACTIVEOBJECT_TYPE_TEST;}
- static ServerActiveObject* create(ServerEnvironment *env, v3f pos,
- const std::string &data);
- void step(float dtime, bool send_recommended);
-private:
- float m_timer1;
- float m_age;
-};
-
-class ItemSAO : public ServerActiveObject
-{
-public:
- ItemSAO(ServerEnvironment *env, v3f pos, const std::string itemstring);
- u8 getType() const
- {return ACTIVEOBJECT_TYPE_ITEM;}
- static ServerActiveObject* create(ServerEnvironment *env, v3f pos,
- const std::string &data);
- void step(float dtime, bool send_recommended);
- std::string getClientInitializationData();
- std::string getStaticData();
- ItemStack createItemStack();
- void punch(ServerActiveObject *puncher, float time_from_last_punch);
- float getMinimumSavedMovement(){ return 0.1*BS; }
-private:
- std::string m_itemstring;
- bool m_itemstring_changed;
- v3f m_speed_f;
- v3f m_last_sent_position;
- IntervalLimiter m_move_interval;
-};
+ServerActiveObject* createItemSAO(ServerEnvironment *env, v3f pos,
+ const std::string itemstring);
-class RatSAO : public ServerActiveObject
-{
-public:
- RatSAO(ServerEnvironment *env, v3f pos);
- u8 getType() const
- {return ACTIVEOBJECT_TYPE_RAT;}
- static ServerActiveObject* create(ServerEnvironment *env, v3f pos,
- const std::string &data);
- void step(float dtime, bool send_recommended);
- std::string getClientInitializationData();
- std::string getStaticData();
- void punch(ServerActiveObject *puncher, float time_from_last_punch);
-private:
- bool m_is_active;
- IntervalLimiter m_inactive_interval;
- v3f m_speed_f;
- v3f m_oldpos;
- v3f m_last_sent_position;
- float m_yaw;
- float m_counter1;
- float m_counter2;
- float m_age;
- bool m_touching_ground;
-};
-
-class Oerkki1SAO : public ServerActiveObject
-{
-public:
- Oerkki1SAO(ServerEnvironment *env, v3f pos);
- u8 getType() const
- {return ACTIVEOBJECT_TYPE_OERKKI1;}
- static ServerActiveObject* create(ServerEnvironment *env, v3f pos,
- const std::string &data);
- void step(float dtime, bool send_recommended);
- std::string getClientInitializationData();
- std::string getStaticData();
- void punch(ServerActiveObject *puncher, float time_from_last_punch);
- bool isPeaceful(){return false;}
-private:
- void doDamage(u16 d);
-
- bool m_is_active;
- IntervalLimiter m_inactive_interval;
- v3f m_speed_f;
- v3f m_oldpos;
- v3f m_last_sent_position;
- float m_yaw;
- float m_counter1;
- float m_counter2;
- float m_age;
- bool m_touching_ground;
- u8 m_hp;
- float m_after_jump_timer;
-};
-
-class FireflySAO : public ServerActiveObject
-{
-public:
- FireflySAO(ServerEnvironment *env, v3f pos);
- u8 getType() const
- {return ACTIVEOBJECT_TYPE_FIREFLY;}
- 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:
- bool m_is_active;
- IntervalLimiter m_inactive_interval;
- v3f m_speed_f;
- v3f m_oldpos;
- v3f m_last_sent_position;
- float m_yaw;
- float m_counter1;
- float m_counter2;
- float m_age;
- bool m_touching_ground;
-};
-
-class Settings;
-
-class MobV2SAO : public ServerActiveObject
-{
-public:
- MobV2SAO(ServerEnvironment *env, v3f pos,
- Settings *init_properties);
- virtual ~MobV2SAO();
- u8 getType() const
- {return ACTIVEOBJECT_TYPE_MOBV2;}
- static ServerActiveObject* create(ServerEnvironment *env, v3f pos,
- const std::string &data);
- std::string getStaticData();
- std::string getClientInitializationData();
- void step(float dtime, bool send_recommended);
- void punch(ServerActiveObject *puncher, float time_from_last_punch);
- bool isPeaceful();
-private:
- void sendPosition();
- void setPropertyDefaults();
- void readProperties();
- void updateProperties();
- void doDamage(u16 d);
-
- std::string m_move_type;
- v3f m_speed;
- v3f m_last_sent_position;
- v3f m_oldpos;
- float m_yaw;
- float m_counter1;
- float m_counter2;
- float m_age;
- bool m_touching_ground;
- int m_hp;
- bool m_walk_around;
- float m_walk_around_timer;
- bool m_next_pos_exists;
- v3s16 m_next_pos_i;
- float m_shoot_reload_timer;
- bool m_shooting;
- float m_shooting_timer;
- float m_die_age;
- v2f m_size;
- bool m_falling;
- float m_disturb_timer;
- std::string m_disturbing_player;
- float m_random_disturb_timer;
- float m_shoot_y;
+/*
+ LuaEntitySAO
- Settings *m_properties;
-};
+ This is the only SAO that needs to have a bunch of it's internals exposed.
+*/
struct LuaEntityProperties;
@@ -206,11 +49,17 @@ public:
void step(float dtime, bool send_recommended);
std::string getClientInitializationData();
std::string getStaticData();
- void punch(ServerActiveObject *puncher, float time_from_last_punch);
+ int punch(v3f dir,
+ const ToolCapabilities *toolcap=NULL,
+ ServerActiveObject *puncher=NULL,
+ float time_from_last_punch=1000000);
void rightClick(ServerActiveObject *clicker);
void setPos(v3f pos);
void moveTo(v3f pos, bool continuous);
float getMinimumSavedMovement();
+ std::string getDescription();
+ void setHP(s16 hp);
+ s16 getHP();
/* LuaEntitySAO-specific */
void setVelocity(v3f velocity);
v3f getVelocity();
@@ -230,9 +79,12 @@ private:
bool m_registered;
struct LuaEntityProperties *m_prop;
+ s16 m_hp;
v3f m_velocity;
v3f m_acceleration;
float m_yaw;
+ ItemGroupList m_armor_groups;
+
float m_last_sent_yaw;
v3f m_last_sent_position;
v3f m_last_sent_velocity;
diff --git a/src/itemgroup.h b/src/itemgroup.h
new file mode 100644
index 000000000..927811dd0
--- /dev/null
+++ b/src/itemgroup.h
@@ -0,0 +1,39 @@
+/*
+Minetest-c55
+Copyright (C) 2012 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 ITEMGROUP_HEADER
+#define ITEMGROUP_HEADER
+
+#include "common_irrlicht.h"
+#include <string>
+#include <map>
+
+typedef std::map<std::string, int> ItemGroupList;
+
+static inline int itemgroup_get(const ItemGroupList &groups,
+ const std::string &name)
+{
+ std::map<std::string, int>::const_iterator i = groups.find(name);
+ if(i == groups.end())
+ return 0;
+ return i->second;
+}
+
+#endif
+
diff --git a/src/luaentity_common.cpp b/src/luaentity_common.cpp
index 40dc4de35..63c3f2d6b 100644
--- a/src/luaentity_common.cpp
+++ b/src/luaentity_common.cpp
@@ -25,6 +25,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#define PP2(x) "("<<(x).X<<","<<(x).Y<<")"
LuaEntityProperties::LuaEntityProperties():
+ hp_max(1),
physical(false),
weight(5),
collisionbox(-0.5,-0.5,-0.5, 0.5,0.5,0.5),
@@ -39,7 +40,8 @@ LuaEntityProperties::LuaEntityProperties():
std::string LuaEntityProperties::dump()
{
std::ostringstream os(std::ios::binary);
- os<<"physical="<<physical;
+ os<<"hp_max="<<hp_max;
+ os<<", physical="<<physical;
os<<", weight="<<weight;
os<<", collisionbox="<<PP(collisionbox.MinEdge)<<","<<PP(collisionbox.MaxEdge);
os<<", visual="<<visual;
@@ -56,7 +58,8 @@ std::string LuaEntityProperties::dump()
void LuaEntityProperties::serialize(std::ostream &os)
{
- writeU8(os, 0); // version
+ writeU8(os, 1); // version
+ writeS16(os, hp_max);
writeU8(os, physical);
writeF1000(os, weight);
writeV3F1000(os, collisionbox.MinEdge);
@@ -74,8 +77,9 @@ void LuaEntityProperties::serialize(std::ostream &os)
void LuaEntityProperties::deSerialize(std::istream &is)
{
int version = readU8(is);
- if(version != 0) throw SerializationError(
+ if(version != 1) throw SerializationError(
"unsupported LuaEntityProperties version");
+ hp_max = readS16(is);
physical = readU8(is);
weight = readF1000(is);
collisionbox.MinEdge = readV3F1000(is);
diff --git a/src/luaentity_common.h b/src/luaentity_common.h
index bc2871a94..b63663828 100644
--- a/src/luaentity_common.h
+++ b/src/luaentity_common.h
@@ -27,6 +27,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
struct LuaEntityProperties
{
// Values are BS=1
+ s16 hp_max;
bool physical;
float weight;
core::aabbox3d<f32> collisionbox;
@@ -42,5 +43,10 @@ struct LuaEntityProperties
void deSerialize(std::istream &is);
};
+#define LUAENTITY_CMD_UPDATE_POSITION 0
+#define LUAENTITY_CMD_SET_TEXTURE_MOD 1
+#define LUAENTITY_CMD_SET_SPRITE 2
+#define LUAENTITY_CMD_PUNCHED 3
+
#endif
diff --git a/src/scriptapi.cpp b/src/scriptapi.cpp
index 2ee727b3f..c3059ec55 100644
--- a/src/scriptapi.cpp
+++ b/src/scriptapi.cpp
@@ -2297,17 +2297,22 @@ private:
return 0;
}
- // punch(self, puncher); puncher = an another ObjectRef
+ // punch(self, puncher, tool_capabilities, direction, time_from_last_punch)
static int l_punch(lua_State *L)
{
ObjectRef *ref = checkobject(L, 1);
- ObjectRef *ref2 = checkobject(L, 2);
+ ObjectRef *puncher_ref = checkobject(L, 2);
ServerActiveObject *co = getobject(ref);
- ServerActiveObject *co2 = getobject(ref2);
+ ServerActiveObject *puncher = getobject(puncher_ref);
if(co == NULL) return 0;
- if(co2 == NULL) return 0;
+ if(puncher == NULL) return 0;
+ ToolCapabilities toolcap = read_tool_capabilities(L, 3);
+ v3f dir = read_v3f(L, 4);
+ float time_from_last_punch = 1000000;
+ if(lua_isnumber(L, 5))
+ time_from_last_punch = lua_tonumber(L, 5);
// Do it
- co->punch(co2);
+ puncher->punch(dir, &toolcap, puncher, time_from_last_punch);
return 0;
}
@@ -2878,7 +2883,7 @@ private:
if(item.empty() || !item.isKnown(get_server(L)->idef()))
return 0;
// Do it
- ServerActiveObject *obj = new ItemSAO(env, pos, item.getItemString());
+ ServerActiveObject *obj = createItemSAO(env, pos, item.getItemString());
int objectid = env->addActiveObject(obj);
// If failed to add, return nothing (reads as nil)
if(objectid == 0)
@@ -2892,15 +2897,8 @@ private:
// pos = {x=num, y=num, z=num}
static int l_add_rat(lua_State *L)
{
- infostream<<"EnvRef::l_add_rat()"<<std::endl;
- EnvRef *o = checkobject(L, 1);
- ServerEnvironment *env = o->m_env;
- if(env == NULL) return 0;
- // pos
- v3f pos = checkFloatPos(L, 2);
- // Do it
- ServerActiveObject *obj = new RatSAO(env, pos);
- env->addActiveObject(obj);
+ infostream<<"EnvRef::l_add_rat(): C++ mobs have been removed."
+ <<" Doing nothing."<<std::endl;
return 0;
}
@@ -2908,15 +2906,8 @@ private:
// pos = {x=num, y=num, z=num}
static int l_add_firefly(lua_State *L)
{
- infostream<<"EnvRef::l_add_firefly()"<<std::endl;
- EnvRef *o = checkobject(L, 1);
- ServerEnvironment *env = o->m_env;
- if(env == NULL) return 0;
- // pos
- v3f pos = checkFloatPos(L, 2);
- // Do it
- ServerActiveObject *obj = new FireflySAO(env, pos);
- env->addActiveObject(obj);
+ infostream<<"EnvRef::l_add_firefly(): C++ mobs have been removed."
+ <<" Doing nothing."<<std::endl;
return 0;
}
@@ -4348,6 +4339,8 @@ void scriptapi_luaentity_get_properties(lua_State *L, u16 id,
/* Read stuff */
+ prop->hp_max = getintfield_default(L, -1, "hp_max", 10);
+
getboolfield(L, -1, "physical", prop->physical);
getfloatfield(L, -1, "weight", prop->weight);
@@ -4415,9 +4408,11 @@ void scriptapi_luaentity_step(lua_State *L, u16 id, float dtime)
script_error(L, "error running function 'on_step': %s\n", lua_tostring(L, -1));
}
-// Calls entity:on_punch(ObjectRef puncher, time_from_last_punch)
+// Calls entity:on_punch(ObjectRef puncher, time_from_last_punch,
+// tool_capabilities, direction)
void scriptapi_luaentity_punch(lua_State *L, u16 id,
- ServerActiveObject *puncher, float time_from_last_punch)
+ ServerActiveObject *puncher, float time_from_last_punch,
+ const ToolCapabilities *toolcap, v3f dir)
{
realitycheck(L);
assert(lua_checkstack(L, 20));
@@ -4436,8 +4431,10 @@ void scriptapi_luaentity_punch(lua_State *L, u16 id,
lua_pushvalue(L, object); // self
objectref_get_or_create(L, puncher); // Clicker reference
lua_pushnumber(L, time_from_last_punch);
- // Call with 2 arguments, 0 results
- if(lua_pcall(L, 3, 0, 0))
+ push_tool_capabilities(L, *toolcap);
+ push_v3f(L, dir);
+ // Call with 5 arguments, 0 results
+ if(lua_pcall(L, 5, 0, 0))
script_error(L, "error running function 'on_punch': %s\n", lua_tostring(L, -1));
}
diff --git a/src/scriptapi.h b/src/scriptapi.h
index df8ae344e..aa2d9d4c7 100644
--- a/src/scriptapi.h
+++ b/src/scriptapi.h
@@ -33,6 +33,7 @@ struct LuaEntityProperties;
struct ItemStack;
struct PointedThing;
//class IGameDef;
+struct ToolCapabilities;
void scriptapi_export(lua_State *L, Server *server);
bool scriptapi_loadmod(lua_State *L, const std::string &scriptpath,
@@ -82,7 +83,8 @@ void scriptapi_luaentity_get_properties(lua_State *L, u16 id,
LuaEntityProperties *prop);
void scriptapi_luaentity_step(lua_State *L, u16 id, float dtime);
void scriptapi_luaentity_punch(lua_State *L, u16 id,
- ServerActiveObject *puncher, float time_from_last_punch);
+ ServerActiveObject *puncher, float time_from_last_punch,
+ const ToolCapabilities *toolcap, v3f dir);
void scriptapi_luaentity_rightclick(lua_State *L, u16 id,
ServerActiveObject *clicker);
diff --git a/src/server.cpp b/src/server.cpp
index 443a2a39b..899624633 100644
--- a/src/server.cpp
+++ b/src/server.cpp
@@ -47,6 +47,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "mods.h"
#include "sha1.h"
#include "base64.h"
+#include "tool.h"
#define PP(x) "("<<(x).X<<","<<(x).Y<<","<<(x).Z<<")"
@@ -1244,7 +1245,7 @@ void Server::AsyncRunStep()
explosion.
*/
player->m_last_good_position_age += dtime;
- if(player->m_last_good_position_age >= 2.0){
+ if(player->m_last_good_position_age >= 1.0){
float age = player->m_last_good_position_age;
v3f diff = (player->getPosition() - player->m_last_good_position);
float d_vert = diff.Y;
@@ -2870,7 +2871,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
if(action == 0 || action == 2 || action == 3)
{
float d = player_pos.getDistanceFrom(pointed_pos_under);
- float max_d = BS * 10; // Just some large enough value
+ float max_d = BS * 14; // Just some large enough value
if(d > max_d){
actionstream<<"Player "<<player->getName()
<<" tried to access "<<pointed.dump()
@@ -2933,8 +2934,14 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
actionstream<<player->getName()<<" punches object "
<<pointed.object_id<<std::endl;
- // Do stuff
- pointed_object->punch(srp, srp->m_time_from_last_punch);
+ ItemStack punchitem = srp->getWieldedItem();
+ ToolCapabilities toolcap =
+ punchitem.getToolCapabilities(m_itemdef);
+ v3f dir = (pointed_object->getBasePosition() -
+ (srp->getPosition() + srp->getEyeOffset())
+ ).normalize();
+ pointed_object->punch(dir, &toolcap, srp,
+ srp->m_time_from_last_punch);
srp->m_time_from_last_punch = 0;
}
diff --git a/src/serverobject.h b/src/serverobject.h
index 380bf7302..15bbe52f7 100644
--- a/src/serverobject.h
+++ b/src/serverobject.h
@@ -44,7 +44,7 @@ Some planning
class ServerEnvironment;
struct ItemStack;
class Player;
-struct ToolDiggingProperties;
+struct ToolCapabilities;
class ServerActiveObject : public ActiveObject
{
@@ -133,10 +133,12 @@ public:
virtual bool isStaticAllowed() const
{return true;}
- // time_from_last_punch is used for lessening damage if punching fast
- virtual void punch(ServerActiveObject *puncher,
+ // Returns tool wear
+ virtual int punch(v3f dir,
+ const ToolCapabilities *toolcap=NULL,
+ ServerActiveObject *puncher=NULL,
float time_from_last_punch=1000000)
- {}
+ { return 0; }
virtual void rightClick(ServerActiveObject *clicker)
{}
virtual void setHP(s16 hp)
diff --git a/src/serverremoteplayer.cpp b/src/serverremoteplayer.cpp
index c57794ea2..667ece7f2 100644
--- a/src/serverremoteplayer.cpp
+++ b/src/serverremoteplayer.cpp
@@ -169,16 +169,18 @@ std::string ServerRemotePlayer::getStaticData()
return "";
}
-void ServerRemotePlayer::punch(ServerActiveObject *puncher,
+int ServerRemotePlayer::punch(v3f dir,
+ const ToolCapabilities *toolcap,
+ ServerActiveObject *puncher,
float time_from_last_punch)
{
- if(!puncher)
- return;
+ if(!toolcap)
+ return 0;
// No effect if PvP disabled
if(g_settings->getBool("enable_pvp") == false){
if(puncher->getType() == ACTIVEOBJECT_TYPE_PLAYER)
- return;
+ return 0;
}
// "Material" groups of the player
@@ -186,19 +188,13 @@ void ServerRemotePlayer::punch(ServerActiveObject *puncher,
groups["choppy"] = 2;
groups["fleshy"] = 3;
- IItemDefManager *idef = m_env->getGameDef()->idef();
- ItemStack punchitem = puncher->getWieldedItem();
- ToolCapabilities tp = punchitem.getToolCapabilities(idef);
-
- HitParams hitparams = getHitParams(groups, &tp, time_from_last_punch);
+ HitParams hitparams = getHitParams(groups, toolcap, time_from_last_punch);
actionstream<<"Player "<<getName()<<" punched by "
<<puncher->getDescription()<<", damage "<<hitparams.hp
<<" HP"<<std::endl;
setHP(getHP() - hitparams.hp);
- punchitem.addWear(hitparams.wear, idef);
- puncher->setWieldedItem(punchitem);
if(hitparams.hp != 0)
{
@@ -211,6 +207,8 @@ void ServerRemotePlayer::punch(ServerActiveObject *puncher,
ActiveObjectMessage aom(getId(), false, os.str());
m_messages_out.push_back(aom);
}
+
+ return hitparams.wear;
}
void ServerRemotePlayer::rightClick(ServerActiveObject *clicker)
diff --git a/src/serverremoteplayer.h b/src/serverremoteplayer.h
index 94926c824..2ff1b0013 100644
--- a/src/serverremoteplayer.h
+++ b/src/serverremoteplayer.h
@@ -67,7 +67,10 @@ public:
void step(float dtime, bool send_recommended);
std::string getClientInitializationData();
std::string getStaticData();
- void punch(ServerActiveObject *puncher, float time_from_last_punch);
+ int punch(v3f dir,
+ const ToolCapabilities *toolcap,
+ ServerActiveObject *puncher,
+ float time_from_last_punch);
void rightClick(ServerActiveObject *clicker);
void setPos(v3f pos);
void moveTo(v3f pos, bool continuous);