X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=src%2Fcontent_sao.cpp;h=414d63f2d38ee03d8e1ac35afe5eaf24a7502d36;hb=d6b30dd3a5df4b84a287305f807442064f4cf68d;hp=0b81855c16aec55f0c9fffaa685e9ed411ba86ca;hpb=7c1ea34baf1560cf8757e95f740e3277afdd2ba2;p=oweals%2Fminetest.git diff --git a/src/content_sao.cpp b/src/content_sao.cpp index 0b81855c1..414d63f2d 100644 --- a/src/content_sao.cpp +++ b/src/content_sao.cpp @@ -20,28 +20,51 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "content_sao.h" #include "collision.h" #include "environment.h" +#include "settings.h" +#include "main.h" // For g_profiler +#include "profiler.h" +#include "serialization.h" // For compressZlib core::map 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 */ // Prototype -TestSAO proto_TestSAO(NULL, 0, v3f(0,0,0)); +TestSAO proto_TestSAO(NULL, v3f(0,0,0)); -TestSAO::TestSAO(ServerEnvironment *env, u16 id, v3f pos): - ServerActiveObject(env, id, pos), +TestSAO::TestSAO(ServerEnvironment *env, v3f pos): + ServerActiveObject(env, pos), m_timer1(0), m_age(0) { ServerActiveObject::registerType(getType(), create); } -ServerActiveObject* TestSAO::create(ServerEnvironment *env, u16 id, v3f pos, +ServerActiveObject* TestSAO::create(ServerEnvironment *env, v3f pos, const std::string &data) { - return new TestSAO(env, id, pos); + return new TestSAO(env, pos); } void TestSAO::step(float dtime, bool send_recommended) @@ -64,7 +87,6 @@ void TestSAO::step(float dtime, bool send_recommended) if(m_timer1 < 0.0) { m_timer1 += 0.125; - //dstream<<"TestSAO: id="<getMap(), pos_max_d, - box, dtime, pos_f, m_speed_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; @@ -186,7 +211,7 @@ std::string ItemSAO::getClientInitializationData() std::string ItemSAO::getStaticData() { - dstream<<__FUNCTION_NAME<getGameDef(); + InventoryItem *item = InventoryItem::deSerialize(is, gamedef); + infostream<<__FUNCTION_NAME<<": m_inventorystring=\"" < item="<addToInventory(item); + if(fits) + m_removed = true; + else + delete item; +} /* RatSAO */ // Prototype -RatSAO proto_RatSAO(NULL, 0, v3f(0,0,0)); +RatSAO proto_RatSAO(NULL, v3f(0,0,0)); -RatSAO::RatSAO(ServerEnvironment *env, u16 id, v3f pos): - ServerActiveObject(env, id, pos), +RatSAO::RatSAO(ServerEnvironment *env, v3f pos): + ServerActiveObject(env, pos), m_is_active(false), m_speed_f(0,0,0) { @@ -232,14 +267,14 @@ RatSAO::RatSAO(ServerEnvironment *env, u16 id, v3f pos): m_oldpos = v3f(0,0,0); m_last_sent_position = v3f(0,0,0); - m_yaw = 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, u16 id, v3f pos, +ServerActiveObject* RatSAO::create(ServerEnvironment *env, v3f pos, const std::string &data) { std::istringstream is(data, std::ios::binary); @@ -250,11 +285,13 @@ ServerActiveObject* RatSAO::create(ServerEnvironment *env, u16 id, v3f pos, // check if version is supported if(version != 0) return NULL; - return new RatSAO(env, id, pos); + return new RatSAO(env, pos); } void RatSAO::step(float dtime, bool send_recommended) { + ScopeProfiler sp2(g_profiler, "RatSAO::step avg", SPT_AVG); + assert(m_env); if(m_is_active == false) @@ -349,8 +386,9 @@ void RatSAO::step(float dtime, bool send_recommended) m_speed_f *= pos_max_d / (m_speed_f.getLength()*dtime); v3f pos_f = getBasePosition(); v3f pos_f_old = pos_f; - moveresult = collisionMoveSimple(&m_env->getMap(), pos_max_d, - box, dtime, pos_f, m_speed_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); @@ -387,46 +425,34 @@ std::string RatSAO::getClientInitializationData() std::string RatSAO::getStaticData() { - //dstream<<__FUNCTION_NAME<getGameDef(); + InventoryItem *item = InventoryItem::deSerialize(is, gamedef); + bool fits = puncher->addToInventory(item); + if(fits) + m_removed = true; + else + delete item; } /* Oerkki1SAO */ -// 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; -} - // Prototype -Oerkki1SAO proto_Oerkki1SAO(NULL, 0, v3f(0,0,0)); +Oerkki1SAO proto_Oerkki1SAO(NULL, v3f(0,0,0)); -Oerkki1SAO::Oerkki1SAO(ServerEnvironment *env, u16 id, v3f pos): - ServerActiveObject(env, id, pos), +Oerkki1SAO::Oerkki1SAO(ServerEnvironment *env, v3f pos): + ServerActiveObject(env, pos), m_is_active(false), m_speed_f(0,0,0) { @@ -443,7 +469,7 @@ Oerkki1SAO::Oerkki1SAO(ServerEnvironment *env, u16 id, v3f pos): m_after_jump_timer = 0; } -ServerActiveObject* Oerkki1SAO::create(ServerEnvironment *env, u16 id, v3f pos, +ServerActiveObject* Oerkki1SAO::create(ServerEnvironment *env, v3f pos, const std::string &data) { std::istringstream is(data, std::ios::binary); @@ -454,13 +480,15 @@ ServerActiveObject* Oerkki1SAO::create(ServerEnvironment *env, u16 id, v3f pos, // check if version is supported if(version != 0) return NULL; - Oerkki1SAO *o = new Oerkki1SAO(env, id, pos); + Oerkki1SAO *o = new Oerkki1SAO(env, pos); o->m_hp = hp; return o; } 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) @@ -503,13 +531,14 @@ void Oerkki1SAO::step(float dtime, bool send_recommended) Player *player = *i; v3f playerpos = player->getPosition(); f32 dist = m_base_position.getDistanceFrom(playerpos); - if(dist < BS*1.45) + if(dist < BS*0.6) { + m_removed = true; + return; player_is_too_close = true; near_player_pos = playerpos; - break; } - else if(dist < BS*15.0) + else if(dist < BS*15.0 && !player_is_too_close) { player_is_close = true; near_player_pos = playerpos; @@ -595,12 +624,13 @@ void Oerkki1SAO::step(float dtime, bool send_recommended) m_speed_f *= pos_max_d / (m_speed_f.getLength()*dtime);*/ v3f pos_f = getBasePosition(); v3f pos_f_old = pos_f; - moveresult = collisionMovePrecise(&m_env->getMap(), pos_max_d, - box, dtime, pos_f, m_speed_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*12; + float tolerance = BS*30; float factor = BS*0.5; v3f speed_diff = old_speed - m_speed_f; // Increase effect in X and Z @@ -648,7 +678,7 @@ std::string Oerkki1SAO::getClientInitializationData() std::string Oerkki1SAO::getStaticData() { - //dstream<<__FUNCTION_NAME<getBasePosition()).normalize(); + + std::string toolname = ""; + InventoryItem *item = puncher->getWieldedItem(); + if(item && (std::string)item->getName() == "ToolItem"){ + ToolItem *titem = (ToolItem*)item; + toolname = titem->getToolName(); + } + m_speed_f += dir*12*BS; u16 amount = 5; + /* See tool names in inventory.h */ + if(toolname == "WSword") + amount = 10; + if(toolname == "STSword") + amount = 12; + if(toolname == "SteelSword") + amount = 16; + if(toolname == "STAxe") + amount = 7; + if(toolname == "SteelAxe") + amount = 9; + if(toolname == "SteelPick") + amount = 7; doDamage(amount); - return 65536/100; + + puncher->damageWieldedItem(65536/100); } void Oerkki1SAO::doDamage(u16 d) { - dstream<<"oerkki damage: "<getMap(), pos_max_d, - box, dtime, pos_f, m_speed_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); @@ -856,7 +912,7 @@ std::string FireflySAO::getClientInitializationData() std::string FireflySAO::getStaticData() { - //dstream<<__FUNCTION_NAME<getGameDef(); + InventoryItem *item = InventoryItem::deSerialize(is, gamedef); + return item; +} + +/* + 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<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 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 modified_blocks; + + for(int dx=0; dxgetNodeNoEx(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::Iterator + i = modified_blocks.getIterator(); + i.atEnd() == false; i++) + { + 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 players = m_env->getPlayers(true); + core::list::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*16) + { + if(myrand_range(0,3) == 0){ + actionstream<<"Mob id="<getName()<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="<addActiveObjectAsStatic(obj); + m_env->addActiveObject(obj); + } else { + infostream<<__FUNCTION_NAME<<": Mob id="<= reload_time && + !m_next_pos_exists && + (m_disturb_timer <= 60.0 || shoot_without_player)) + { + 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::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); + } + } + } + + 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= 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="< 0.05*BS) + { + sendPosition(); + } +} + +void MobV2SAO::punch(ServerActiveObject *puncher) +{ + v3f dir = (getBasePosition() - puncher->getBasePosition()).normalize(); + + std::string toolname = ""; + InventoryItem *item = puncher->getWieldedItem(); + if(item && (std::string)item->getName() == "ToolItem"){ + ToolItem *titem = (ToolItem*)item; + toolname = titem->getToolName(); + } + + // A quick hack; SAO description is player name for player + std::string playername = puncher->getDescription(); + + Map *map = &m_env->getMap(); + + actionstream<= 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(); + + u16 amount = 2; + /* See tool names in inventory.h */ + if(toolname == "WSword") + amount = 4; + if(toolname == "STSword") + amount = 6; + if(toolname == "SteelSword") + amount = 8; + if(toolname == "STAxe") + amount = 3; + if(toolname == "SteelAxe") + amount = 4; + if(toolname == "SteelPick") + amount = 3; + doDamage(amount); + + puncher->damageWieldedItem(65536/100); +} + +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); +} + +void MobV2SAO::doDamage(u16 d) +{ + infostream<<"MobV2 hp="<getLua(); + scriptapi_luaentity_rm(L, m_id); + } + delete m_prop; +} + +void LuaEntitySAO::addedToEnvironment() +{ + ServerActiveObject::addedToEnvironment(); + + // Create entity from name and state + lua_State *L = m_env->getLua(); + m_registered = scriptapi_luaentity_add(L, m_id, m_init_name.c_str(), + m_init_state.c_str()); + + if(m_registered){ + // Get properties + scriptapi_luaentity_get_properties(L, m_id, m_prop); + } +} + +ServerActiveObject* LuaEntitySAO::create(ServerEnvironment *env, v3f pos, + const std::string &data) +{ + std::istringstream is(data, std::ios::binary); + // read version + u8 version = readU8(is); + // check if version is supported + if(version != 0) + return NULL; + // read name + std::string name = deSerializeString(is); + // read state + std::string state = deSerializeLongString(is); + // create object + infostream<<"LuaEntitySAO::create(name=\""<physical){ + core::aabbox3d box = m_prop->collisionbox; + box.MinEdge *= BS; + box.MaxEdge *= BS; + collisionMoveResult moveresult; + f32 pos_max_d = BS*0.25; // Distance per iteration + v3f p_pos = getBasePosition(); + v3f p_velocity = m_velocity; + IGameDef *gamedef = m_env->getGameDef(); + moveresult = collisionMovePrecise(&m_env->getMap(), gamedef, + pos_max_d, box, dtime, p_pos, p_velocity); + // Apply results + setBasePosition(p_pos); + m_velocity = p_velocity; + + m_velocity += dtime * m_acceleration; + } else { + m_base_position += dtime * m_velocity + 0.5 * dtime + * dtime * m_acceleration; + m_velocity += dtime * m_acceleration; + } + + if(m_registered){ + lua_State *L = m_env->getLua(); + scriptapi_luaentity_step(L, m_id, dtime); + } + + if(send_recommended == false) + return; + + // TODO: force send when acceleration changes enough? + float minchange = 0.2*BS; + if(m_last_sent_position_timer > 1.0){ + minchange = 0.01*BS; + } else if(m_last_sent_position_timer > 0.2){ + minchange = 0.05*BS; + } + float move_d = m_base_position.getDistanceFrom(m_last_sent_position); + move_d += m_last_sent_move_precision; + float vel_d = m_velocity.getDistanceFrom(m_last_sent_velocity); + if(move_d > minchange || vel_d > minchange || + fabs(m_yaw - m_last_sent_yaw) > 1.0){ + sendPosition(true, false); + } +} + +std::string LuaEntitySAO::getClientInitializationData() +{ + std::ostringstream os(std::ios::binary); + // version + writeU8(os, 0); + // pos + writeV3F1000(os, m_base_position); + // yaw + writeF1000(os, m_yaw); + // properties + std::ostringstream prop_os(std::ios::binary); + m_prop->serialize(prop_os); + os<getLua(); + std::string state = scriptapi_luaentity_get_staticdata(L, m_id); + os<getGameDef(); + InventoryItem *item = InventoryItem::deSerialize(is, gamedef); return item; } + +void LuaEntitySAO::punch(ServerActiveObject *puncher) +{ + if(!m_registered) + return; + lua_State *L = m_env->getLua(); + scriptapi_luaentity_punch(L, m_id, puncher); +} + +void LuaEntitySAO::rightClick(ServerActiveObject *clicker) +{ + if(!m_registered) + return; + lua_State *L = m_env->getLua(); + scriptapi_luaentity_rightclick(L, m_id, clicker); +} + +void LuaEntitySAO::setPos(v3f pos) +{ + m_base_position = pos; + sendPosition(false, true); +} + +void LuaEntitySAO::moveTo(v3f pos, bool continuous) +{ + m_base_position = pos; + if(!continuous) + sendPosition(true, true); +} + +float LuaEntitySAO::getMinimumSavedMovement() +{ + return 0.1 * BS; +} + +void LuaEntitySAO::setVelocity(v3f velocity) +{ + m_velocity = velocity; +} + +void LuaEntitySAO::setAcceleration(v3f acceleration) +{ + m_acceleration = acceleration; +} + +v3f LuaEntitySAO::getAcceleration() +{ + return m_acceleration; +} + +void LuaEntitySAO::setTextureMod(const std::string &mod) +{ + std::ostringstream os(std::ios::binary); + // command (1 = set texture modification) + writeU8(os, 1); + // parameters + os<getSendRecommendedInterval(); + + std::ostringstream os(std::ios::binary); + // command (0 = update position) + writeU8(os, 0); + + // do_interpolate + writeU8(os, do_interpolate); + // pos + writeV3F1000(os, m_base_position); + // velocity + writeV3F1000(os, m_velocity); + // acceleration + writeV3F1000(os, m_acceleration); + // yaw + writeF1000(os, m_yaw); + // is_end_position (for interpolation) + writeU8(os, is_movement_end); + // update_interval (for interpolation) + writeF1000(os, update_interval); + + // create message and add to list + ActiveObjectMessage aom(getId(), false, os.str()); + m_messages_out.push_back(aom); +} + +