minecraft-like crafting
authorPerttu Ahola <celeron55@gmail.com>
Fri, 24 Dec 2010 23:54:39 +0000 (01:54 +0200)
committerPerttu Ahola <celeron55@gmail.com>
Fri, 24 Dec 2010 23:54:39 +0000 (01:54 +0200)
13 files changed:
Makefile
data/stick.png [new file with mode: 0644]
data/wood.png [new file with mode: 0644]
src/inventory.h
src/main.cpp
src/mapnode.cpp
src/mapnode.h
src/materials.cpp [new file with mode: 0644]
src/materials.h [new file with mode: 0644]
src/server.cpp
src/servermain.cpp
src/tile.cpp
src/tile.h

index 5dad9433f6c2ebdc0909e620024cdbc18f9ac747..a6e360f3f33a40bad68b6ba4cc8c6bbe52c5193e 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
 # Makefile for Irrlicht Examples\r
 # It's usually sufficient to change just the target name and source file list\r
 # and be sure that CXX is set to a valid compiler\r
-SOURCE_FILES = guiTextInputMenu.cpp guiInventoryMenu.cpp irrlichtwrapper.cpp guiPauseMenu.cpp defaultsettings.cpp mapnode.cpp tile.cpp voxel.cpp mapblockobject.cpp inventory.cpp debug.cpp serialization.cpp light.cpp filesys.cpp connection.cpp environment.cpp client.cpp server.cpp socket.cpp mapblock.cpp mapsector.cpp heightmap.cpp map.cpp player.cpp utility.cpp main.cpp test.cpp\r
+SOURCE_FILES = materials.cpp guiTextInputMenu.cpp guiInventoryMenu.cpp irrlichtwrapper.cpp guiPauseMenu.cpp defaultsettings.cpp mapnode.cpp tile.cpp voxel.cpp mapblockobject.cpp inventory.cpp debug.cpp serialization.cpp light.cpp filesys.cpp connection.cpp environment.cpp client.cpp server.cpp socket.cpp mapblock.cpp mapsector.cpp heightmap.cpp map.cpp player.cpp utility.cpp main.cpp test.cpp\r
 \r
 DEBUG_TARGET = debugtest\r
 DEBUG_SOURCES = $(addprefix src/, $(SOURCE_FILES))\r
@@ -14,7 +14,7 @@ FAST_BUILD_DIR = fastbuild
 FAST_OBJECTS = $(addprefix $(FAST_BUILD_DIR)/, $(SOURCE_FILES:.cpp=.o))\r
 \r
 SERVER_TARGET = server\r
-SERVER_SOURCE_FILES = defaultsettings.cpp mapnode.cpp voxel.cpp mapblockobject.cpp inventory.cpp debug.cpp serialization.cpp light.cpp filesys.cpp connection.cpp environment.cpp server.cpp socket.cpp mapblock.cpp mapsector.cpp heightmap.cpp map.cpp player.cpp utility.cpp servermain.cpp test.cpp\r
+SERVER_SOURCE_FILES = materials.cpp defaultsettings.cpp mapnode.cpp voxel.cpp mapblockobject.cpp inventory.cpp debug.cpp serialization.cpp light.cpp filesys.cpp connection.cpp environment.cpp server.cpp socket.cpp mapblock.cpp mapsector.cpp heightmap.cpp map.cpp player.cpp utility.cpp servermain.cpp test.cpp\r
 SERVER_SOURCES = $(addprefix src/, $(SERVER_SOURCE_FILES))\r
 SERVER_BUILD_DIR = serverbuild\r
 SERVER_OBJECTS = $(addprefix $(SERVER_BUILD_DIR)/, $(SERVER_SOURCE_FILES:.cpp=.o))\r
diff --git a/data/stick.png b/data/stick.png
new file mode 100644 (file)
index 0000000..7a4663c
Binary files /dev/null and b/data/stick.png differ
diff --git a/data/wood.png b/data/wood.png
new file mode 100644 (file)
index 0000000..57c1d7c
Binary files /dev/null and b/data/wood.png differ
index 13bd27d8bb42e6bf257b42e508c3c46ab336dbaf..ff0086102cfc7bb0d33c06d0fe02dfb3c0ee8527 100644 (file)
@@ -390,6 +390,20 @@ public:
        {
                return m_wear;
        }
+       // Returns true if weared out
+       bool addWear(u16 add)
+       {
+               if(m_wear >= 65535 - add)
+               {
+                       m_wear = 65535;
+                       return true;
+               }
+               else
+               {
+                       m_wear += add;
+                       return false;
+               }
+       }
 private:
        std::string m_toolname;
        u16 m_wear;
index 1a9379e4141692990efd638ca14df342fcb797a1..47dcbf70fb10d86e9796382e632fadfcc45f1fdd 100644 (file)
@@ -167,6 +167,8 @@ TODO: Better handling of objects and mobs
          - Make separate classes for client and server\r
            - Client should not discriminate between blocks, server should\r
            - Make other players utilize the same framework\r
+               - This is also needed for objects that don't get sent to client\r
+                 but are used for triggers etc\r
 \r
 TODO: Draw big amounts of torches better (that is, throw them in the\r
       same meshbuffer (can the meshcollector class be used?))\r
@@ -174,6 +176,9 @@ TODO: Draw big amounts of torches better (that is, throw them in the
 TODO: Check if the usage of Client::isFetchingBlocks() in\r
       updateViewingRange() actually does something\r
 \r
+TODO: Make an option to the server to disable building and digging near\r
+      the starting position\r
+\r
 Doing now:\r
 ======================================================================\r
 \r
@@ -239,6 +244,7 @@ TODO: Transferring of the table from server to client
 #include "guiPauseMenu.h"\r
 #include "guiInventoryMenu.h"\r
 #include "guiTextInputMenu.h"\r
+#include "materials.h"\r
 \r
 IrrlichtWrapper *g_irrlicht;\r
 \r
@@ -1022,6 +1028,22 @@ private:
        s32 m_selection;\r
 };\r
 \r
+// Chat data\r
+struct ChatLine\r
+{\r
+       ChatLine():\r
+               age(0.0)\r
+       {\r
+       }\r
+       ChatLine(const std::wstring &a_text):\r
+               age(0.0),\r
+               text(a_text)\r
+       {\r
+       }\r
+       float age;\r
+       std::wstring text;\r
+};\r
+\r
 int main(int argc, char *argv[])\r
 {\r
        /*\r
@@ -1039,6 +1061,8 @@ int main(int argc, char *argv[])
        debug_stacks_init();\r
 \r
        DSTACK(__FUNCTION_NAME);\r
+       \r
+       initializeMaterialProperties();\r
 \r
        try\r
        {\r
@@ -1541,8 +1565,7 @@ int main(int argc, char *argv[])
                        L"Chat here\nOther line\nOther line\nOther line\nOther line",\r
                        core::rect<s32>(70, 60, 795, 150),\r
                        false, true);\r
-       core::list<std::wstring> chat_lines;\r
-       //chat_lines.push_back(L"Minetest-c55 up and running!");\r
+       core::list<ChatLine> chat_lines;\r
        \r
        /*\r
                Some statistics are collected in these\r
@@ -2102,34 +2125,38 @@ int main(int argc, char *argv[])
                                if(g_input->getLeftState())\r
                                {\r
                                        MapNode n = client.getNode(nodepos);\r
-\r
-                                       // TODO: Get this from some table that is sent by server\r
-                                       float dig_time_complete = 0.5;\r
-                                       if(n.d == CONTENT_STONE || n.d == CONTENT_COALSTONE)\r
+                               \r
+                                       // Get tool name. Default is "" = bare hands\r
+                                       std::string toolname = "";\r
+                                       InventoryList *mlist = local_inventory.getList("main");\r
+                                       if(mlist != NULL)\r
                                        {\r
-                                               dig_time_complete = 10.0;\r
-\r
-                                               InventoryList *mlist = local_inventory.getList("main");\r
-                                               if(mlist != NULL)\r
+                                               InventoryItem *item = mlist->getItem(g_selected_item);\r
+                                               if(item && (std::string)item->getName() == "ToolItem")\r
                                                {\r
-                                                       InventoryItem *item = mlist->getItem(g_selected_item);\r
-                                                       if(item && (std::string)item->getName() == "ToolItem")\r
-                                                       {\r
-                                                               ToolItem *titem = (ToolItem*)item;\r
-                                                               if(titem->getToolName() == "WPick")\r
-                                                               {\r
-                                                                       dig_time_complete = 1.2;\r
-                                                               }\r
-                                                               else if(titem->getToolName() == "STPick")\r
-                                                               {\r
-                                                                       dig_time_complete = 0.6;\r
-                                                               }\r
-                                                       }\r
+                                                       ToolItem *titem = (ToolItem*)item;\r
+                                                       toolname = titem->getToolName();\r
                                                }\r
                                        }\r
-                                       else if(n.d == CONTENT_TORCH)\r
+\r
+                                       // Get digging properties for material and tool\r
+                                       u8 material = n.d;\r
+                                       DiggingProperties prop =\r
+                                                       getDiggingProperties(material, toolname);\r
+                                       \r
+                                       float dig_time_complete = 0.0;\r
+\r
+                                       if(prop.diggable == false)\r
+                                       {\r
+                                               /*dstream<<"Material "<<(int)material\r
+                                                               <<" not diggable with \""\r
+                                                               <<toolname<<"\""<<std::endl;*/\r
+                                               // I guess nobody will wait for this long\r
+                                               dig_time_complete = 10000000.0;\r
+                                       }\r
+                                       else\r
                                        {\r
-                                               dig_time_complete = 0.0;\r
+                                               dig_time_complete = prop.time;\r
                                        }\r
                                        \r
                                        if(dig_time_complete >= 0.001)\r
@@ -2305,14 +2332,14 @@ int main(int argc, char *argv[])
                        Get chat messages from client\r
                */\r
                {\r
-                       // Get messages\r
+                       // Get new messages\r
                        std::wstring message;\r
                        while(client.getChatMessage(message))\r
                        {\r
-                               chat_lines.push_back(message);\r
-                               if(chat_lines.size() > 5)\r
+                               chat_lines.push_back(ChatLine(message));\r
+                               if(chat_lines.size() > 7)\r
                                {\r
-                                       core::list<std::wstring>::Iterator\r
+                                       core::list<ChatLine>::Iterator\r
                                                        i = chat_lines.begin();\r
                                        chat_lines.erase(i);\r
                                }\r
@@ -2320,11 +2347,24 @@ int main(int argc, char *argv[])
                        // Append them to form the whole static text and throw\r
                        // it to the gui element\r
                        std::wstring whole;\r
-                       for(core::list<std::wstring>::Iterator\r
+                       u16 to_be_removed_count = 0;\r
+                       for(core::list<ChatLine>::Iterator\r
                                        i = chat_lines.begin();\r
                                        i != chat_lines.end(); i++)\r
                        {\r
-                               whole += (*i) + L'\n';\r
+                               (*i).age += dtime;\r
+                               if((*i).age > 30.0)\r
+                               {\r
+                                       to_be_removed_count++;\r
+                                       continue;\r
+                               }\r
+                               whole += (*i).text + L'\n';\r
+                       }\r
+                       for(u16 i=0; i<to_be_removed_count; i++)\r
+                       {\r
+                               core::list<ChatLine>::Iterator\r
+                                               i = chat_lines.begin();\r
+                               chat_lines.erase(i);\r
                        }\r
                        chat_guitext->setText(whole.c_str());\r
                        // Update gui element size and position\r
index a8e9f07fc41fb2c313d616efd7d8aded71e28898..3dae653edef9f8460e2a916ad2d6a77a235a3687 100644 (file)
@@ -43,6 +43,7 @@ u16 g_content_tiles[USEFUL_CONTENT_COUNT][6] =
        {TILE_WATER,TILE_WATER,TILE_WATER,TILE_WATER,TILE_WATER,TILE_WATER},
        {TILE_CLOUD,TILE_CLOUD,TILE_CLOUD,TILE_CLOUD,TILE_CLOUD,TILE_CLOUD},
        {TILE_COALSTONE,TILE_COALSTONE,TILE_COALSTONE,TILE_COALSTONE,TILE_COALSTONE,TILE_COALSTONE},
+       {TILE_WOOD,TILE_WOOD,TILE_WOOD,TILE_WOOD,TILE_WOOD,TILE_WOOD},
 };
 
 const char * g_content_inventory_textures[USEFUL_CONTENT_COUNT] =
@@ -59,5 +60,6 @@ const char * g_content_inventory_textures[USEFUL_CONTENT_COUNT] =
        "../data/water.png",
        "../data/cloud.png",
        "../data/coalstone.png",
+       "../data/wood.png",
 };
 
index ad85d88e848a3af0dc9fdf50489425f08c1213c7..659d585b5fc3b1ba959d04c2783b5eb98205a202 100644 (file)
@@ -77,6 +77,7 @@ enum Content
        CONTENT_OCEAN,
        CONTENT_CLOUD,
        CONTENT_COALSTONE,
+       CONTENT_WOOD,
        
        // This is set to the number of the actual values in this enum
        USEFUL_CONTENT_COUNT
@@ -96,6 +97,7 @@ inline bool light_propagates_content(u8 m)
 
 /*
        If true, the material allows lossless sunlight propagation.
+       NOTE: It doesn't seem to go through torches regardlessly of this
 */
 inline bool sunlight_propagates_content(u8 m)
 {
@@ -153,14 +155,12 @@ inline bool content_buildable_to(u8 m)
 */
 inline bool is_ground_content(u8 m)
 {
-       return(
-               m == CONTENT_STONE ||
-               m == CONTENT_GRASS ||
-               m == CONTENT_GRASS_FOOTSTEPS ||
-               m == CONTENT_MESE ||
-               m == CONTENT_MUD ||
-               m == CONTENT_COALSTONE
-       );
+       return (m != CONTENT_WATER
+               && m != CONTENT_TORCH
+               && m != CONTENT_TREE
+               && m != CONTENT_LEAVES
+               && m != CONTENT_OCEAN
+               && m != CONTENT_CLOUD);
 }
 
 inline bool is_mineral(u8 c)
@@ -169,12 +169,18 @@ inline bool is_mineral(u8 c)
                || c == CONTENT_COALSTONE);
 }
 
-/*inline bool content_has_faces(u8 c)
+inline bool liquid_replaces_content(u8 c)
 {
-       return (m != CONTENT_IGNORE
-            && m != CONTENT_AIR
-                && m != CONTENT_TORCH);
-}*/
+       return (c == CONTENT_AIR || c == CONTENT_TORCH);
+}
+
+/*
+       When placing a node, drection info is added to it if this is true
+*/
+inline bool content_directional(u8 c)
+{
+       return (c == CONTENT_TORCH);
+}
 
 /*
        Nodes make a face if contents differ and solidness differs.
@@ -201,19 +207,6 @@ inline u8 face_contents(u8 m1, u8 m2)
                return 2;
 }
 
-inline bool liquid_replaces_content(u8 c)
-{
-       return (c == CONTENT_AIR || c == CONTENT_TORCH);
-}
-
-/*
-       When placing a node, drection info is added to it if this is true
-*/
-inline bool content_directional(u8 c)
-{
-       return (c == CONTENT_TORCH);
-}
-
 /*
        Packs directions like (1,0,0), (1,-1,0)
 */
diff --git a/src/materials.cpp b/src/materials.cpp
new file mode 100644 (file)
index 0000000..5c14195
--- /dev/null
@@ -0,0 +1,75 @@
+#include "materials.h"
+
+#define MATERIAL_PROPERTIES_COUNT 256
+
+// These correspond to the CONTENT_* constants
+MaterialProperties g_material_properties[MATERIAL_PROPERTIES_COUNT];
+
+bool g_material_properties_initialized = false;
+
+void setStoneLikeDiggingProperties(u8 material, float toughness)
+{
+       g_material_properties[material].setDiggingProperties("",
+                       DiggingProperties(true, 15.0*toughness, 0));
+       g_material_properties[material].setDiggingProperties("WPick",
+                       DiggingProperties(true, 2.0*toughness, 65535./20.*toughness));
+       g_material_properties[material].setDiggingProperties("STPick",
+                       DiggingProperties(true, 1.0*toughness, 65535./50.*toughness));
+}
+
+void initializeMaterialProperties()
+{
+       /*
+               Now, the g_material_properties array is already initialized
+               by the constructors to such that no digging is possible.
+
+               Add some digging properties to them.
+       */
+       
+       setStoneLikeDiggingProperties(CONTENT_STONE, 1.0);
+
+       g_material_properties[CONTENT_GRASS].setDiggingProperties("",
+                       DiggingProperties(true, 0.5, 0));
+
+       g_material_properties[CONTENT_TORCH].setDiggingProperties("",
+                       DiggingProperties(true, 0.0, 0));
+
+       g_material_properties[CONTENT_TREE].setDiggingProperties("",
+                       DiggingProperties(true, 1.5, 0));
+
+       g_material_properties[CONTENT_LEAVES].setDiggingProperties("",
+                       DiggingProperties(true, 0.5, 0));
+
+       g_material_properties[CONTENT_GRASS_FOOTSTEPS].setDiggingProperties("",
+                       DiggingProperties(true, 0.5, 0));
+
+       setStoneLikeDiggingProperties(CONTENT_MESE, 0.5);
+
+       g_material_properties[CONTENT_MUD].setDiggingProperties("",
+                       DiggingProperties(true, 0.5, 0));
+
+       setStoneLikeDiggingProperties(CONTENT_COALSTONE, 1.5);
+
+       g_material_properties[CONTENT_WOOD].setDiggingProperties("",
+                       DiggingProperties(true, 1.0, 0));
+
+
+       g_material_properties_initialized = true;
+}
+
+MaterialProperties * getMaterialProperties(u8 material)
+{
+       assert(g_material_properties_initialized);
+       return &g_material_properties[material];
+}
+
+DiggingProperties getDiggingProperties(u8 material, const std::string &tool)
+{
+       MaterialProperties *mprop = getMaterialProperties(material);
+       if(mprop == NULL)
+               // Not diggable
+               return DiggingProperties();
+       
+       return mprop->getDiggingProperties(tool);
+}
+
diff --git a/src/materials.h b/src/materials.h
new file mode 100644 (file)
index 0000000..ae2deac
--- /dev/null
@@ -0,0 +1,98 @@
+/*
+Minetest-c55
+Copyright (C) 2010 celeron55, Perttu Ahola <celeron55@gmail.com>
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along
+with this program; if not, write to the Free Software Foundation, Inc.,
+51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#ifndef MATERIALS_HEADER
+#define MATERIALS_HEADER
+
+/*
+       Material properties
+*/
+
+#include "common_irrlicht.h"
+#include "inventory.h"
+#include <string>
+
+struct DiggingProperties
+{
+       DiggingProperties():
+               diggable(false),
+               time(0.0),
+               wear(0)
+       {
+       }
+       DiggingProperties(bool a_diggable, float a_time, u16 a_wear):
+               diggable(a_diggable),
+               time(a_time),
+               wear(a_wear)
+       {
+       }
+       bool diggable;
+       // Digging time in seconds
+       float time;
+       // Caused wear
+       u16 wear;
+};
+
+class MaterialProperties
+{
+public:
+       MaterialProperties()
+       {
+               dstream<<__FUNCTION_NAME<<std::endl;
+       }
+
+       void setDiggingProperties(const std::string toolname,
+                       const DiggingProperties &prop)
+       {
+               m_digging_properties[toolname] = prop;
+       }
+
+       DiggingProperties getDiggingProperties(const std::string toolname)
+       {
+               core::map<std::string, DiggingProperties>::Node *n;
+               n = m_digging_properties.find(toolname);
+               if(n == NULL)
+               {
+                       // Not diggable by this tool, try to get defaults
+                       n = m_digging_properties.find("");
+                       if(n == NULL)
+                       {
+                               // Not diggable at all
+                               return DiggingProperties();
+                       }
+               }
+               // Return found properties
+               return n->getValue();
+       }
+
+private:
+       // toolname="": default properties (digging by hand)
+       // Key is toolname
+       core::map<std::string, DiggingProperties> m_digging_properties;
+};
+
+void initializeMaterialProperties();
+
+// Material correspond to the CONTENT_* constants
+MaterialProperties * getMaterialProperties(u8 material);
+// For getting the default properties, set tool=""
+DiggingProperties getDiggingProperties(u8 material, const std::string &tool);
+
+#endif
+
index c0af61b989b6d856728f61c9d0ca58d8eb7fde46..e1f7ba7395b1b5795151654225d5de8d4e9e10de 100644 (file)
@@ -30,6 +30,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include "main.h"
 #include "constants.h"
 #include "voxel.h"
+#include "materials.h"
 
 #define BLOCK_EMERGE_FLAG_FROMDISK (1<<0)
 
@@ -1821,9 +1822,47 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
 
                        if(g_settings.getBool("creative_mode") == false)
                        {
-                               // Add to inventory and send inventory
+                               /*
+                                       Wear out tool
+                               */
+                               InventoryList *mlist = player->inventory.getList("main");
+                               if(mlist != NULL)
+                               {
+                                       InventoryItem *item = mlist->getItem(item_i);
+                                       if(item && (std::string)item->getName() == "ToolItem")
+                                       {
+                                               ToolItem *titem = (ToolItem*)item;
+                                               std::string toolname = titem->getToolName();
+
+                                               // Get digging properties for material and tool
+                                               DiggingProperties prop =
+                                                               getDiggingProperties(material, toolname);
+
+                                               if(prop.diggable == false)
+                                               {
+                                                       derr_server<<"Server: WARNING: Player digged"
+                                                                       <<" with impossible material + tool"
+                                                                       <<" combination"<<std::endl;
+                                               }
+                                               
+                                               bool weared_out = titem->addWear(prop.wear);
+
+                                               if(weared_out)
+                                               {
+                                                       mlist->deleteItem(item_i);
+                                               }
+                                       }
+                               }
+
+                               /*
+                                       Add digged item to inventory
+                               */
                                InventoryItem *item = new MaterialItem(material, 1);
                                player->inventory.addItem("main", item);
+
+                               /*
+                                       Send inventory
+                               */
                                SendInventory(player->peer_id);
                        }
 
@@ -2404,138 +2443,6 @@ void Server::peerAdded(con::Peer *peer)
        c.peer_id = peer->id;
        c.timeout = false;
        m_peer_change_queue.push_back(c);
-
-#if 0
-       // NOTE: Connection is already locked when this is called.
-       // NOTE: Environment is already locked when this is called.
-       
-       // Error check
-       core::map<u16, RemoteClient*>::Node *n;
-       n = m_clients.find(peer->id);
-       // The client shouldn't already exist
-       assert(n == NULL);
-
-       // Create client
-       RemoteClient *client = new RemoteClient();
-       client->peer_id = peer->id;
-       m_clients.insert(client->peer_id, client);
-
-       // Create player
-       {
-               Player *player = m_env.getPlayer(peer->id);
-               
-               // The player shouldn't already exist
-               assert(player == NULL);
-
-               player = new ServerRemotePlayer();
-               player->peer_id = peer->id;
-
-               /*
-                       Set player position
-               */
-               
-               // We're going to throw the player to this position
-               //v2s16 nodepos(29990,29990);
-               //v2s16 nodepos(9990,9990);
-               v2s16 nodepos(0,0);
-               v2s16 sectorpos = getNodeSectorPos(nodepos);
-               // Get zero sector (it could have been unloaded to disk)
-               m_env.getMap().emergeSector(sectorpos);
-               // Get ground height at origin
-               f32 groundheight = m_env.getMap().getGroundHeight(nodepos, true);
-               // The sector should have been generated -> groundheight exists
-               assert(groundheight > GROUNDHEIGHT_VALID_MINVALUE);
-               // Don't go underwater
-               if(groundheight < WATER_LEVEL)
-                       groundheight = WATER_LEVEL;
-
-               player->setPosition(intToFloat(v3s16(
-                               nodepos.X,
-                               groundheight + 1,
-                               nodepos.Y
-               )));
-
-               /*
-                       Add player to environment
-               */
-
-               m_env.addPlayer(player);
-
-               /*
-                       Add stuff to inventory
-               */
-               
-               if(g_settings.getBool("creative_mode"))
-               {
-                       // Give a good pick
-                       {
-                               InventoryItem *item = new ToolItem("STPick", 32000);
-                               void* r = player->inventory.addItem("main", item);
-                               assert(r == NULL);
-                       }
-                       // Give all materials
-                       assert(USEFUL_CONTENT_COUNT <= PLAYER_INVENTORY_SIZE);
-                       for(u16 i=0; i<USEFUL_CONTENT_COUNT; i++)
-                       {
-                               // Skip some materials
-                               if(i == CONTENT_OCEAN)
-                                       continue;
-
-                               InventoryItem *item = new MaterialItem(i, 1);
-                               player->inventory.addItem("main", item);
-                       }
-                       // Sign
-                       {
-                               InventoryItem *item = new MapBlockObjectItem("Sign Example text");
-                               void* r = player->inventory.addItem("main", item);
-                               assert(r == NULL);
-                       }
-                       /*// Rat
-                       {
-                               InventoryItem *item = new MapBlockObjectItem("Rat");
-                               bool r = player->inventory.addItem("main", item);
-                               assert(r == true);
-                       }*/
-               }
-               else
-               {
-                       {
-                               InventoryItem *item = new CraftItem("Stick", 4);
-                               void* r = player->inventory.addItem("main", item);
-                               assert(r == NULL);
-                       }
-                       {
-                               InventoryItem *item = new ToolItem("WPick", 32000);
-                               void* r = player->inventory.addItem("main", item);
-                               assert(r == NULL);
-                       }
-                       {
-                               InventoryItem *item = new ToolItem("STPick", 32000);
-                               void* r = player->inventory.addItem("main", item);
-                               assert(r == NULL);
-                       }
-                       /*// Give some lights
-                       {
-                               InventoryItem *item = new MaterialItem(CONTENT_TORCH, 999);
-                               bool r = player->inventory.addItem("main", item);
-                               assert(r == true);
-                       }
-                       // and some signs
-                       for(u16 i=0; i<4; i++)
-                       {
-                               InventoryItem *item = new MapBlockObjectItem("Sign Example text");
-                               bool r = player->inventory.addItem("main", item);
-                               assert(r == true);
-                       }*/
-                       /*// Give some other stuff
-                       {
-                               InventoryItem *item = new MaterialItem(CONTENT_TREE, 999);
-                               bool r = player->inventory.addItem("main", item);
-                               assert(r == true);
-                       }*/
-               }
-       }
-#endif
 }
 
 void Server::deletingPeer(con::Peer *peer, bool timeout)
@@ -2549,46 +2456,6 @@ void Server::deletingPeer(con::Peer *peer, bool timeout)
        c.peer_id = peer->id;
        c.timeout = timeout;
        m_peer_change_queue.push_back(c);
-
-#if 0
-       // NOTE: Connection is already locked when this is called.
-
-       // NOTE: Environment is already locked when this is called.
-       // NOTE: Locking environment cannot be moved here because connection
-       //       is already locked and env has to be locked before
-
-       // Error check
-       core::map<u16, RemoteClient*>::Node *n;
-       n = m_clients.find(peer->id);
-       // The client should exist
-       assert(n != NULL);
-       
-       // Send information about leaving in chat
-       {
-               std::wstring name = L"unknown";
-               Player *player = m_env.getPlayer(peer->id);
-               if(player != NULL)
-                       name = narrow_to_wide(player->getName());
-               
-               std::wstring message;
-               message += L"*** ";
-               message += name;
-               message += L" left game";
-               BroadcastChatMessage(message);
-       }
-
-       // Delete player
-       {
-               m_env.removePlayer(peer->id);
-       }
-       
-       // Delete client
-       delete m_clients[peer->id];
-       m_clients.remove(peer->id);
-
-       // Send player info to all clients
-       SendPlayerInfos();
-#endif
 }
 
 void Server::SendObjectData(float dtime)
@@ -2647,6 +2514,159 @@ void Server::SendPlayerInfos()
        m_con.SendToAll(0, data, true);
 }
 
+enum ItemSpecType
+{
+       ITEM_NONE,
+       ITEM_MATERIAL,
+       ITEM_CRAFT,
+       ITEM_TOOL,
+       ITEM_MBO
+};
+
+struct ItemSpec
+{
+       ItemSpec():
+               type(ITEM_NONE)
+       {
+       }
+       ItemSpec(enum ItemSpecType a_type, std::string a_name):
+               type(a_type),
+               name(a_name),
+               num(65535)
+       {
+       }
+       ItemSpec(enum ItemSpecType a_type, u16 a_num):
+               type(a_type),
+               name(""),
+               num(a_num)
+       {
+       }
+       enum ItemSpecType type;
+       // Only other one of these is used
+       std::string name;
+       u16 num;
+};
+
+/*
+       items: a pointer to an array of 9 pointers to items
+       specs: a pointer to an array of 9 ItemSpecs
+*/
+bool checkItemCombination(InventoryItem **items, ItemSpec *specs)
+{
+       u16 items_min_x = 100;
+       u16 items_max_x = 100;
+       u16 items_min_y = 100;
+       u16 items_max_y = 100;
+       for(u16 y=0; y<3; y++)
+       for(u16 x=0; x<3; x++)
+       {
+               if(items[y*3 + x] == NULL)
+                       continue;
+               if(items_min_x == 100 || x < items_min_x)
+                       items_min_x = x;
+               if(items_min_y == 100 || y < items_min_y)
+                       items_min_y = y;
+               if(items_max_x == 100 || x > items_max_x)
+                       items_max_x = x;
+               if(items_max_y == 100 || y > items_max_y)
+                       items_max_y = y;
+       }
+       // No items at all, just return false
+       if(items_min_x == 100)
+               return false;
+       
+       u16 items_w = items_max_x - items_min_x + 1;
+       u16 items_h = items_max_y - items_min_y + 1;
+
+       u16 specs_min_x = 100;
+       u16 specs_max_x = 100;
+       u16 specs_min_y = 100;
+       u16 specs_max_y = 100;
+       for(u16 y=0; y<3; y++)
+       for(u16 x=0; x<3; x++)
+       {
+               if(specs[y*3 + x].type == ITEM_NONE)
+                       continue;
+               if(specs_min_x == 100 || x < specs_min_x)
+                       specs_min_x = x;
+               if(specs_min_y == 100 || y < specs_min_y)
+                       specs_min_y = y;
+               if(specs_max_x == 100 || x > specs_max_x)
+                       specs_max_x = x;
+               if(specs_max_y == 100 || y > specs_max_y)
+                       specs_max_y = y;
+       }
+       // No specs at all, just return false
+       if(specs_min_x == 100)
+               return false;
+
+       u16 specs_w = specs_max_x - specs_min_x + 1;
+       u16 specs_h = specs_max_y - specs_min_y + 1;
+
+       // Different sizes
+       if(items_w != specs_w || items_h != specs_h)
+               return false;
+
+       for(u16 y=0; y<specs_h; y++)
+       for(u16 x=0; x<specs_w; x++)
+       {
+               u16 items_x = items_min_x + x;
+               u16 items_y = items_min_y + y;
+               u16 specs_x = specs_min_x + x;
+               u16 specs_y = specs_min_y + y;
+               InventoryItem *item = items[items_y * 3 + items_x];
+               ItemSpec &spec = specs[specs_y * 3 + specs_x];
+               
+               if(spec.type == ITEM_NONE)
+               {
+                       // Has to be no item
+                       if(item != NULL)
+                               return false;
+                       continue;
+               }
+               
+               // There should be an item
+               if(item == NULL)
+                       return false;
+
+               std::string itemname = item->getName();
+
+               if(spec.type == ITEM_MATERIAL)
+               {
+                       if(itemname != "MaterialItem")
+                               return false;
+                       MaterialItem *mitem = (MaterialItem*)item;
+                       if(mitem->getMaterial() != spec.num)
+                               return false;
+               }
+               else if(spec.type == ITEM_CRAFT)
+               {
+                       if(itemname != "CraftItem")
+                               return false;
+                       CraftItem *mitem = (CraftItem*)item;
+                       if(mitem->getSubName() != spec.name)
+                               return false;
+               }
+               else if(spec.type == ITEM_TOOL)
+               {
+                       // Not supported yet
+                       assert(0);
+               }
+               else if(spec.type == ITEM_MBO)
+               {
+                       // Not supported yet
+                       assert(0);
+               }
+               else
+               {
+                       // Not supported yet
+                       assert(0);
+               }
+       }
+
+       return true;
+}
+
 void Server::SendInventory(u16 peer_id)
 {
        DSTACK(__FUNCTION_NAME);
@@ -2670,31 +2690,96 @@ void Server::SendInventory(u16 peer_id)
                {
                        items[i] = clist->getItem(i);
                }
+               
+               bool found = false;
+
+               // Wood
+               if(!found)
+               {
+                       ItemSpec specs[9];
+                       specs[0] = ItemSpec(ITEM_MATERIAL, CONTENT_TREE);
+                       if(checkItemCombination(items, specs))
+                       {
+                               rlist->addItem(new MaterialItem(CONTENT_WOOD, 4));
+                               found = true;
+                       }
+               }
+
+               // Stick
+               if(!found)
+               {
+                       ItemSpec specs[9];
+                       specs[0] = ItemSpec(ITEM_MATERIAL, CONTENT_WOOD);
+                       if(checkItemCombination(items, specs))
+                       {
+                               rlist->addItem(new CraftItem("Stick", 4));
+                               found = true;
+                       }
+               }
+
                // Sign
-               if(clist->getUsedSlots() == 1 && items[0])
+               if(!found)
                {
-                       if((std::string)items[0]->getName() == "MaterialItem")
+                       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_MATERIAL, CONTENT_WOOD);
+                       specs[5] = ItemSpec(ITEM_MATERIAL, CONTENT_WOOD);
+                       specs[7] = ItemSpec(ITEM_CRAFT, "Stick");
+                       if(checkItemCombination(items, specs))
                        {
-                               MaterialItem *mitem = (MaterialItem*)items[0];
-                               if(mitem->getMaterial() == CONTENT_TREE)
-                               {
-                                       rlist->addItem(new MapBlockObjectItem("Sign"));
-                               }
+                               rlist->addItem(new MapBlockObjectItem("Sign"));
+                               found = true;
                        }
                }
+
                // Torch
-               if(clist->getUsedSlots() == 2 && items[0] && items[3])
-               {
-                       if(
-                                  (std::string)items[0]->getName() == "MaterialItem"
-                               && ((MaterialItem*)items[0])->getMaterial() == CONTENT_COALSTONE
-                               && (std::string)items[3]->getName() == "MaterialItem"
-                               && ((MaterialItem*)items[3])->getMaterial() == CONTENT_TREE
-                       )
+               if(!found)
+               {
+                       ItemSpec specs[9];
+                       specs[0] = ItemSpec(ITEM_MATERIAL, CONTENT_COALSTONE);
+                       specs[3] = ItemSpec(ITEM_CRAFT, "Stick");
+                       if(checkItemCombination(items, specs))
                        {
                                rlist->addItem(new MaterialItem(CONTENT_TORCH, 4));
+                               found = true;
                        }
                }
+
+               // Wooden pick
+               if(!found)
+               {
+                       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[4] = ItemSpec(ITEM_CRAFT, "Stick");
+                       specs[7] = ItemSpec(ITEM_CRAFT, "Stick");
+                       if(checkItemCombination(items, specs))
+                       {
+                               rlist->addItem(new ToolItem("WPick", 0));
+                               found = true;
+                       }
+               }
+
+               // Stone pick
+               if(!found)
+               {
+                       ItemSpec specs[9];
+                       specs[0] = ItemSpec(ITEM_MATERIAL, CONTENT_STONE);
+                       specs[1] = ItemSpec(ITEM_MATERIAL, CONTENT_STONE);
+                       specs[2] = ItemSpec(ITEM_MATERIAL, CONTENT_STONE);
+                       specs[4] = ItemSpec(ITEM_CRAFT, "Stick");
+                       specs[7] = ItemSpec(ITEM_CRAFT, "Stick");
+                       if(checkItemCombination(items, specs))
+                       {
+                               rlist->addItem(new ToolItem("STPick", 0));
+                               found = true;
+                       }
+               }
+
        }
 
        /*
@@ -2958,6 +3043,16 @@ void Server::handlePeerChange(PeerChange &c)
                        }
                        else
                        {
+                               {
+                                       InventoryItem *item = new MaterialItem(CONTENT_COALSTONE, 6);
+                                       void* r = player->inventory.addItem("main", item);
+                                       assert(r == NULL);
+                               }
+                               {
+                                       InventoryItem *item = new MaterialItem(CONTENT_WOOD, 6);
+                                       void* r = player->inventory.addItem("main", item);
+                                       assert(r == NULL);
+                               }
                                {
                                        InventoryItem *item = new CraftItem("Stick", 4);
                                        void* r = player->inventory.addItem("main", item);
index c2d697cfeef340573a93dfd37880b16f31cd4425..b8bc0dc542691db66a7a97316f997a24ae5e54af 100644 (file)
@@ -123,6 +123,8 @@ int main(int argc, char *argv[])
 
        DSTACK(__FUNCTION_NAME);
 
+       initializeMaterialProperties();
+
        try
        {
        
index 25d9c00d08ef235225759394a9e1aafdcfd19538..a9470dc8e2d4915149f48e99a52ca3a6b15797d2 100644 (file)
@@ -36,6 +36,7 @@ const char * g_tile_texture_paths[TILES_COUNT] =
        "../data/mud_with_grass.png",
        "../data/cloud.png",
        "../data/coalstone.png",
+       "../data/wood.png",
 };
 
 const char * tile_texture_path_get(u32 i)
index 9823160c237842a89942802671bf48c9e362e7fc..c35c27e6457257f5240abd02871a48437b64d2bd 100644 (file)
@@ -40,6 +40,7 @@ enum TileID
        TILE_MUD_WITH_GRASS,
        TILE_CLOUD,
        TILE_COALSTONE,
+       TILE_WOOD,
        
        // Count of tile ids
        TILES_COUNT