aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordarkrose <lisa@ltmnet.com>2011-09-22 19:11:48 +1000
committerdarkrose <lisa@ltmnet.com>2011-09-22 19:11:48 +1000
commit582e450bad08006dff141216351b81d3eb9270b7 (patch)
tree0c76a61f5e36f8e4414d220637ff90eacde4eb86
parentae6d83a41ed958b65ec7f6584d7b042ae6a6e51f (diff)
downloadminetest-582e450bad08006dff141216351b81d3eb9270b7.tar.gz
minetest-582e450bad08006dff141216351b81d3eb9270b7.tar.bz2
minetest-582e450bad08006dff141216351b81d3eb9270b7.zip
added locking chests - clean patch
-rw-r--r--doc/mapformat.txt5
-rw-r--r--src/client.cpp3
-rw-r--r--src/content_craft.cpp18
-rw-r--r--src/content_mapnode.cpp14
-rw-r--r--src/content_mapnode.h1
-rw-r--r--src/content_nodemeta.cpp64
-rw-r--r--src/content_nodemeta.h23
-rw-r--r--src/map.cpp19
-rw-r--r--src/map.h2
-rw-r--r--src/server.cpp42
10 files changed, 186 insertions, 5 deletions
diff --git a/doc/mapformat.txt b/doc/mapformat.txt
index a0241804e..206f5f350 100644
--- a/doc/mapformat.txt
+++ b/doc/mapformat.txt
@@ -85,5 +85,10 @@ Furnace metadata:
Chest metadata:
TBD
+Locking Chest metadata:
+ u16 string_len
+ u8[string_len] string
+ TBD
+
// END
diff --git a/src/client.cpp b/src/client.cpp
index a5ed6f61b..2e3984bae 100644
--- a/src/client.cpp
+++ b/src/client.cpp
@@ -1963,7 +1963,8 @@ void Client::addNode(v3s16 p, MapNode n)
try
{
//TimeTaker timer3("Client::addNode(): addNodeAndUpdate");
- m_env.getMap().addNodeAndUpdate(p, n, modified_blocks);
+ std::string st = std::string("");
+ m_env.getMap().addNodeAndUpdate(p, n, modified_blocks, st);
}
catch(InvalidPositionException &e)
{}
diff --git a/src/content_craft.cpp b/src/content_craft.cpp
index 8e8b17a9b..866c1e532 100644
--- a/src/content_craft.cpp
+++ b/src/content_craft.cpp
@@ -297,6 +297,24 @@ InventoryItem *craft_get_result(InventoryItem **items)
}
}
+ // Locking Chest
+ {
+ ItemSpec specs[9];
+ specs[0] = ItemSpec(ITEM_MATERIAL, CONTENT_WOOD);
+ specs[1] = ItemSpec(ITEM_MATERIAL, CONTENT_WOOD);
+ specs[2] = ItemSpec(ITEM_MATERIAL, CONTENT_WOOD);
+ specs[3] = ItemSpec(ITEM_MATERIAL, CONTENT_WOOD);
+ specs[4] = ItemSpec(ITEM_CRAFT, "steel_ingot");
+ specs[5] = ItemSpec(ITEM_MATERIAL, CONTENT_WOOD);
+ specs[6] = ItemSpec(ITEM_MATERIAL, CONTENT_WOOD);
+ specs[7] = ItemSpec(ITEM_MATERIAL, CONTENT_WOOD);
+ specs[8] = ItemSpec(ITEM_MATERIAL, CONTENT_WOOD);
+ if(checkItemCombination(items, specs))
+ {
+ return new MaterialItem(CONTENT_LOCKABLE_CHEST, 1);
+ }
+ }
+
// Furnace
{
ItemSpec specs[9];
diff --git a/src/content_mapnode.cpp b/src/content_mapnode.cpp
index 09a84156a..38c5099e4 100644
--- a/src/content_mapnode.cpp
+++ b/src/content_mapnode.cpp
@@ -573,6 +573,20 @@ void content_mapnode_init()
f->initial_metadata = new ChestNodeMetadata();
setWoodLikeDiggingProperties(f->digging_properties, 1.0);
+ i = CONTENT_LOCKABLE_CHEST;
+ f = &content_features(i);
+ f->param_type = CPT_FACEDIR_SIMPLE;
+ f->setAllTextures("chest_side.png");
+ f->setTexture(0, "chest_top.png");
+ f->setTexture(1, "chest_top.png");
+ f->setTexture(5, "chest_lock.png"); // Z-
+ f->setInventoryTexture("chest_lock.png");
+ //f->setInventoryTextureCube("chest_top.png", "chest_side.png", "chest_side.png");
+ f->dug_item = std::string("MaterialItem2 ")+itos(i)+" 1";
+ if(f->initial_metadata == NULL)
+ f->initial_metadata = new LockingChestNodeMetadata();
+ setWoodLikeDiggingProperties(f->digging_properties, 1.0);
+
i = CONTENT_FURNACE;
f = &content_features(i);
f->param_type = CPT_FACEDIR_SIMPLE;
diff --git a/src/content_mapnode.h b/src/content_mapnode.h
index 35dcc20ec..366c9b1a0 100644
--- a/src/content_mapnode.h
+++ b/src/content_mapnode.h
@@ -48,6 +48,7 @@ MapNode mapnode_translate_to_internal(MapNode n_from, u8 version);
#define CONTENT_SIGN_WALL 14
#define CONTENT_CHEST 15
#define CONTENT_FURNACE 16
+#define CONTENT_LOCKABLE_CHEST 17
#define CONTENT_FENCE 21
diff --git a/src/content_nodemeta.cpp b/src/content_nodemeta.cpp
index 1552c8e15..e79ff6d54 100644
--- a/src/content_nodemeta.cpp
+++ b/src/content_nodemeta.cpp
@@ -118,6 +118,70 @@ std::string ChestNodeMetadata::getInventoryDrawSpecString()
}
/*
+ LockingChestNodeMetadata
+*/
+
+// Prototype
+LockingChestNodeMetadata proto_LockingChestNodeMetadata;
+
+LockingChestNodeMetadata::LockingChestNodeMetadata()
+{
+ NodeMetadata::registerType(typeId(), create);
+
+ m_inventory = new Inventory();
+ m_inventory->addList("0", 8*4);
+}
+LockingChestNodeMetadata::~LockingChestNodeMetadata()
+{
+ delete m_inventory;
+}
+u16 LockingChestNodeMetadata::typeId() const
+{
+ return CONTENT_LOCKABLE_CHEST;
+}
+NodeMetadata* LockingChestNodeMetadata::create(std::istream &is)
+{
+ LockingChestNodeMetadata *d = new LockingChestNodeMetadata();
+ d->setOwner(deSerializeString(is));
+ d->m_inventory->deSerialize(is);
+ return d;
+}
+NodeMetadata* LockingChestNodeMetadata::clone()
+{
+ LockingChestNodeMetadata *d = new LockingChestNodeMetadata();
+ *d->m_inventory = *m_inventory;
+ return d;
+}
+void LockingChestNodeMetadata::serializeBody(std::ostream &os)
+{
+ os<<serializeString(m_text);
+ m_inventory->serialize(os);
+}
+std::string LockingChestNodeMetadata::infoText()
+{
+ return "Locking Chest";
+}
+bool LockingChestNodeMetadata::nodeRemovalDisabled()
+{
+ /*
+ Disable removal if chest contains something
+ */
+ InventoryList *list = m_inventory->getList("0");
+ if(list == NULL)
+ return false;
+ if(list->getUsedSlots() == 0)
+ return false;
+ return true;
+}
+std::string LockingChestNodeMetadata::getInventoryDrawSpecString()
+{
+ return
+ "invsize[8,9;]"
+ "list[current_name;0;0,0;8,4;]"
+ "list[current_player;main;0,5;8,4;]";
+}
+
+/*
FurnaceNodeMetadata
*/
diff --git a/src/content_nodemeta.h b/src/content_nodemeta.h
index 50decd910..af3374124 100644
--- a/src/content_nodemeta.h
+++ b/src/content_nodemeta.h
@@ -62,6 +62,29 @@ private:
Inventory *m_inventory;
};
+class LockingChestNodeMetadata : public NodeMetadata
+{
+public:
+ LockingChestNodeMetadata();
+ ~LockingChestNodeMetadata();
+
+ virtual u16 typeId() const;
+ static NodeMetadata* create(std::istream &is);
+ virtual NodeMetadata* clone();
+ virtual void serializeBody(std::ostream &os);
+ virtual std::string infoText();
+ virtual Inventory* getInventory() {return m_inventory;}
+ virtual bool nodeRemovalDisabled();
+ virtual std::string getInventoryDrawSpecString();
+
+ std::string getOwner(){ return m_text; }
+ void setOwner(std::string t){ m_text = t; }
+
+private:
+ Inventory *m_inventory;
+ std::string m_text;
+};
+
class FurnaceNodeMetadata : public NodeMetadata
{
public:
diff --git a/src/map.cpp b/src/map.cpp
index 7de79c75d..a8e7235cf 100644
--- a/src/map.cpp
+++ b/src/map.cpp
@@ -28,6 +28,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "porting.h"
#include "mapgen.h"
#include "nodemetadata.h"
+#include "content_nodemeta.h"
+#include "content_mapnode.h"
/*
SQLite format specification:
@@ -890,7 +892,7 @@ void Map::updateLighting(core::map<v3s16, MapBlock*> & a_blocks,
/*
*/
void Map::addNodeAndUpdate(v3s16 p, MapNode n,
- core::map<v3s16, MapBlock*> &modified_blocks)
+ core::map<v3s16, MapBlock*> &modified_blocks, std::string &player_name)
{
/*PrintInfo(m_dout);
m_dout<<DTIME<<"Map::addNodeAndUpdate(): p=("
@@ -1014,8 +1016,20 @@ void Map::addNodeAndUpdate(v3s16 p, MapNode n,
if(meta_proto)
{
NodeMetadata *meta = meta_proto->clone();
+ /* lockable chest, insert the owner's name */
+ if (meta->typeId() == CONTENT_LOCKABLE_CHEST)
+ {
+ LockingChestNodeMetadata *lcm = (LockingChestNodeMetadata*)meta;
+ lcm->setOwner(player_name);
+ }
setNodeMetadata(p, meta);
}
+ else if (n.getContent() == CONTENT_LOCKABLE_CHEST)
+ {
+ LockingChestNodeMetadata *lcm = new LockingChestNodeMetadata();
+ lcm->setOwner(player_name);
+ setNodeMetadata(p, (NodeMetadata*)lcm);
+ }
/*
If node is under sunlight and doesn't let sunlight through,
@@ -1290,7 +1304,8 @@ bool Map::addNodeWithEvent(v3s16 p, MapNode n)
bool succeeded = true;
try{
core::map<v3s16, MapBlock*> modified_blocks;
- addNodeAndUpdate(p, n, modified_blocks);
+ std::string st = std::string("");
+ addNodeAndUpdate(p, n, modified_blocks, st);
// Copy modified_blocks to event
for(core::map<v3s16, MapBlock*>::Iterator
diff --git a/src/map.h b/src/map.h
index e0b67eb6e..6248a5665 100644
--- a/src/map.h
+++ b/src/map.h
@@ -205,7 +205,7 @@ public:
These handle lighting but not faces.
*/
void addNodeAndUpdate(v3s16 p, MapNode n,
- core::map<v3s16, MapBlock*> &modified_blocks);
+ core::map<v3s16, MapBlock*> &modified_blocks, std::string &player_name);
void removeNodeAndUpdate(v3s16 p,
core::map<v3s16, MapBlock*> &modified_blocks);
diff --git a/src/server.cpp b/src/server.cpp
index 14d8942cb..689a2b538 100644
--- a/src/server.cpp
+++ b/src/server.cpp
@@ -2873,7 +2873,8 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
{
MapEditEventIgnorer ign(&m_ignore_map_edit_events);
- m_env.getMap().addNodeAndUpdate(p_over, n, modified_blocks);
+ std::string p_name = std::string(player->getName());
+ m_env.getMap().addNodeAndUpdate(p_over, n, modified_blocks, p_name);
}
/*
Set blocks not sent to far players
@@ -3200,7 +3201,46 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
}
// Disallow moving items if not allowed to build
else if((getPlayerPrivs(player) & PRIV_BUILD) == 0)
+ {
return;
+ }
+ // if it's a locking chest, only allow the owner or server admins to move items
+ else if (ma->from_inv != "current_player" && (getPlayerPrivs(player) & PRIV_SERVER) == 0)
+ {
+ Strfnd fn(ma->from_inv);
+ std::string id0 = fn.next(":");
+ if(id0 == "nodemeta")
+ {
+ v3s16 p;
+ p.X = stoi(fn.next(","));
+ p.Y = stoi(fn.next(","));
+ p.Z = stoi(fn.next(","));
+ NodeMetadata *meta = m_env.getMap().getNodeMetadata(p);
+ if(meta && meta->typeId() == CONTENT_LOCKABLE_CHEST) {
+ LockingChestNodeMetadata *lcm = (LockingChestNodeMetadata*)meta;
+ if (lcm->getOwner() != player->getName())
+ return;
+ }
+ }
+ }
+ else if (ma->to_inv != "current_player" && (getPlayerPrivs(player) & PRIV_SERVER) == 0)
+ {
+ Strfnd fn(ma->to_inv);
+ std::string id0 = fn.next(":");
+ if(id0 == "nodemeta")
+ {
+ v3s16 p;
+ p.X = stoi(fn.next(","));
+ p.Y = stoi(fn.next(","));
+ p.Z = stoi(fn.next(","));
+ NodeMetadata *meta = m_env.getMap().getNodeMetadata(p);
+ if(meta && meta->typeId() == CONTENT_LOCKABLE_CHEST) {
+ LockingChestNodeMetadata *lcm = (LockingChestNodeMetadata*)meta;
+ if (lcm->getOwner() != player->getName())
+ return;
+ }
+ }
+ }
}
if(disable_action == false)