added locking chests - clean patch
authordarkrose <lisa@ltmnet.com>
Thu, 22 Sep 2011 09:11:48 +0000 (19:11 +1000)
committerdarkrose <lisa@ltmnet.com>
Thu, 22 Sep 2011 09:11:48 +0000 (19:11 +1000)
doc/mapformat.txt
src/client.cpp
src/content_craft.cpp
src/content_mapnode.cpp
src/content_mapnode.h
src/content_nodemeta.cpp
src/content_nodemeta.h
src/map.cpp
src/map.h
src/server.cpp

index a0241804e40764f574ce39d8779eea29a35e307a..206f5f350e4e125fb77949ba508a49adf8788d23 100644 (file)
@@ -85,5 +85,10 @@ Furnace metadata:
 Chest metadata:
   TBD
 
+Locking Chest metadata:
+  u16 string_len
+  u8[string_len] string
+  TBD
+
 // END
 
index a5ed6f61bf204807399b9e342d7f330bf83aa754..2e3984bae543f638fee950cf8844df1e4cd1a7df 100644 (file)
@@ -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)
        {}
index 8e8b17a9b08acda44ef5a949f2590bb6926be1fa..866c1e5328e07bbc02eab363f40aefa6c3f43f5d 100644 (file)
@@ -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];
index 09a84156adada5ad2c36b32d3c8548848a840d4c..38c5099e49a20e760d4c6356815d9bf7168bf902 100644 (file)
@@ -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;
index 35dcc20ec5278944db341c731c3ebe9729dcc399..366c9b1a08199f83a88df2ba36a8b55a9e2898c1 100644 (file)
@@ -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
 
index 1552c8e1524ace63957af47df30d0fdc9e06f0a7..e79ff6d54c14762772542612f403f8588cdea34b 100644 (file)
@@ -117,6 +117,70 @@ std::string ChestNodeMetadata::getInventoryDrawSpecString()
                "list[current_player;main;0,5;8,4;]";
 }
 
+/*
+       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
 */
index 50decd91081782242808797e4fb42041bbc37e66..af3374124b79f39784804bcaae7e250dbaf6e95d 100644 (file)
@@ -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:
index 7de79c75d8f4a963fad21443c6e19f15e5ef5b24..a8e7235cfdde19d994f86d39b5f4aefc2cb96e6c 100644 (file)
@@ -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
index e0b67eb6e9aa4baa4dfaac901edb0a0fd0bb09eb..6248a56657d0845d35a5fd8fc282f06b9f7a87ef 100644 (file)
--- 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);
 
index 14d8942cb0cf6a4a4b5091b8c70923ae207e248a..689a2b538198d0168f46b814ffdb388bb1f21cf6 100644 (file)
@@ -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)