summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt2
-rw-r--r--data/apple.pngbin0 -> 203 bytes
-rw-r--r--data/apple_iron.pngbin0 -> 207 bytes
-rw-r--r--data/chest_lock.pngbin0 -> 224 bytes
-rw-r--r--doc/changelog.txt16
-rw-r--r--doc/mapformat.txt5
-rw-r--r--src/CMakeLists.txt8
-rw-r--r--src/client.cpp5
-rw-r--r--src/content_craft.cpp32
-rw-r--r--src/content_inventory.cpp12
-rw-r--r--src/content_mapblock.cpp60
-rw-r--r--src/content_mapnode.cpp26
-rw-r--r--src/content_mapnode.h3
-rw-r--r--src/content_nodemeta.cpp64
-rw-r--r--src/content_nodemeta.h23
-rw-r--r--src/defaultsettings.cpp1
-rw-r--r--src/environment.cpp7
-rw-r--r--src/map.cpp6
-rw-r--r--src/map.h2
-rw-r--r--src/mapgen.cpp26
-rw-r--r--src/nodemetadata.h3
-rw-r--r--src/server.cpp80
-rw-r--r--util/colors.txt23
-rwxr-xr-xutil/minetestmapper.py73
24 files changed, 432 insertions, 45 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index ff6db1698..ec94768e0 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -9,7 +9,7 @@ project(minetest)
set(VERSION_MAJOR 0)
set(VERSION_MINOR 2)
-set(VERSION_PATCH 201109xx_dev)
+set(VERSION_PATCH 20110922_1)
set(VERSION_STRING "${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}")
# Configuration options
diff --git a/data/apple.png b/data/apple.png
new file mode 100644
index 000000000..9593f28f6
--- /dev/null
+++ b/data/apple.png
Binary files differ
diff --git a/data/apple_iron.png b/data/apple_iron.png
new file mode 100644
index 000000000..2dffdf014
--- /dev/null
+++ b/data/apple_iron.png
Binary files differ
diff --git a/data/chest_lock.png b/data/chest_lock.png
new file mode 100644
index 000000000..ae038fae5
--- /dev/null
+++ b/data/chest_lock.png
Binary files differ
diff --git a/doc/changelog.txt b/doc/changelog.txt
index d242070b6..66e0912cd 100644
--- a/doc/changelog.txt
+++ b/doc/changelog.txt
@@ -3,14 +3,20 @@ Minetest-c55 changelog
This should contain all the major changes.
For minor stuff, refer to the commit log of the repository.
-X:
-- Ladders
+0.2.20110922_1:
+- Make client report a newer version number to the server than 2011-07-31 does and make server disallow old clients
+
+0.2.20110922:
+- Map is saved in an SQLite database file (by Queatz)
+- Ladders (MarkTraceur)
- Lava
-- /me chat command
-- Slightly better looking inventory (transparency)
+- Apple trees (sfan5)
+- Slightly better looking inventory with transparency
+- /me chat command (Oblomov)
+- Using chosen map seed possible through fixed_map_seed configuration option (kahrl)
- Fix the long-existed PeerNotFound loop bug
- Some translations and localization-related fixes
-- Lots of small fixes, once again
+- Lots of small fixes
2011-07-31_3:
- Fixes a bug that made the server to deny non-empty passwords from players connecting the first time
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/CMakeLists.txt b/src/CMakeLists.txt
index 80ee0fc64..a753b6d87 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -74,7 +74,7 @@ else()
endif(APPLE)
endif(BUILD_CLIENT)
find_package(ZLIB REQUIRED)
- set(PLATFORM_LIBS -lpthread)
+ set(PLATFORM_LIBS -lpthread ${CMAKE_DL_LIBS})
#set(CLIENT_PLATFORM_LIBS -lXxf86vm)
# This way Xxf86vm is found on OpenBSD too
find_library(XXF86VM_LIBRARY Xxf86vm)
@@ -189,10 +189,10 @@ if(BUILD_CLIENT)
${PNG_LIBRARIES}
${X11_LIBRARIES}
${GETTEXT_LIBRARY}
- ${PLATFORM_LIBS}
- ${CLIENT_PLATFORM_LIBS}
${JTHREAD_LIBRARY}
${SQLITE3_LIBRARY}
+ ${PLATFORM_LIBS}
+ ${CLIENT_PLATFORM_LIBS}
)
endif(BUILD_CLIENT)
@@ -201,9 +201,9 @@ if(BUILD_SERVER)
target_link_libraries(
${PROJECT_NAME}server
${ZLIB_LIBRARIES}
- ${PLATFORM_LIBS}
${JTHREAD_LIBRARY}
${SQLITE3_LIBRARY}
+ ${PLATFORM_LIBS}
)
endif(BUILD_SERVER)
diff --git a/src/client.cpp b/src/client.cpp
index 81dedd144..fa600719e 100644
--- a/src/client.cpp
+++ b/src/client.cpp
@@ -429,7 +429,7 @@ void Client::step(float dtime)
snprintf((char*)&data[23], PASSWORD_SIZE, "%s", m_password.c_str());
// This should be incremented in each version
- writeU16(&data[51], 1);
+ writeU16(&data[51], 2);
// Send as unreliable
Send(0, data, false);
@@ -1961,7 +1961,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 20ab5f069..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];
@@ -428,6 +446,20 @@ InventoryItem *craft_get_result(InventoryItem **items)
return new MaterialItem(CONTENT_LADDER, 1);
}
}
+
+ // Iron Apple
+ {
+ ItemSpec specs[9];
+ specs[1] = ItemSpec(ITEM_CRAFT, "steel_ingot");
+ specs[3] = ItemSpec(ITEM_CRAFT, "steel_ingot");
+ specs[4] = ItemSpec(ITEM_CRAFT, "apple");
+ specs[5] = ItemSpec(ITEM_CRAFT, "steel_ingot");
+ specs[7] = ItemSpec(ITEM_CRAFT, "steel_ingot");
+ if(checkItemCombination(items, specs))
+ {
+ return new CraftItem("apple_iron", 1);
+ }
+ }
return NULL;
}
diff --git a/src/content_inventory.cpp b/src/content_inventory.cpp
index de8f8e397..59997ee4b 100644
--- a/src/content_inventory.cpp
+++ b/src/content_inventory.cpp
@@ -71,6 +71,10 @@ std::string item_craft_get_image_name(const std::string &subname)
return "scorched_stuff.png";
else if(subname == "firefly")
return "firefly.png";
+ else if(subname == "apple")
+ return "apple.png";
+ else if(subname == "apple_iron")
+ return "apple_iron.png";
else
return "cloud.png"; // just something
}
@@ -126,6 +130,10 @@ bool item_craft_is_eatable(const std::string &subname)
{
if(subname == "cooked_rat")
return true;
+ else if(subname == "apple")
+ return true;
+ else if(subname == "apple_iron")
+ return true;
return false;
}
@@ -133,6 +141,10 @@ s16 item_craft_eat_hp_change(const std::string &subname)
{
if(subname == "cooked_rat")
return 6; // 3 hearts
+ else if(subname == "apple")
+ return 4; // 2 hearts
+ else if(subname == "apple_iron")
+ return 8; // 4 hearts
return 0;
}
diff --git a/src/content_mapblock.cpp b/src/content_mapblock.cpp
index 482b9eb63..1cc37b969 100644
--- a/src/content_mapblock.cpp
+++ b/src/content_mapblock.cpp
@@ -188,6 +188,16 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
AtlasPointer pa_papyrus = g_texturesource->getTexture(
g_texturesource->getTextureId("papyrus.png"));
material_papyrus.setTexture(0, pa_papyrus.atlas);
+
+ // Apple material
+ video::SMaterial material_apple;
+ material_apple.setFlag(video::EMF_LIGHTING, false);
+ material_apple.setFlag(video::EMF_BILINEAR_FILTER, false);
+ material_apple.setFlag(video::EMF_FOG_ENABLE, true);
+ material_apple.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
+ AtlasPointer pa_apple = g_texturesource->getTexture(
+ g_texturesource->getTextureId("apple.png"));
+ material_apple.setTexture(0, pa_apple.atlas);
// junglegrass material
video::SMaterial material_junglegrass;
@@ -1203,6 +1213,56 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
// Add to mesh collector
collector.append(material_ladder, vertices, 4, indices, 6);
}
+ else if(n.getContent() == CONTENT_APPLE)
+ {
+ u8 l = decode_light(undiminish_light(n.getLightBlend(data->m_daynight_ratio)));
+ video::SColor c = MapBlock_LightColor(255, l);
+
+ for(u32 j=0; j<4; j++)
+ {
+ video::S3DVertex vertices[4] =
+ {
+ video::S3DVertex(-BS/2,-BS/2,0, 0,0,0, c,
+ pa_apple.x0(), pa_apple.y1()),
+ video::S3DVertex(BS/2,-BS/2,0, 0,0,0, c,
+ pa_apple.x1(), pa_apple.y1()),
+ video::S3DVertex(BS/2,BS/2,0, 0,0,0, c,
+ pa_apple.x1(), pa_apple.y0()),
+ video::S3DVertex(-BS/2,BS/2,0, 0,0,0, c,
+ pa_apple.x0(), pa_apple.y0()),
+ };
+
+ if(j == 0)
+ {
+ for(u16 i=0; i<4; i++)
+ vertices[i].Pos.rotateXZBy(45);
+ }
+ else if(j == 1)
+ {
+ for(u16 i=0; i<4; i++)
+ vertices[i].Pos.rotateXZBy(-45);
+ }
+ else if(j == 2)
+ {
+ for(u16 i=0; i<4; i++)
+ vertices[i].Pos.rotateXZBy(135);
+ }
+ else if(j == 3)
+ {
+ for(u16 i=0; i<4; i++)
+ vertices[i].Pos.rotateXZBy(-135);
+ }
+
+ for(u16 i=0; i<4; i++)
+ {
+ vertices[i].Pos += intToFloat(p + blockpos_nodes, BS);
+ }
+
+ u16 indices[] = {0,1,2,2,3,0};
+ // Add to mesh collector
+ collector.append(material_apple, vertices, 4, indices, 6);
+ }
+ }
}
}
#endif
diff --git a/src/content_mapnode.cpp b/src/content_mapnode.cpp
index 70f465130..a573ca141 100644
--- a/src/content_mapnode.cpp
+++ b/src/content_mapnode.cpp
@@ -581,6 +581,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;
@@ -638,6 +652,18 @@ void content_mapnode_init()
f->dug_item = std::string("MaterialItem2 ")+itos(i)+" 1";
setStoneLikeDiggingProperties(f->digging_properties, 3.0);
+ i = CONTENT_APPLE;
+ f = &content_features(i);
+ f->setInventoryTexture("apple.png");
+ f->param_type = CPT_LIGHT;
+ f->light_propagates = true;
+ f->sunlight_propagates = true;
+ f->solidness = 0; // drawn separately, makes no faces
+ f->walkable = false;
+ f->air_equivalent = true;
+ f->dug_item = std::string("CraftItem apple 1");
+ f->digging_properties.set("", DiggingProperties(true, 0.0, 0));
+
// NOTE: Remember to add frequently used stuff to the texture atlas in tile.cpp
diff --git a/src/content_mapnode.h b/src/content_mapnode.h
index 1f6292ba4..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
@@ -83,6 +84,8 @@ MapNode mapnode_translate_to_internal(MapNode n_from, u8 version);
#define CONTENT_JUNGLEGRASS 0x816
#define CONTENT_NC 0x817
#define CONTENT_NC_RB 0x818
+#define CONTENT_APPLE 0x819
+
#endif
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..e20334312 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();
+
+ virtual std::string getOwner(){ return m_text; }
+ virtual 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/defaultsettings.cpp b/src/defaultsettings.cpp
index 163ed0884..dec7f17bd 100644
--- a/src/defaultsettings.cpp
+++ b/src/defaultsettings.cpp
@@ -79,6 +79,7 @@ void set_default_settings()
// Server stuff
g_settings.setDefault("motd", "");
+ g_settings.setDefault("max_users", "20");
g_settings.setDefault("enable_experimental", "false");
g_settings.setDefault("creative_mode", "false");
g_settings.setDefault("enable_damage", "true");
diff --git a/src/environment.cpp b/src/environment.cpp
index ea33274df..ff570554d 100644
--- a/src/environment.cpp
+++ b/src/environment.cpp
@@ -1345,8 +1345,6 @@ void ServerEnvironment::deactivateFarObjects(bool force_delete)
i.atEnd()==false; i++)
{
ServerActiveObject* obj = i.getNode()->getValue();
- u16 id = i.getNode()->getKey();
- v3f objectpos = obj->getBasePosition();
// This shouldn't happen but check it
if(obj == NULL)
@@ -1357,9 +1355,12 @@ void ServerEnvironment::deactivateFarObjects(bool force_delete)
continue;
}
+ u16 id = i.getNode()->getKey();
+ v3f objectpos = obj->getBasePosition();
+
// The block in which the object resides in
v3s16 blockpos_o = getNodeBlockPos(floatToInt(objectpos, BS));
-
+
// If block is active, don't remove
if(m_active_blocks.contains(blockpos_o))
continue;
diff --git a/src/map.cpp b/src/map.cpp
index ecd12bddb..eb55d3a57 100644
--- a/src/map.cpp
+++ b/src/map.cpp
@@ -890,7 +890,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,6 +1014,7 @@ void Map::addNodeAndUpdate(v3s16 p, MapNode n,
if(meta_proto)
{
NodeMetadata *meta = meta_proto->clone();
+ meta->setOwner(player_name);
setNodeMetadata(p, meta);
}
@@ -1290,7 +1291,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 cb649addd..b58ba047b 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/mapgen.cpp b/src/mapgen.cpp
index 0018b9919..a07f4cac8 100644
--- a/src/mapgen.cpp
+++ b/src/mapgen.cpp
@@ -80,11 +80,12 @@ static s16 find_ground_level_clever(VoxelManipulator &vmanip, v2s16 p2d)
}
#endif
-static void make_tree(VoxelManipulator &vmanip, v3s16 p0)
+static void make_tree(VoxelManipulator &vmanip, v3s16 p0, bool is_apple_tree)
{
MapNode treenode(CONTENT_TREE);
MapNode leavesnode(CONTENT_LEAVES);
-
+ MapNode applenode(CONTENT_APPLE);
+
s16 trunk_h = myrand_range(4, 5);
v3s16 p1 = p0;
for(s16 ii=0; ii<trunk_h; ii++)
@@ -147,8 +148,14 @@ static void make_tree(VoxelManipulator &vmanip, v3s16 p0)
&& vmanip.m_data[vi].getContent() != CONTENT_IGNORE)
continue;
u32 i = leaves_a.index(x,y,z);
- if(leaves_d[i] == 1)
- vmanip.m_data[vi] = leavesnode;
+ if(leaves_d[i] == 1) {
+ bool is_apple = myrand_range(0,99) < 10;
+ if(is_apple_tree && is_apple) {
+ vmanip.m_data[vi] = applenode;
+ } else {
+ vmanip.m_data[vi] = leavesnode;
+ }
+ }
}
}
@@ -2129,7 +2136,16 @@ void make_block(BlockMakeData *data)
p.Y++;
//if(surface_humidity_2d(data->seed, v2s16(x, y)) < 0.5)
if(is_jungle == false)
- make_tree(vmanip, p);
+ {
+ bool is_apple_tree;
+ if(myrand_range(0,4) != 0)
+ is_apple_tree = false;
+ else
+ is_apple_tree = noise2d_perlin(
+ 0.5+(float)p.X/100, 0.5+(float)p.Z/100,
+ data->seed+342902, 3, 0.45) > 0.2;
+ make_tree(vmanip, p, is_apple_tree);
+ }
else
make_jungletree(vmanip, p);
}
diff --git a/src/nodemetadata.h b/src/nodemetadata.h
index de682f9b6..d81ade96c 100644
--- a/src/nodemetadata.h
+++ b/src/nodemetadata.h
@@ -65,6 +65,9 @@ public:
// Used to make custom inventory menus.
// See format in guiInventoryMenu.cpp.
virtual std::string getInventoryDrawSpecString(){return "";}
+ // primarily used for locking chests, but others can play too
+ virtual std::string getOwner(){ return std::string(""); }
+ virtual void setOwner(std::string t){ }
protected:
static void registerType(u16 id, Factory f);
diff --git a/src/server.cpp b/src/server.cpp
index 46993913f..5395d7618 100644
--- a/src/server.cpp
+++ b/src/server.cpp
@@ -2013,6 +2013,14 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
L"Your client is too old. Please upgrade.");
return;
}
+
+ /* Uhh... this should actually be a warning but let's do it like this */
+ if(net_proto_version < 2)
+ {
+ SendAccessDenied(m_con, peer_id,
+ L"Your client is too old. Please upgrade.");
+ return;
+ }
/*
Set up player
@@ -2091,11 +2099,21 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
stringToPrivs(g_settings.get("default_privs")));
m_authmanager.save();
}
+
+ // Enforce user limit.
+ // Don't enforce for users that have some admin right
+ if(m_clients.size() >= g_settings.getU16("max_users") &&
+ (m_authmanager.getPrivs(playername)
+ & (PRIV_SERVER|PRIV_BAN|PRIV_PRIVS)) == 0 &&
+ playername != g_settings.get("name"))
+ {
+ SendAccessDenied(m_con, peer_id, L"Too many users.");
+ return;
+ }
// Get player
Player *player = emergePlayer(playername, password, peer_id);
-
/*{
// DEBUG: Test serialization
std::ostringstream test_os;
@@ -2876,7 +2894,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
@@ -3203,7 +3222,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)
@@ -4104,7 +4162,7 @@ void Server::UpdateCrafting(u16 peer_id)
InventoryList *clist = player->inventory.getList("craft");
InventoryList *rlist = player->inventory.getList("craftresult");
- if(rlist->getUsedSlots() == 0)
+ if(rlist && rlist->getUsedSlots() == 0)
player->craftresult_is_preview = true;
if(rlist && player->craftresult_is_preview)
@@ -4381,16 +4439,16 @@ void Server::handlePeerChange(PeerChange &c)
// Collect information about leaving in chat
std::wstring message;
{
- std::wstring name = L"unknown";
Player *player = m_env.getPlayer(c.peer_id);
if(player != NULL)
- name = narrow_to_wide(player->getName());
-
- message += L"*** ";
- message += name;
- message += L" left game";
- if(c.timeout)
- message += L" (timed out)";
+ {
+ std::wstring name = narrow_to_wide(player->getName());
+ message += L"*** ";
+ message += name;
+ message += L" left game";
+ if(c.timeout)
+ message += L" (timed out)";
+ }
}
/*// Delete player
diff --git a/util/colors.txt b/util/colors.txt
index 2dceb9134..b605a9e2e 100644
--- a/util/colors.txt
+++ b/util/colors.txt
@@ -1,22 +1,26 @@
0 128 128 128 # CONTENT_STONE
-800 107 134 51 # CONTENT_GRASS
2 39 66 106 # CONTENT_WATER
3 255 255 0 # CONTENT_TORCH
+9 39 66 106 # CONTENT_WATERSOURCE
+e 117 86 41 # CONTENT_SIGN_WALL
+f 128 79 0 # CONTENT_CHEST
+10 118 118 118 # CONTENT_FURNACE
+15 103 78 42 # CONTENT_FENCE
+1e 162 119 53 # CONTENT_RAIL
+1f 154 110 40 # CONTENT_LADDER
+20 255 204 0 # CONTENT_LAVA
+21 255 204 0 # CONTENT_LAVASOURCE
+800 107 134 51 # CONTENT_GRASS
801 86 58 31 # CONTENT_TREE
802 48 95 8 # CONTENT_LEAVES
803 102 129 38 # CONTENT_GRASS_FOOTSTEPS
804 178 178 0 # CONTENT_MESE
805 101 84 36 # CONTENT_MUD
-9 39 66 106 # CONTENT_WATERSOURCE
808 104 78 42 # CONTENT_WOOD
809 210 194 156 # CONTENT_SAND
-e 117 86 41 # CONTENT_SIGN_WALL
-f 128 79 0 # CONTENT_CHEST
-10 118 118 118 # CONTENT_FURNACE
80a 123 123 123 # CONTENT_COBBLE
80b 199 199 199 # CONTENT_STEEL
-80c 183 183 222 # CONENT_GLASS
-15 103 78 42 # CONTENT_FENCE
+80c 183 183 222 # CONTENT_GLASS
80d 219 202 178 # CONTENT_MOSSYCOBBLE
80e 78 154 6 # CONTENT_GRAVEL
80f 204 0 0 # CONTENT_SANDSTONE
@@ -24,3 +28,8 @@ f 128 79 0 # CONTENT_CHEST
811 170 50 25 # CONTENT_BRICK
812 104 78 42 # CONTENT_CLAY
813 58 105 18 # CONTENT_PAPYRUS
+814 196 160 0 # CONTENT_BOOKSHELF
+815 205 190 121 # CONTENT_JUNGLETREE
+816 62 101 25 # CONTENT_JUNGLEGRASS
+817 255 153 255 # CONTENT_NC
+818 102 50 255 # CONTENT_NC_RB
diff --git a/util/minetestmapper.py b/util/minetestmapper.py
index e13a1bdc3..c7ec0774e 100755
--- a/util/minetestmapper.py
+++ b/util/minetestmapper.py
@@ -85,6 +85,13 @@ def int_to_hex4(i):
return "%04X" % i
+def getBlockAsInteger(p):
+ return p[2]*16777216 + p[1]*4096 + p[0]
+
+def getIntegerAsBlock(i):
+ return i%4096, int(i/4096)%4096, int(i/16777216)%4096
+
+
def limit(i, l, h):
if(i > h):
i = h
@@ -169,6 +176,30 @@ zlist = []
# List all sectors to memory and calculate the width and heigth of the
# resulting picture.
+
+conn = None
+cur = None
+if os.path.exists(path + "map.sqlite"):
+ import sqlite3
+ conn = sqlite3.connect(path + "map.sqlite")
+ cur = conn.cursor()
+
+ cur.execute("SELECT `pos` FROM `blocks`")
+ while True:
+ r = cur.fetchone()
+ if not r:
+ break
+
+ x, y, z = getIntegerAsBlock (r[0])
+
+ if x < sector_xmin or x > sector_xmax:
+ continue
+ if z < sector_zmin or z > sector_zmax:
+ continue
+
+ xlist.append(x)
+ zlist.append(z)
+
if os.path.exists(path + "sectors2"):
for filename in os.listdir(path + "sectors2"):
for filename2 in os.listdir(path + "sectors2/" + filename):
@@ -305,6 +336,16 @@ for n in range(len(xlist)):
sectortype = ""
+ if cur:
+ ps = getBlockAsInteger((xpos, 0, zpos))
+ cur.execute("SELECT `pos` FROM `blocks` WHERE `pos`>=? AND `pos`<?", (ps, ps + 4096))
+ while True:
+ r = cur.fetchone()
+ if not r:
+ break
+ pos = getIntegerAsBlock(r[0])[1]
+ ylist.append(pos)
+ sectortype = "sqlite"
try:
for filename in os.listdir(path + "sectors/" + sector1):
if(filename != "meta"):
@@ -316,7 +357,7 @@ for n in range(len(xlist)):
except OSError:
pass
- if sectortype != "old":
+ if sectortype == "":
try:
for filename in os.listdir(path + "sectors2/" + sector2):
if(filename != "meta"):
@@ -348,10 +389,21 @@ for n in range(len(xlist)):
yhex = int_to_hex4(ypos)
filename = ""
- if sectortype == "old":
- filename = path + "sectors/" + sector1 + "/" + yhex.lower()
+ if sectortype == "sqlite":
+ ps = getBlockAsInteger((xpos, ypos, zpos))
+ cur.execute("SELECT `data` FROM `blocks` WHERE `pos`==? LIMIT 1", (ps,))
+ r = cur.fetchone()
+ if not r:
+ continue
+ filename = "mtm_tmp"
+ f = file(filename, 'wb')
+ f.write(r[0])
+ f.close()
else:
- filename = path + "sectors2/" + sector2 + "/" + yhex.lower()
+ if sectortype == "old":
+ filename = path + "sectors/" + sector1 + "/" + yhex.lower()
+ else:
+ filename = path + "sectors2/" + sector2 + "/" + yhex.lower()
f = file(filename, "rb")
@@ -374,6 +426,16 @@ for n in range(len(xlist)):
if len(pixellist) > 0:
for (ypos, filename) in ylist2:
+ ps = getBlockAsInteger((xpos, ypos, zpos))
+ cur.execute("SELECT `data` FROM `blocks` WHERE `pos`==? LIMIT 1", (ps,))
+ r = cur.fetchone()
+ if not r:
+ continue
+ filename = "mtm_tmp"
+ f = file(filename, 'wb')
+ f.write(r[0])
+ f.close()
+
f = file(filename, "rb")
version = ord(f.read(1))
@@ -495,5 +557,8 @@ if drawplayers:
except OSError:
pass
+if os.path.isfile("mtm_tmp"):
+ os.remove("mtm_tmp")
+
print "Saving"
im.save(output)