lose inventory on death in survival mode

This commit is contained in:
darkrose 2015-08-29 18:15:44 +10:00
parent 8e913f592c
commit 390ccbd88f
6 changed files with 115 additions and 4 deletions

View File

@ -2107,6 +2107,7 @@ void content_mapnode_special(bool repeat)
f->dug_item = std::string("MaterialItem2 ")+itos(i)+" 1";
f->solidness = 0; // drawn separately, makes no faces
f->air_equivalent = true; // grass grows underneath
f->borderstone_diggable = true;
content_nodebox_parcel(f);
f->setInventoryTextureNodeBox(i,"parcel_top.png", "parcel.png", "parcel.png");
f->type = CMT_DIRT;

View File

@ -179,6 +179,7 @@ void set_creative_defaults(Settings *settings)
settings->setDefault("enable_hunger", "false");
settings->setDefault("max_mob_level", "passive");
settings->setDefault("initial_inventory", "false");
settings->setDefault("lose_inv_on_death", "false");
settings->setDefault("tool_wear","false");
}
@ -191,6 +192,7 @@ void set_adventure_defaults(Settings *settings)
settings->setDefault("enable_hunger", "false");
settings->setDefault("max_mob_level", "aggressive");
settings->setDefault("initial_inventory", "true");
settings->setDefault("lose_inv_on_death", "false");
settings->setDefault("tool_wear","true");
}
@ -203,6 +205,7 @@ void set_survival_defaults(Settings *settings)
settings->setDefault("enable_hunger", "true");
settings->setDefault("max_mob_level", "destructive");
settings->setDefault("initial_inventory", "false");
settings->setDefault("lose_inv_on_death", "true");
settings->setDefault("tool_wear","true");
}

View File

@ -363,6 +363,8 @@ struct ContentFeatures
bool fertilizer_affects;
// when dug with a shovel near water, turns to farm dirt
bool farm_ploughable;
// if true, this node can be dug even in a borderstone protected area
bool borderstone_diggable;
// Inventory item string as which the node appears in inventory when dug.
// Mineral overrides this.
@ -531,6 +533,7 @@ struct ContentFeatures
destructive_mob_safe = false;
fertilizer_affects = false;
farm_ploughable = false;
borderstone_diggable = false;
dug_item = "";
extra_dug_item = "";
extra_dug_item_rarity = 2;

View File

@ -81,9 +81,24 @@ void Player::wieldItem(u16 item)
m_selected_item = item;
}
void Player::resetInventory()
void Player::resetInventory(bool include_clothes)
{
inventory.clear();
if (include_clothes) {
inventory.clear();
}else{
InventoryList *l = inventory.getList("main");
if (l)
l->clearItems();
l = inventory.getList("discard");
if (l)
l->clearItems();
l = inventory.getList("craft");
if (l)
l->clearItems();
l = inventory.getList("craftresult");
if (l)
l->clearItems();
}
checkInventory();
}

View File

@ -65,7 +65,7 @@ public:
Player();
virtual ~Player();
void resetInventory();
void resetInventory(bool include_clothes = true);
void checkInventory();
virtual void move(f32 dtime, Map &map, f32 pos_max_d) = 0;

View File

@ -3085,7 +3085,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
<<std::endl;
cannot_remove_node = true;
// check for borderstone
}else if (borderstone_locked) {
}else if (borderstone_locked && !selected_node_features.borderstone_diggable) {
infostream<<"Player "<<player->getName()<<" cannot remove node: borderstone protected"<<std::endl;
cannot_remove_node = true;
// check for locked items and borderstone
@ -5515,6 +5515,95 @@ void Server::HandlePlayerHP(Player *player, s16 damage, s16 suffocate, s16 hunge
player->hp = 0;
//TODO: Throw items around
if (g_settings->getBool("lose_inv_on_death")) {
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);
}
}
}
}
}
player->resetInventory(false);
UpdateCrafting(player->peer_id);
SendInventory(player->peer_id);
}
// Handle players that are not connected
if (player->peer_id == PEER_ID_INEXISTENT) {