remove Item{S,C}ao, drop items directly to parcels
parent
9cf5666177
commit
02fd4ceb8c
|
@ -34,192 +34,6 @@
|
|||
|
||||
core::map<u16, ClientActiveObject::Factory> ClientActiveObject::m_types;
|
||||
|
||||
/*
|
||||
ItemCAO
|
||||
*/
|
||||
|
||||
#include "inventory.h"
|
||||
|
||||
// Prototype
|
||||
ItemCAO proto_ItemCAO;
|
||||
|
||||
ItemCAO::ItemCAO():
|
||||
ClientActiveObject(0),
|
||||
m_selection_box(-0.25*BS,-0.26*BS,-0.26*BS,0.26*BS,0.26*BS,0.26*BS),
|
||||
m_node(NULL),
|
||||
m_position(v3f(0,10*BS,0)),
|
||||
m_camera_offset(v3s16(0,0,0)),
|
||||
m_content(CONTENT_IGNORE)
|
||||
{
|
||||
ClientActiveObject::registerType(getType(), create);
|
||||
m_rot = myrand_range(0,360);
|
||||
}
|
||||
|
||||
ItemCAO::~ItemCAO()
|
||||
{
|
||||
}
|
||||
|
||||
ClientActiveObject* ItemCAO::create()
|
||||
{
|
||||
return new ItemCAO();
|
||||
}
|
||||
|
||||
void ItemCAO::addToScene(scene::ISceneManager *smgr)
|
||||
{
|
||||
if (m_node == NULL) {
|
||||
m_node = new ExtrudedSpriteSceneNode(smgr->getRootSceneNode(),smgr,-1,v3f(0,0,0),v3f(0,0,0),v3f(5,5,5));
|
||||
m_node->setVisible(false);
|
||||
}
|
||||
|
||||
updateVisual();
|
||||
}
|
||||
|
||||
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);
|
||||
m_node->updateLight(li);
|
||||
}
|
||||
|
||||
v3s16 ItemCAO::getLightPosition()
|
||||
{
|
||||
return floatToInt(m_position, BS);
|
||||
}
|
||||
|
||||
void ItemCAO::updateNodePos()
|
||||
{
|
||||
if (m_node == NULL)
|
||||
return;
|
||||
|
||||
m_node->setPosition(pos_translator.vect_show-intToFloat(m_camera_offset, BS));
|
||||
}
|
||||
|
||||
void ItemCAO::step(float dtime, ClientEnvironment *env)
|
||||
{
|
||||
if (m_node == NULL)
|
||||
return;
|
||||
|
||||
pos_translator.translate(dtime);
|
||||
updateNodePos();
|
||||
|
||||
v3f rot = m_node->getRotation();
|
||||
rot.Y = m_rot++;
|
||||
if (m_rot > 360)
|
||||
m_rot -= 360;
|
||||
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);
|
||||
m_position += v3f(0,BS*0.4,0);
|
||||
pos_translator.update(m_position,m_rot);
|
||||
updateNodePos();
|
||||
}
|
||||
}
|
||||
|
||||
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 == 1) {
|
||||
readF1000(is);
|
||||
}else if (version != 0) {
|
||||
return;
|
||||
}
|
||||
// pos
|
||||
m_position = readV3F1000(is);
|
||||
m_position += v3f(0,BS*0.4,0);
|
||||
// inventorystring
|
||||
m_inventorystring = deSerializeString(is);
|
||||
|
||||
pos_translator.init(m_position,m_rot);
|
||||
}
|
||||
|
||||
|
||||
updateVisual();
|
||||
updateNodePos();
|
||||
}
|
||||
|
||||
void ItemCAO::updateVisual()
|
||||
{
|
||||
if (m_node == NULL)
|
||||
return;
|
||||
InventoryItem *item = NULL;
|
||||
|
||||
// Create an inventory item to see what is its image
|
||||
std::istringstream is(m_inventorystring, std::ios_base::binary);
|
||||
try{
|
||||
item = InventoryItem::deSerialize(is);
|
||||
infostream<<__FUNCTION_NAME<<": m_inventorystring=\""
|
||||
<<m_inventorystring<<"\" -> item="<<item
|
||||
<<std::endl;
|
||||
}
|
||||
catch(SerializationError &e)
|
||||
{
|
||||
infostream<<"WARNING: "<<__FUNCTION_NAME
|
||||
<<": error deSerializing inventorystring \""
|
||||
<<m_inventorystring<<"\""<<std::endl;
|
||||
}
|
||||
if (item == NULL)
|
||||
return;
|
||||
|
||||
bool haveWield = false;
|
||||
|
||||
// Try to make a MaterialItem cube.
|
||||
if (std::string(item->getName()) == "MaterialItem") {
|
||||
// A block-type material
|
||||
MaterialItem* mat_item = (MaterialItem*)item;
|
||||
content_t content = mat_item->getMaterial();
|
||||
if (content_features(content).solidness || content_features(content).visual_solidness) {
|
||||
m_node->setCube(content_features(content).tiles);
|
||||
haveWield = true;
|
||||
}else if (
|
||||
(
|
||||
content_features(content).draw_type == CDT_NODEBOX
|
||||
|| content_features(content).draw_type == CDT_NODEBOX_META
|
||||
|| content_features(content).draw_type == CDT_FENCELIKE
|
||||
|| content_features(content).draw_type == CDT_WALLLIKE
|
||||
)
|
||||
&& content_features(content).wield_nodebox == true
|
||||
) {
|
||||
m_node->setNodeBox(content);
|
||||
haveWield = true;
|
||||
}
|
||||
}
|
||||
|
||||
// If that failed, make an extruded sprite.
|
||||
if (!haveWield)
|
||||
m_node->setSprite(item->getImageRaw());
|
||||
|
||||
m_node->setVisible(true);
|
||||
updateNodePos();
|
||||
m_content = item->getContent();
|
||||
delete item;
|
||||
}
|
||||
|
||||
/*
|
||||
MobCAO
|
||||
*/
|
||||
|
|
|
@ -124,58 +124,6 @@ struct SmoothTranslator
|
|||
}
|
||||
};
|
||||
|
||||
/*
|
||||
ItemCAO
|
||||
*/
|
||||
|
||||
class ItemCAO : public ClientActiveObject
|
||||
{
|
||||
public:
|
||||
ItemCAO();
|
||||
virtual ~ItemCAO();
|
||||
|
||||
u8 getType() const
|
||||
{
|
||||
return ACTIVEOBJECT_TYPE_ITEM;
|
||||
}
|
||||
|
||||
static ClientActiveObject* create();
|
||||
|
||||
void addToScene(scene::ISceneManager *smgr);
|
||||
void removeFromScene();
|
||||
void updateLight(u8 light_at_pos);
|
||||
v3s16 getLightPosition();
|
||||
void updateNodePos();
|
||||
|
||||
void step(float dtime, ClientEnvironment *env);
|
||||
|
||||
void processMessage(const std::string &data);
|
||||
|
||||
void initialize(const std::string &data);
|
||||
|
||||
core::aabbox3d<f32>* getSelectionBox() {return &m_selection_box;}
|
||||
v3f getPosition() {return pos_translator.vect_show;}
|
||||
|
||||
void updateCameraOffset(v3s16 camera_offset)
|
||||
{
|
||||
m_camera_offset = camera_offset;
|
||||
}
|
||||
|
||||
virtual content_t getContent() {return m_content;}
|
||||
|
||||
private:
|
||||
void updateVisual();
|
||||
|
||||
core::aabbox3d<f32> m_selection_box;
|
||||
ExtrudedSpriteSceneNode *m_node;
|
||||
v3f m_position;
|
||||
v3s16 m_camera_offset;
|
||||
std::string m_inventorystring;
|
||||
content_t m_content;
|
||||
f32 m_rot;
|
||||
SmoothTranslator pos_translator;
|
||||
};
|
||||
|
||||
/*
|
||||
MobCAO
|
||||
*/
|
||||
|
|
|
@ -271,6 +271,8 @@ void content_mapnode_plants(bool repeat)
|
|||
f->ondig_special_drop = CONTENT_TRIMMED_LEAVES;
|
||||
f->ondig_special_drop_count = 1;
|
||||
f->ondig_special_tool = TT_SHEAR;
|
||||
f->place_on_drop = CONTENT_SAPLING;
|
||||
f->place_on_drop_alternate = CONTENT_WILDGRASS_SHORT;
|
||||
f->type = CMT_PLANT;
|
||||
f->hardness = 0.15;
|
||||
f->pressure_type = CST_CRUSHABLE;
|
||||
|
@ -302,6 +304,8 @@ void content_mapnode_plants(bool repeat)
|
|||
f->ondig_special_drop = CONTENT_TRIMMED_LEAVES_AUTUMN;
|
||||
f->ondig_special_drop_count = 1;
|
||||
f->ondig_special_tool = TT_SHEAR;
|
||||
f->place_on_drop = CONTENT_SAPLING;
|
||||
f->place_on_drop_alternate = CONTENT_WILDGRASS_SHORT;
|
||||
f->type = CMT_PLANT;
|
||||
f->hardness = 0.15;
|
||||
f->pressure_type = CST_CRUSHABLE;
|
||||
|
@ -333,6 +337,8 @@ void content_mapnode_plants(bool repeat)
|
|||
f->ondig_special_drop = CONTENT_TRIMMED_LEAVES_WINTER;
|
||||
f->ondig_special_drop_count = 1;
|
||||
f->ondig_special_tool = TT_SHEAR;
|
||||
f->place_on_drop = CONTENT_SAPLING;
|
||||
f->place_on_drop_alternate = CONTENT_WILDGRASS_SHORT;
|
||||
f->type = CMT_PLANT;
|
||||
f->hardness = 0.15;
|
||||
f->pressure_type = CST_CRUSHABLE;
|
||||
|
@ -364,6 +370,8 @@ void content_mapnode_plants(bool repeat)
|
|||
f->ondig_special_drop = CONTENT_TRIMMED_LEAVES_WINTER;
|
||||
f->ondig_special_drop_count = 1;
|
||||
f->ondig_special_tool = TT_SHEAR;
|
||||
f->place_on_drop = CONTENT_SAPLING;
|
||||
f->place_on_drop_alternate = CONTENT_WILDGRASS_SHORT;
|
||||
f->type = CMT_PLANT;
|
||||
f->hardness = 0.15;
|
||||
f->pressure_type = CST_CRUSHABLE;
|
||||
|
@ -396,6 +404,8 @@ void content_mapnode_plants(bool repeat)
|
|||
f->ondig_special_drop = CONTENT_TRIMMED_APPLE_LEAVES;
|
||||
f->ondig_special_drop_count = 1;
|
||||
f->ondig_special_tool = TT_SHEAR;
|
||||
f->place_on_drop = CONTENT_APPLE_SAPLING;
|
||||
f->place_on_drop_alternate = CONTENT_WILDGRASS_SHORT;
|
||||
f->type = CMT_PLANT;
|
||||
f->hardness = 0.15;
|
||||
f->pressure_type = CST_CRUSHABLE;
|
||||
|
@ -427,6 +437,8 @@ void content_mapnode_plants(bool repeat)
|
|||
f->ondig_special_drop = CONTENT_TRIMMED_JUNGLE_LEAVES;
|
||||
f->ondig_special_drop_count = 1;
|
||||
f->ondig_special_tool = TT_SHEAR;
|
||||
f->place_on_drop = CONTENT_JUNGLESAPLING;
|
||||
f->place_on_drop_alternate = CONTENT_WILDGRASS_SHORT;
|
||||
f->type = CMT_PLANT;
|
||||
f->hardness = 0.15;
|
||||
f->pressure_type = CST_CRUSHABLE;
|
||||
|
@ -458,6 +470,8 @@ void content_mapnode_plants(bool repeat)
|
|||
f->ondig_special_drop = CONTENT_TRIMMED_CONIFER_LEAVES;
|
||||
f->ondig_special_drop_count = 1;
|
||||
f->ondig_special_tool = TT_SHEAR;
|
||||
f->place_on_drop = CONTENT_CONIFER_SAPLING;
|
||||
f->place_on_drop_alternate = CONTENT_WILDGRASS_SHORT;
|
||||
f->type = CMT_PLANT;
|
||||
f->hardness = 0.15;
|
||||
f->pressure_type = CST_CRUSHABLE;
|
||||
|
|
|
@ -347,31 +347,15 @@ bool CampBedNodeMetadata::step(float dtime, v3s16 pos, ServerEnvironment *env)
|
|||
if (fp == pos)
|
||||
return false;
|
||||
|
||||
MapNode nn = env->getMap().getNodeNoEx(fp);
|
||||
nn.setContent(CONTENT_PARCEL);
|
||||
env->getMap().addNodeWithEvent(fp,nn);
|
||||
NodeMetadata *meta = env->getMap().getNodeMetadata(fp);
|
||||
if (meta) {
|
||||
Inventory* inv = meta->getInventory();
|
||||
if (inv) {
|
||||
InventoryList *l = inv->getList("0");
|
||||
if (l) {
|
||||
// add random dead grass/fur to parcel
|
||||
{
|
||||
u16 c = myrand_range(1,4);
|
||||
InventoryItem *item = InventoryItem::create(CONTENT_DEADGRASS,c);
|
||||
item = l->addItem(item);
|
||||
if (item)
|
||||
delete item;
|
||||
}
|
||||
if (myrand_range(0,1)) {
|
||||
InventoryItem *item = InventoryItem::create(CONTENT_CRAFTITEM_FUR,1);
|
||||
item = l->addItem(item);
|
||||
if (item)
|
||||
delete item;
|
||||
}
|
||||
}
|
||||
}
|
||||
// add random dead grass/fur to parcel
|
||||
{
|
||||
u16 c = myrand_range(1,4);
|
||||
InventoryItem *item = InventoryItem::create(CONTENT_DEADGRASS,c);
|
||||
env->dropToParcel(pos,item);
|
||||
}
|
||||
if (myrand_range(0,1)) {
|
||||
InventoryItem *item = InventoryItem::create(CONTENT_CRAFTITEM_FUR,1);
|
||||
env->dropToParcel(pos,item);
|
||||
}
|
||||
|
||||
n.setContent(CONTENT_DEADGRASS);
|
||||
|
|
|
@ -28,11 +28,11 @@
|
|||
#define CONTENT_OBJECT_HEADER
|
||||
|
||||
#define ACTIVEOBJECT_TYPE_TEST 1
|
||||
#define ACTIVEOBJECT_TYPE_ITEM 2
|
||||
#define ACTIVEOBJECT_TYPE_RAT 3
|
||||
#define ACTIVEOBJECT_TYPE_OERKKI1 4
|
||||
#define ACTIVEOBJECT_TYPE_FIREFLY 5
|
||||
#define ACTIVEOBJECT_TYPE_MOBV2 6
|
||||
//#define ACTIVEOBJECT_TYPE_ITEM 2
|
||||
//#define ACTIVEOBJECT_TYPE_RAT 3
|
||||
//#define ACTIVEOBJECT_TYPE_OERKKI1 4
|
||||
//#define ACTIVEOBJECT_TYPE_FIREFLY 5
|
||||
//#define ACTIVEOBJECT_TYPE_MOBV2 6
|
||||
#define ACTIVEOBJECT_TYPE_MOB 7
|
||||
|
||||
#endif
|
||||
|
|
|
@ -53,313 +53,6 @@ void accelerate_xz(v3f &speed, v3f target_speed, f32 max_increase)
|
|||
speed.Y = target_speed.Y;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
ItemSAO
|
||||
*/
|
||||
|
||||
// Prototype
|
||||
ItemSAO proto_ItemSAO(NULL, 0, v3f(0,0,0), "");
|
||||
|
||||
ItemSAO::ItemSAO(ServerEnvironment *env, u16 id, v3f pos, const std::string inventorystring):
|
||||
ServerActiveObject(env, id, pos),
|
||||
m_inventorystring(inventorystring),
|
||||
m_speed_f(0,0,0),
|
||||
m_last_sent_position(0,0,0),
|
||||
m_age(600.0)
|
||||
{
|
||||
ServerActiveObject::registerType(getType(), create);
|
||||
std::istringstream is(m_inventorystring, std::ios_base::binary);
|
||||
try{
|
||||
InventoryItem *item = NULL;
|
||||
item = InventoryItem::deSerialize(is);
|
||||
if (item) {
|
||||
m_content = item->getContent();
|
||||
delete item;
|
||||
}
|
||||
}catch(SerializationError &e) {}
|
||||
}
|
||||
|
||||
ItemSAO::ItemSAO(ServerEnvironment *env, u16 id, v3f pos, float age, const std::string inventorystring):
|
||||
ServerActiveObject(env, id, pos),
|
||||
m_inventorystring(inventorystring),
|
||||
m_speed_f(0,0,0),
|
||||
m_last_sent_position(0,0,0),
|
||||
m_age(age)
|
||||
{
|
||||
ServerActiveObject::registerType(getType(), create);
|
||||
std::istringstream is(m_inventorystring, std::ios_base::binary);
|
||||
try{
|
||||
InventoryItem *item = NULL;
|
||||
item = InventoryItem::deSerialize(is);
|
||||
if (item) {
|
||||
m_content = item->getContent();
|
||||
delete item;
|
||||
}
|
||||
}catch(SerializationError &e) {}
|
||||
}
|
||||
|
||||
ServerActiveObject* ItemSAO::create(ServerEnvironment *env, u16 id, 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];
|
||||
float age = 600.0;
|
||||
// check if version is supported
|
||||
if (version == 1) {
|
||||
age = readF1000(is);
|
||||
}else if (version != 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
std::string inventorystring = deSerializeString(is);
|
||||
infostream<<"ItemSAO::create(): Creating item \""<<inventorystring<<"\""<<std::endl;
|
||||
return new ItemSAO(env, id, pos, age, inventorystring);
|
||||
}
|
||||
|
||||
void ItemSAO::step(float dtime, bool send_recommended)
|
||||
{
|
||||
ScopeProfiler sp2(g_profiler, "ItemSAO::step avg", SPT_AVG);
|
||||
|
||||
assert(m_env);
|
||||
|
||||
// craftitems, and materialitems should die after a while
|
||||
if (
|
||||
(m_content&CONTENT_TOOLITEM_MASK) == 0
|
||||
&& (m_content&CONTENT_CLOTHESITEM_MASK) == 0
|
||||
) {
|
||||
m_age -= dtime;
|
||||
if (m_age < 0.0) {
|
||||
m_removed = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
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.5;
|
||||
// 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 accel_f = v3f(0,0,0);
|
||||
moveresult = collisionMoveSimple(&m_env->getMap(), pos_max_d,
|
||||
box, 0.0, dtime, pos_f, m_speed_f, accel_f);
|
||||
|
||||
if (moveresult.touching_ground) {
|
||||
v3s16 pos_i = floatToInt(pos_f,BS);
|
||||
MapNode n = m_env->getMap().getNodeNoEx(pos_i);
|
||||
MapNode un = m_env->getMap().getNodeNoEx(pos_i+v3s16(0,-1,0));
|
||||
bool parcel = false;
|
||||
InventoryItem *item = createInventoryItem();
|
||||
if (un.getContent() == CONTENT_AIR) {
|
||||
// item is stuck on the edge of something
|
||||
setBasePosition(intToFloat(pos_i,BS));
|
||||
return;
|
||||
}else if (
|
||||
item
|
||||
&& item->getCount() == 1
|
||||
&& (
|
||||
m_content == CONTENT_LEAVES
|
||||
|| m_content == CONTENT_JUNGLELEAVES
|
||||
|| m_content == CONTENT_APPLE_LEAVES
|
||||
|| m_content == CONTENT_CONIFER_LEAVES
|
||||
|| m_content == CONTENT_LEAVES_AUTUMN
|
||||
|| m_content == CONTENT_LEAVES_WINTER
|
||||
|| m_content == CONTENT_LEAVES_SNOWY
|
||||
)
|
||||
) { // leaves falling on grass become either saplings or wild grass
|
||||
if (
|
||||
un.getContent() == CONTENT_MUD
|
||||
|| un.getContent() == CONTENT_GRASS
|
||||
|| un.getContent() == CONTENT_GRASS_FOOTSTEPS
|
||||
|| un.getContent() == CONTENT_GRASS_AUTUMN
|
||||
|| un.getContent() == CONTENT_GRASS_FOOTSTEPS_AUTUMN
|
||||
|| un.getContent() == CONTENT_MUDSNOW
|
||||
) {
|
||||
content_t c = CONTENT_SAPLING;
|
||||
std::vector<content_t> search;
|
||||
search.push_back(CONTENT_SAPLING);
|
||||
search.push_back(CONTENT_JUNGLESAPLING);
|
||||
search.push_back(CONTENT_APPLE_SAPLING);
|
||||
search.push_back(CONTENT_CONIFER_SAPLING);
|
||||
if (m_env->searchNear(pos_i,v3s16(3,3,3),search,NULL)) {
|
||||
c = CONTENT_WILDGRASS_SHORT;
|
||||
}else{
|
||||
switch (m_content) {
|
||||
case CONTENT_JUNGLELEAVES:
|
||||
c = CONTENT_JUNGLESAPLING;
|
||||
break;
|
||||
case CONTENT_APPLE_LEAVES:
|
||||
c = CONTENT_APPLE_SAPLING;
|
||||
break;
|
||||
case CONTENT_CONIFER_LEAVES:
|
||||
c = CONTENT_CONIFER_SAPLING;
|
||||
break;
|
||||
default:;
|
||||
}
|
||||
}
|
||||
n.setContent(c);
|
||||
m_env->getMap().addNodeWithEvent(pos_i,n);
|
||||
}
|
||||
delete item;
|
||||
m_removed = true;
|
||||
return;
|
||||
}else if (!content_craftitem_features(m_content).consumable) {
|
||||
v3s16 pp;
|
||||
if (n.getContent() == CONTENT_PARCEL) {
|
||||
parcel = true;
|
||||
}else if (m_env->searchNear(pos_i,v3s16(3,3,3),CONTENT_PARCEL,&pp)) {
|
||||
pos_i = pp;
|
||||
parcel = true;
|
||||
}else if (n.getContent() == CONTENT_LAVASOURCE) {
|
||||
m_removed = true;
|
||||
}else if (content_features(n).buildable_to) {
|
||||
n.setContent(CONTENT_PARCEL);
|
||||
m_env->getMap().addNodeWithEvent(pos_i,n);
|
||||
parcel = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (item && parcel) {
|
||||
NodeMetadata *meta = m_env->getMap().getNodeMetadata(pos_i);
|
||||
if (!meta)
|
||||
return;
|
||||
Inventory *inv = meta->getInventory();
|
||||
if (!inv)
|
||||
return;
|
||||
InventoryList *l = inv->getList("0");
|
||||
if (!l)
|
||||
return;
|
||||
l->addItem(item);
|
||||
m_removed = true;
|
||||
|
||||
{
|
||||
v3s16 bp = getNodeBlockPos(pos_i);
|
||||
MapBlock *block = m_env->getMap().getBlockNoCreateNoEx(bp);
|
||||
if (block) {
|
||||
MapEditEvent event;
|
||||
event.type = MEET_BLOCK_NODE_METADATA_CHANGED;
|
||||
event.p = bp;
|
||||
m_env->getMap().dispatchEvent(&event);
|
||||
|
||||
block->setChangedFlag();
|
||||
}
|
||||
}
|
||||
}else if (item) {
|
||||
delete item;
|
||||
}
|
||||
}
|
||||
|
||||
if (send_recommended == false)
|
||||
return;
|
||||
|
||||
if (pos_f.getDistanceFrom(m_last_sent_position) > 0.05*BS) {
|
||||
setBasePosition(pos_f);
|
||||
m_last_sent_position = pos_f;
|
||||
|
||||
std::ostringstream os(std::ios::binary);
|
||||
char buf[6];
|
||||
// command (0 = update position)
|
||||
buf[0] = 0;
|
||||
os.write(buf, 1);
|
||||
// pos
|
||||
writeS32((u8*)buf, m_base_position.X*1000);
|
||||
os.write(buf, 4);
|
||||
writeS32((u8*)buf, m_base_position.Y*1000);
|
||||
os.write(buf, 4);
|
||||
writeS32((u8*)buf, m_base_position.Z*1000);
|
||||
os.write(buf, 4);
|
||||
// create message and add to list
|
||||
ActiveObjectMessage aom(getId(), false, os.str());
|
||||
m_messages_out.push_back(aom);
|
||||
}
|
||||
}
|
||||
|
||||
std::string ItemSAO::getClientInitializationData()
|
||||
{
|
||||
std::ostringstream os(std::ios::binary);
|
||||
char buf[6];
|
||||
// version
|
||||
buf[0] = 1;
|
||||
os.write(buf, 1);
|
||||
// age
|
||||
writeF1000(os,m_age);
|
||||
// pos
|
||||
writeS32((u8*)buf, m_base_position.X*1000);
|
||||
os.write(buf, 4);
|
||||
writeS32((u8*)buf, m_base_position.Y*1000);
|
||||
os.write(buf, 4);
|
||||
writeS32((u8*)buf, m_base_position.Z*1000);
|
||||
os.write(buf, 4);
|
||||
// inventorystring
|
||||
os<<serializeString(m_inventorystring);
|
||||
return os.str();
|
||||
}
|
||||
|
||||
std::string ItemSAO::getStaticData()
|
||||
{
|
||||
infostream<<__FUNCTION_NAME<<std::endl;
|
||||
std::ostringstream os(std::ios::binary);
|
||||
char buf[1];
|
||||
// version
|
||||
buf[0] = 1;
|
||||
os.write(buf, 1);
|
||||
// age
|
||||
writeF1000(os,m_age);
|
||||
// inventorystring
|
||||
os<<serializeString(m_inventorystring);
|
||||
return os.str();
|
||||
}
|
||||
|
||||
InventoryItem * ItemSAO::createInventoryItem()
|
||||
{
|
||||
try{
|
||||
std::istringstream is(m_inventorystring, std::ios_base::binary);
|
||||
InventoryItem *item = InventoryItem::deSerialize(is);
|
||||
infostream<<__FUNCTION_NAME<<": m_inventorystring=\""
|
||||
<<m_inventorystring<<"\" -> item="<<item
|
||||
<<std::endl;
|
||||
return item;
|
||||
}
|
||||
catch(SerializationError &e)
|
||||
{
|
||||
infostream<<__FUNCTION_NAME<<": serialization error: "
|
||||
<<"m_inventorystring=\""<<m_inventorystring<<"\""<<std::endl;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
bool ItemSAO::rightClick(Player *player)
|
||||
{
|
||||
infostream<<__FUNCTION_NAME<<std::endl;
|
||||
InventoryItem *item = createInventoryItem();
|
||||
if (item == NULL)
|
||||
return false;
|
||||
|
||||
bool to_be_deleted = item->use(m_env, player);
|
||||
|
||||
if(to_be_deleted)
|
||||
m_removed = true;
|
||||
else
|
||||
// Reflect changes to the item here
|
||||
m_inventorystring = item->getItemString();
|
||||
|
||||
delete item;
|
||||
return false;
|
||||
}
|
||||
|
||||
static void get_random_u32_array(u32 a[], u32 len)
|
||||
{
|
||||
u32 i, n;
|
||||
|
@ -713,9 +406,6 @@ void MobSAO::step(float dtime, bool send_recommended)
|
|||
if (obj->getType() == ACTIVEOBJECT_TYPE_MOB) {
|
||||
((MobSAO*)obj)->doDamage(m.attack_mob_damage);
|
||||
hit = true;
|
||||
}else if (obj->getType() == ACTIVEOBJECT_TYPE_ITEM) {
|
||||
((ItemSAO*)obj)->m_removed = true;
|
||||
hit = true;
|
||||
}
|
||||
}
|
||||
if (hit)
|
||||
|
|
|
@ -31,30 +31,6 @@
|
|||
#include "content_object.h"
|
||||
#include "content_mob.h"
|
||||
|
||||
class ItemSAO : public ServerActiveObject
|
||||
{
|
||||
public:
|
||||
ItemSAO(ServerEnvironment *env, u16 id, v3f pos, const std::string inventorystring);
|
||||
ItemSAO(ServerEnvironment *env, u16 id, v3f pos, float age, const std::string inventorystring);
|
||||
u8 getType() const
|
||||
{return ACTIVEOBJECT_TYPE_ITEM;}
|
||||
static ServerActiveObject* create(ServerEnvironment *env, u16 id, v3f pos,
|
||||
const std::string &data);
|
||||
void step(float dtime, bool send_recommended);
|
||||
std::string getClientInitializationData();
|
||||
std::string getStaticData();
|
||||
InventoryItem* createInventoryItem();
|
||||
InventoryItem* createPickedUpItem(content_t punch_item){return createInventoryItem();}
|
||||
bool rightClick(Player *player);
|
||||
private:
|
||||
std::string m_inventorystring;
|
||||
v3f m_speed_f;
|
||||
v3f m_last_sent_position;
|
||||
IntervalLimiter m_move_interval;
|
||||
float m_age;
|
||||
content_t m_content;
|
||||
};
|
||||
|
||||
class MobSAO : public ServerActiveObject
|
||||
{
|
||||
public:
|
||||
|
|
|
@ -804,6 +804,275 @@ bool ServerEnvironment::searchNearInv(v3s16 pos, v3s16 radius_min, v3s16 radius_
|
|||
return false;
|
||||
}
|
||||
|
||||
/* search from pos in direction dir, until a collidable node is hit
|
||||
* if pos is a collidable node, then search till not collidable
|
||||
* return false if CONTENT_IGNORE is found
|
||||
* return true otherwise
|
||||
* result is a non-collidable node, which is:
|
||||
* the first liquid node found
|
||||
* if searching till not collidable:
|
||||
* the first walkable node found
|
||||
* else
|
||||
* the last walkable node found
|
||||
*/
|
||||
bool ServerEnvironment::getCollidedPosition(v3s16 pos, v3s16 dir, v3s16 *result)
|
||||
{
|
||||
ContentFeatures *f;
|
||||
v3s16 cpos = pos;
|
||||
MapNode n = m_map->getNodeNoEx(pos);
|
||||
if (n.getContent() == CONTENT_IGNORE)
|
||||
return false;
|
||||
|
||||
f = &content_features(n.getContent());
|
||||
|
||||
// if pos is a collidable node, search till not collidable
|
||||
if (!f->walkable) {
|
||||
while (!f->walkable) {
|
||||
cpos += dir;
|
||||
n = m_map->getNodeNoEx(cpos);
|
||||
if (n.getContent() == CONTENT_IGNORE)
|
||||
return false;
|
||||
|
||||
f = &content_features(n.getContent());
|
||||
}
|
||||
//else search till collidable, then go back one
|
||||
}else{
|
||||
while (f->walkable) {
|
||||
cpos += dir;
|
||||
n = m_map->getNodeNoEx(cpos);
|
||||
if (n.getContent() == CONTENT_IGNORE)
|
||||
return false;
|
||||
|
||||
f = &content_features(n.getContent());
|
||||
}
|
||||
cpos -= dir;
|
||||
n = m_map->getNodeNoEx(cpos);
|
||||
f = &content_features(n.getContent());
|
||||
}
|
||||
|
||||
// if node is liquid, or air_equivalent and buildable_to, return true
|
||||
if (f->liquid_type != LIQUID_NONE || (f->air_equivalent && f->buildable_to)) {
|
||||
if (result)
|
||||
*result = cpos;
|
||||
return true;
|
||||
}
|
||||
|
||||
// otherwise, reverse direction, but no further than (but including) pos
|
||||
// search for last air_equivalent and buildable_to
|
||||
while (cpos != pos) {
|
||||
cpos -= dir;
|
||||
n = m_map->getNodeNoEx(cpos);
|
||||
if (n.getContent() == CONTENT_IGNORE)
|
||||
return false;
|
||||
|
||||
f = &content_features(n.getContent());
|
||||
if (f->liquid_type != LIQUID_NONE || (f->air_equivalent && f->buildable_to)) {
|
||||
if (result)
|
||||
*result = cpos;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
n = m_map->getNodeNoEx(cpos);
|
||||
if (n.getContent() == CONTENT_IGNORE)
|
||||
return false;
|
||||
|
||||
f = &content_features(n.getContent());
|
||||
|
||||
// if found, return true
|
||||
if (f->liquid_type != LIQUID_NONE || (f->air_equivalent && f->buildable_to)) {
|
||||
if (result)
|
||||
*result = cpos;
|
||||
return true;
|
||||
}
|
||||
|
||||
// otherwise, return false
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ServerEnvironment::dropToParcel(v3s16 pos, InventoryItem *item)
|
||||
{
|
||||
v3s16 ppos;
|
||||
NodeMetadata *meta;
|
||||
Inventory *inv;
|
||||
InventoryList *list;
|
||||
|
||||
if (!item)
|
||||
return true;
|
||||
|
||||
// check for single material item and above dirtlike
|
||||
// if so, and it has a place_on_drop then
|
||||
if (
|
||||
item->getCount() == 1
|
||||
&& (item->getContent()&0xF000) == 0
|
||||
&& content_features(item->getContent()).place_on_drop != CONTENT_IGNORE
|
||||
&& getCollidedPosition(pos,v3s16(0,-1,0),&ppos)
|
||||
&& content_features(m_map->getNodeNoEx(ppos+v3s16(0,-1,0)).getContent()).draw_type == CDT_DIRTLIKE
|
||||
) {
|
||||
ContentFeatures *f = &content_features(item->getContent());
|
||||
// if it's landing on a place_on_drop, destroy it
|
||||
if (m_map->getNodeNoEx(ppos).getContent() == f->place_on_drop) {
|
||||
delete item;
|
||||
return true;
|
||||
// it has a place_on_drop_alternate and a place_on_drop is nearby
|
||||
}else if (f->place_on_drop_alternate && searchNear(ppos,v3s16(3,3,3),f->place_on_drop,NULL)) {
|
||||
// place place_on_drop_alternate at pos
|
||||
MapNode n(f->place_on_drop_alternate);
|
||||
m_map->addNodeWithEvent(ppos,n);
|
||||
delete item;
|
||||
return true;
|
||||
// else place place_on_drop
|
||||
}else{
|
||||
MapNode n(f->place_on_drop);
|
||||
m_map->addNodeWithEvent(ppos,n);
|
||||
delete item;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// look for a parcel near pos
|
||||
if (searchNear(pos,v3s16(3,3,3),CONTENT_PARCEL,&ppos)) {
|
||||
// add items if found
|
||||
meta = m_map->getNodeMetadata(ppos);
|
||||
if (meta) {
|
||||
inv = meta->getInventory();
|
||||
if (inv) {
|
||||
list = inv->getList("0");
|
||||
if (list)
|
||||
item = list->addItem(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!item) {
|
||||
v3s16 bp = getNodeBlockPos(ppos);
|
||||
MapBlock *block = m_map->getBlockNoCreateNoEx(bp);
|
||||
if (block) {
|
||||
MapEditEvent event;
|
||||
event.type = MEET_BLOCK_NODE_METADATA_CHANGED;
|
||||
event.p = bp;
|
||||
m_map->dispatchEvent(&event);
|
||||
|
||||
block->setChangedFlag();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// if underground, go up to first air_equivalent and buildable_to
|
||||
if (!content_features(m_map->getNodeNoEx(pos).getContent()).air_equivalent) {
|
||||
if (!getCollidedPosition(pos,v3s16(0,1,0),&ppos)) {
|
||||
delete item;
|
||||
return false;
|
||||
}
|
||||
pos = ppos;
|
||||
// otherwise go down to first non-air_equivalent and buildable_to
|
||||
}else{
|
||||
if (!getCollidedPosition(pos,v3s16(0,-1,0),&ppos)) {
|
||||
delete item;
|
||||
return false;
|
||||
}
|
||||
pos = ppos;
|
||||
}
|
||||
|
||||
// look for a parcel near pos
|
||||
if (searchNear(pos,v3s16(3,3,3),CONTENT_PARCEL,&ppos)) {
|
||||
// add items if found
|
||||
meta = m_map->getNodeMetadata(ppos);
|
||||
if (meta) {
|
||||
inv = meta->getInventory();
|
||||
if (inv) {
|
||||
list = inv->getList("0");
|
||||
if (list)
|
||||
item = list->addItem(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!item) {
|
||||
v3s16 bp = getNodeBlockPos(ppos);
|
||||
MapBlock *block = m_map->getBlockNoCreateNoEx(bp);
|
||||
if (block) {
|
||||
MapEditEvent event;
|
||||
event.type = MEET_BLOCK_NODE_METADATA_CHANGED;
|
||||
event.p = bp;
|
||||
m_map->dispatchEvent(&event);
|
||||
|
||||
block->setChangedFlag();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// if liquid, do a slightly wider search for a parcel on shore
|
||||
if (content_features(m_map->getNodeNoEx(pos).getContent()).liquid_type != LIQUID_NONE) {
|
||||
if (content_features(m_map->getNodeNoEx(pos).getContent()).damage_per_second > 0) {
|
||||
delete item;
|
||||
return false;
|
||||
}else if (searchNear(pos,v3s16(5,5,5),CONTENT_PARCEL,&ppos)) {
|
||||
// add items if found
|
||||
meta = m_map->getNodeMetadata(ppos);
|
||||
if (meta) {
|
||||
inv = meta->getInventory();
|
||||
if (inv) {
|
||||
list = inv->getList("0");
|
||||
if (list)
|
||||
item = list->addItem(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!item) {
|
||||
v3s16 bp = getNodeBlockPos(ppos);
|
||||
MapBlock *block = m_map->getBlockNoCreateNoEx(bp);
|
||||
if (block) {
|
||||
MapEditEvent event;
|
||||
event.type = MEET_BLOCK_NODE_METADATA_CHANGED;
|
||||
event.p = bp;
|
||||
m_map->dispatchEvent(&event);
|
||||
|
||||
block->setChangedFlag();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// check that pos is air_equivalent and buildable_to
|
||||
{
|
||||
ContentFeatures *f = &content_features(m_map->getNodeNoEx(pos).getContent());
|
||||
if (f->liquid_type != LIQUID_NONE || (f->air_equivalent && f->buildable_to)) {
|
||||
// create a parcel
|
||||
MapNode n(CONTENT_PARCEL);
|
||||
m_map->addNodeWithEvent(pos,n);
|
||||
// add items
|
||||
meta = m_map->getNodeMetadata(pos);
|
||||
if (meta) {
|
||||
inv = meta->getInventory();
|
||||
if (inv) {
|
||||
list = inv->getList("0");
|
||||
if (list)
|
||||
item = list->addItem(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!item) {
|
||||
v3s16 bp = getNodeBlockPos(pos);
|
||||
MapBlock *block = m_map->getBlockNoCreateNoEx(bp);
|
||||
if (block) {
|
||||
MapEditEvent event;
|
||||
event.type = MEET_BLOCK_NODE_METADATA_CHANGED;
|
||||
event.p = bp;
|
||||
m_map->dispatchEvent(&event);
|
||||
|
||||
block->setChangedFlag();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
delete item;
|
||||
return false;
|
||||
}
|
||||
|
||||
void ServerEnvironment::step(float dtime)
|
||||
{
|
||||
DSTACK(__FUNCTION_NAME);
|
||||
|
@ -1101,16 +1370,6 @@ void ServerEnvironment::step(float dtime)
|
|||
Everything should bind to inside this single content
|
||||
searching loop to keep things fast.
|
||||
*/
|
||||
u32 active_object_count_wider = 0;
|
||||
for (s16 x=-1; x<=1; x++)
|
||||
for (s16 y=-1; y<=1; y++)
|
||||
for (s16 z=-1; z<=1; z++) {
|
||||
MapBlock *wblock = m_map->getBlockNoCreateNoEx(bp+v3s16(x,y,z));
|
||||
if (wblock == NULL)
|
||||
continue;
|
||||
active_object_count_wider += wblock->m_static_objects.m_objects.size();
|
||||
active_object_count_wider += wblock->m_active_objects.size();
|
||||
}
|
||||
|
||||
if (block->last_spawn < m_time_of_day-6000) {
|
||||
MapNode n1 = block->getNodeNoEx(block->spawn_area+v3s16(0,1,0));
|
||||
|
@ -1713,12 +1972,8 @@ void ServerEnvironment::step(float dtime)
|
|||
m_map->addNodeWithEvent(p, n);
|
||||
}else{
|
||||
m_map->removeNodeWithEvent(p);
|
||||
if (active_object_count_wider < 10) {
|
||||
v3f rot_pos = intToFloat(p, BS);
|
||||
rot_pos += v3f(myrand_range(-1500,1500)*1.0/1000, 0, myrand_range(-1500,1500)*1.0/1000);
|
||||
ServerActiveObject *obj = new ItemSAO(this, 0, rot_pos, "CraftItem mush 1");
|
||||
addActiveObject(obj);
|
||||
}
|
||||
InventoryItem *item = InventoryItem::create(CONTENT_CRAFTITEM_MUSH,1,0,0);
|
||||
dropToParcel(p,item);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -1762,10 +2017,8 @@ void ServerEnvironment::step(float dtime)
|
|||
if (!searchNear(p,v3s16(3,3,3),search,NULL)) {
|
||||
m_map->removeNodeWithEvent(leaf_p);
|
||||
if (myrand()%10 == 0) {
|
||||
v3f sapling_pos = intToFloat(leaf_p, BS);
|
||||
sapling_pos += v3f(myrand_range(-1500,1500)*1.0/1000, 0, myrand_range(-1500,1500)*1.0/1000);
|
||||
ServerActiveObject *obj = new ItemSAO(this, 0, sapling_pos, "MaterialItem2 " + itos(n.getContent()) + " 1");
|
||||
addActiveObject(obj);
|
||||
InventoryItem *item = InventoryItem::create(n.getContent(),1,0,0);
|
||||
dropToParcel(p,item);
|
||||
}
|
||||
}else if (n.getContent() == CONTENT_LEAVES) {
|
||||
if (season == ENV_SEASON_AUTUMN) {
|
||||
|
@ -1832,10 +2085,8 @@ void ServerEnvironment::step(float dtime)
|
|||
if (myrand()%5 == 0) {
|
||||
n.setContent(CONTENT_APPLE_LEAVES);
|
||||
m_map->addNodeWithEvent(p, n);
|
||||
v3f blossom_pos = intToFloat(p, BS);
|
||||
blossom_pos += v3f(myrand_range(-1500,1500)*1.0/1000, 0, myrand_range(-1500,1500)*1.0/1000);
|
||||
ServerActiveObject *obj = new ItemSAO(this, 0, blossom_pos, "CraftItem apple_blossom 1");
|
||||
addActiveObject(obj);
|
||||
InventoryItem *item = InventoryItem::create(CONTENT_CRAFTITEM_APPLE_BLOSSOM,1,0,0);
|
||||
dropToParcel(p,item);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1873,17 +2124,13 @@ void ServerEnvironment::step(float dtime)
|
|||
}
|
||||
if (n.envticks > 10) {
|
||||
m_map->removeNodeWithEvent(p);
|
||||
v3f ash_pos = intToFloat(p, BS);
|
||||
ash_pos += v3f(myrand_range(-1500,1500)*1.0/1000, 0, myrand_range(-1500,1500)*1.0/1000);
|
||||
ServerActiveObject *obj = new ItemSAO(this, 0, ash_pos, "CraftItem lump_of_ash 1");
|
||||
addActiveObject(obj);
|
||||
InventoryItem *item = InventoryItem::create(CONTENT_CRAFTITEM_ASH,1,0,0);
|
||||
dropToParcel(p,item);
|
||||
}
|
||||
}else if (n.envticks > 2) {
|
||||
m_map->removeNodeWithEvent(p);
|
||||
v3f ash_pos = intToFloat(p, BS);
|
||||
ash_pos += v3f(myrand_range(-1500,1500)*1.0/1000, 0, myrand_range(-1500,1500)*1.0/1000);
|
||||
ServerActiveObject *obj = new ItemSAO(this, 0, ash_pos, "CraftItem lump_of_ash 1");
|
||||
addActiveObject(obj);
|
||||
InventoryItem *item = InventoryItem::create(CONTENT_CRAFTITEM_ASH,1,0,0);
|
||||
dropToParcel(p,item);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -2493,17 +2740,13 @@ void ServerEnvironment::step(float dtime)
|
|||
search.push_back(CONTENT_IGNORE);
|
||||
if (!searchNear(p,v3s16(1,1,1),search,NULL)) {
|
||||
m_map->removeNodeWithEvent(apple_p);
|
||||
v3f apple_pos = intToFloat(apple_p, BS);
|
||||
apple_pos += v3f(myrand_range(-1500,1500)*1.0/1000, 0, myrand_range(-1500,1500)*1.0/1000);
|
||||
ServerActiveObject *obj = new ItemSAO(this, 0, apple_pos, "CraftItem apple 1");
|
||||
addActiveObject(obj);
|
||||
}else if ((n.envticks > 600 || (n.envticks > 100 && season == ENV_SEASON_WINTER)) && active_object_count_wider < 10) {
|
||||
InventoryItem *item = InventoryItem::create(CONTENT_CRAFTITEM_APPLE,1,0,0);
|
||||
dropToParcel(p,item);
|
||||
}else if (n.envticks > 600 || (n.envticks > 100 && season == ENV_SEASON_WINTER)) {
|
||||
n.setContent(CONTENT_APPLE_LEAVES);
|
||||
m_map->addNodeWithEvent(p,n);
|
||||
v3f rot_pos = intToFloat(p, BS);
|
||||
rot_pos += v3f(myrand_range(-1500,1500)*1.0/1000, 0, myrand_range(-1500,1500)*1.0/1000);
|
||||
ServerActiveObject *obj = new ItemSAO(this, 0, rot_pos, "CraftItem mush 1");
|
||||
addActiveObject(obj);
|
||||
InventoryItem *item = InventoryItem::create(CONTENT_CRAFTITEM_MUSH,1,0,0);
|
||||
dropToParcel(p,item);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -387,6 +387,9 @@ public:
|
|||
|
||||
void setPostStepNodeSwap(v3s16 pos, MapNode n) {m_poststep_nodeswaps[pos] = n;}
|
||||
|
||||
bool getCollidedPosition(v3s16 pos, v3s16 dir, v3s16 *result);
|
||||
bool dropToParcel(v3s16 pos, InventoryItem *item);
|
||||
|
||||
private:
|
||||
|
||||
/*
|
||||
|
|
|
@ -178,16 +178,6 @@ std::string InventoryItem::getItemString() {
|
|||
return os.str();
|
||||
}
|
||||
|
||||
ServerActiveObject* InventoryItem::createSAO(ServerEnvironment *env, u16 id, v3f pos)
|
||||
{
|
||||
/*
|
||||
Create an ItemSAO
|
||||
*/
|
||||
// Create object
|
||||
ServerActiveObject *obj = new ItemSAO(env, 0, pos, getItemString());
|
||||
return obj;
|
||||
}
|
||||
|
||||
/*
|
||||
MaterialItem
|
||||
*/
|
||||
|
@ -414,7 +404,7 @@ ServerActiveObject* CraftItem::createSAO(ServerEnvironment *env, u16 id, v3f pos
|
|||
return obj;
|
||||
}
|
||||
// Default
|
||||
return InventoryItem::createSAO(env, id, pos);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
u16 CraftItem::getDropCount() const
|
||||
|
@ -620,7 +610,7 @@ ServerActiveObject* ToolItem::createSAO(ServerEnvironment *env, u16 id, v3f pos)
|
|||
return obj;
|
||||
}
|
||||
// Default
|
||||
return InventoryItem::createSAO(env, id, pos);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -81,7 +81,7 @@ public:
|
|||
// Returns the string used for inventory
|
||||
virtual std::string getItemString();
|
||||
// Creates an object from the item, to be placed in the world.
|
||||
virtual ServerActiveObject* createSAO(ServerEnvironment *env, u16 id, v3f pos);
|
||||
virtual ServerActiveObject* createSAO(ServerEnvironment *env, u16 id, v3f pos) {return NULL;}
|
||||
// Gets amount of items that dropping one SAO will decrement
|
||||
virtual u16 getDropCount() const { return getCount(); }
|
||||
|
||||
|
|
|
@ -424,6 +424,11 @@ struct ContentFeatures
|
|||
// if false then player gets as much as possible, rest stays in undug node
|
||||
bool ondig_gives_inventory_all_or_none;
|
||||
|
||||
// if dropped on dirt, place this instead of inserting in a parcel
|
||||
content_t place_on_drop;
|
||||
// if a place_on_drop is nearby, place this instead
|
||||
content_t place_on_drop_alternate;
|
||||
|
||||
// when energised, replace with this node
|
||||
content_t powered_node;
|
||||
// when unenergised, replace with this node
|
||||
|
@ -569,6 +574,8 @@ struct ContentFeatures
|
|||
onact_also_affects = v3s16(0,0,0);
|
||||
ondig_gives_inventory = false;
|
||||
ondig_gives_inventory_all_or_none = false;
|
||||
place_on_drop = CONTENT_IGNORE;
|
||||
place_on_drop_alternate = CONTENT_IGNORE;
|
||||
powered_node = CONTENT_IGNORE;
|
||||
unpowered_node = CONTENT_IGNORE;
|
||||
cook_result = "";
|
||||
|
|
145
src/server.cpp
145
src/server.cpp
|
@ -3974,9 +3974,18 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
|
|||
ServerActiveObject *obj = wielditem->createSAO(&m_env, 0, pos);
|
||||
|
||||
if (obj == NULL) {
|
||||
infostream<<"WARNING: item resulted in NULL object, "
|
||||
<<"not placing onto map"
|
||||
<<std::endl;
|
||||
InventoryItem *nitem;
|
||||
if (g_settings->getBool("infinite_inventory") == false) {
|
||||
// Delete the right amount of items from the slot
|
||||
InventoryList *ilist = player->inventory.getList("main");
|
||||
nitem = ilist->changeItem(item_i,NULL);
|
||||
// Send inventory
|
||||
UpdateCrafting(peer_id);
|
||||
SendInventory(peer_id);
|
||||
}else{
|
||||
nitem = wielditem->clone();
|
||||
}
|
||||
m_env.dropToParcel(p_over,nitem);
|
||||
}else{
|
||||
actionstream<<player->getName()<<" places "<<item->getName()
|
||||
<<" at "<<PP(p_over)<<std::endl;
|
||||
|
@ -4090,9 +4099,18 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
|
|||
}
|
||||
|
||||
if (obj == NULL) {
|
||||
infostream<<"WARNING: item resulted in NULL object, "
|
||||
<<"not placing onto map"
|
||||
<<std::endl;
|
||||
InventoryItem *nitem;
|
||||
if (g_settings->getBool("infinite_inventory") == false) {
|
||||
// Delete the right amount of items from the slot
|
||||
InventoryList *ilist = player->inventory.getList("main");
|
||||
nitem = ilist->changeItem(item_i,NULL);
|
||||
// Send inventory
|
||||
UpdateCrafting(peer_id);
|
||||
SendInventory(peer_id);
|
||||
}else{
|
||||
nitem = wielditem->clone();
|
||||
}
|
||||
m_env.dropToParcel(p_over,nitem);
|
||||
}else{
|
||||
actionstream<<player->getName()<<" places "<<item->getName()
|
||||
<<" at "<<PP(p_over)<<std::endl;
|
||||
|
@ -4378,19 +4396,21 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
|
|||
) {
|
||||
InventoryList *list = player->inventory.getList("discard");
|
||||
InventoryItem *item = list->getItem(0);
|
||||
if (g_settings->getBool("droppable_inventory")) {
|
||||
v3f pos = player->getPosition();
|
||||
pos.Y += BS;
|
||||
v3f dir = v3f(0,0,BS);
|
||||
dir.rotateXZBy(player->getYaw());
|
||||
pos += dir;
|
||||
ServerActiveObject *obj = item->createSAO(&m_env,0,pos);
|
||||
if (obj)
|
||||
m_env.addActiveObject(obj);
|
||||
}
|
||||
if (g_settings->getBool("infinite_inventory") == false) {
|
||||
list->deleteItem(0);
|
||||
SendInventory(player->peer_id);
|
||||
if (item) {
|
||||
if (g_settings->getBool("droppable_inventory")) {
|
||||
v3f pos = player->getPosition();
|
||||
pos.Y += BS;
|
||||
v3f dir = v3f(0,0,BS);
|
||||
dir.rotateXZBy(player->getYaw());
|
||||
pos += dir;
|
||||
v3s16 pp = floatToInt(pos,BS);
|
||||
item = item->clone();
|
||||
m_env.dropToParcel(pp,item);
|
||||
}
|
||||
if (g_settings->getBool("infinite_inventory") == false) {
|
||||
list->deleteItem(0);
|
||||
SendInventory(player->peer_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -5530,88 +5550,17 @@ void Server::HandlePlayerHP(Player *player, s16 damage, s16 suffocate, s16 hunge
|
|||
player->wet = 0;
|
||||
player->blood = 0;
|
||||
|
||||
//TODO: Throw items around
|
||||
// Throw items around
|
||||
if (g_settings->getBool("death_drops_inv")) {
|
||||
v3s16 bottompos = floatToInt(player->getPosition() + v3f(0,-BS/4,0), BS);
|
||||
v3s16 p = bottompos + v3s16(0,1,0);
|
||||
MapNode in_n = m_env.getMap().getNodeNoEx(p);
|
||||
v3s16 droppos = p;
|
||||
bool can_drop = false;
|
||||
// if they're standing in an air-like node, drop inventory to a parcel
|
||||
// otherwise they just lose it
|
||||
v3s16 pp;
|
||||
if (in_n.getContent() == CONTENT_PARCEL) {
|
||||
can_drop = true;
|
||||
}else if (m_env.searchNear(p,v3s16(3,3,3),CONTENT_PARCEL,&pp)) {
|
||||
droppos = pp;
|
||||
can_drop = true;
|
||||
}else if (in_n.getContent() != CONTENT_LAVASOURCE && content_features(in_n.getContent()).buildable_to) {
|
||||
while (!can_drop && p.Y > -30000) {
|
||||
MapNode nn = m_env.getMap().getNodeNoEx(p+v3s16(0,-1,0));
|
||||
if (nn.getContent() == CONTENT_PARCEL) {
|
||||
droppos = p+v3s16(0,-1,0);
|
||||
can_drop = true;
|
||||
}else if (nn.getContent() == CONTENT_LAVASOURCE) {
|
||||
break;
|
||||
}else if (!content_features(nn.getContent()).buildable_to) {
|
||||
droppos = p;
|
||||
can_drop = true;
|
||||
break;
|
||||
}
|
||||
p.Y--;
|
||||
}
|
||||
}
|
||||
|
||||
if (can_drop) {
|
||||
MapNode nn = m_env.getMap().getNodeNoEx(droppos);
|
||||
if (nn.getContent() != CONTENT_PARCEL) {
|
||||
v3s16 pp;
|
||||
if (m_env.searchNear(droppos,v3s16(3,3,3),CONTENT_PARCEL,&pp)) {
|
||||
droppos = pp;
|
||||
nn = m_env.getMap().getNodeNoEx(droppos);
|
||||
}else{
|
||||
nn.setContent(CONTENT_PARCEL);
|
||||
core::list<u16> far_players;
|
||||
sendAddNode(droppos, nn, 0, &far_players, 30);
|
||||
|
||||
/*
|
||||
Add node.
|
||||
|
||||
This takes some time so it is done after the quick stuff
|
||||
*/
|
||||
core::map<v3s16, MapBlock*> modified_blocks;
|
||||
{
|
||||
MapEditEventIgnorer ign(&m_ignore_map_edit_events);
|
||||
|
||||
std::string p_name(player->getName());
|
||||
m_env.getMap().addNodeAndUpdate(droppos, nn, modified_blocks, p_name);
|
||||
}
|
||||
/*
|
||||
Set blocks not sent to far players
|
||||
*/
|
||||
for (core::list<u16>::Iterator i = far_players.begin(); i != far_players.end(); i++) {
|
||||
u16 peer_id = *i;
|
||||
RemoteClient *client = getClient(peer_id);
|
||||
if (client==NULL)
|
||||
continue;
|
||||
client->SetBlocksNotSent(modified_blocks);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
NodeMetadata *meta = m_env.getMap().getNodeMetadata(droppos);
|
||||
if (meta) {
|
||||
Inventory *inv = meta->getInventory();
|
||||
if (inv) {
|
||||
InventoryList *pl = inv->getList("0");
|
||||
InventoryList *il = player->inventory.getList("main");
|
||||
if (pl && il) {
|
||||
for (u32 i=0; i<32; i++) {
|
||||
InventoryItem *item = il->takeItem(i,99);
|
||||
if (item)
|
||||
pl->addItem(item);
|
||||
}
|
||||
}
|
||||
{
|
||||
InventoryList *il = player->inventory.getList("main");
|
||||
if (il) {
|
||||
for (u32 i=0; i<32; i++) {
|
||||
InventoryItem *item = il->changeItem(i,NULL);
|
||||
if (item)
|
||||
m_env.dropToParcel(p,item);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -53,21 +53,6 @@ ServerActiveObject* ServerActiveObject::create(u8 type,
|
|||
core::map<u16, Factory>::Node *n;
|
||||
n = m_types.find(type);
|
||||
if (n == NULL) {
|
||||
// convert old creatures to new
|
||||
switch (type) {
|
||||
case ACTIVEOBJECT_TYPE_RAT:
|
||||
return new MobSAO(env,id,pos,CONTENT_MOB_RAT);
|
||||
break;
|
||||
case ACTIVEOBJECT_TYPE_OERKKI1:
|
||||
return new MobSAO(env,id,pos,CONTENT_MOB_OERKKI);
|
||||
break;
|
||||
case ACTIVEOBJECT_TYPE_FIREFLY:
|
||||
return new MobSAO(env,id,pos,CONTENT_MOB_FIREFLY);
|
||||
break;
|
||||
case ACTIVEOBJECT_TYPE_MOBV2:
|
||||
return new MobSAO(env,id,pos,CONTENT_MOB_DUNGEON_MASTER);
|
||||
break;
|
||||
}
|
||||
// If factory is not found, just return.
|
||||
dstream<<"WARNING: ServerActiveObject: No factory for type="
|
||||
<<type<<std::endl;
|
||||
|
|
Loading…
Reference in New Issue