diff --git a/data/rail.png b/data/rail.png new file mode 100644 index 000000000..18176d9f3 Binary files /dev/null and b/data/rail.png differ diff --git a/data/rail_crossing.png b/data/rail_crossing.png new file mode 100644 index 000000000..984640577 Binary files /dev/null and b/data/rail_crossing.png differ diff --git a/data/rail_curved.png b/data/rail_curved.png new file mode 100644 index 000000000..62afa3d2b Binary files /dev/null and b/data/rail_curved.png differ diff --git a/data/rail_t_junction.png b/data/rail_t_junction.png new file mode 100644 index 000000000..9985f63cd Binary files /dev/null and b/data/rail_t_junction.png differ diff --git a/src/mapblock.cpp b/src/mapblock.cpp index c6b82634d..71044652d 100644 --- a/src/mapblock.cpp +++ b/src/mapblock.cpp @@ -1672,6 +1672,110 @@ scene::SMesh* makeMapBlockMesh(MeshMakeData *data) collector.append(material_papyrus, vertices, 4, indices, 6); } } + else if(n.d == CONTENT_RAIL) + { + u8 l = decode_light(n.getLightBlend(data->m_daynight_ratio)); + video::SColor c(255,l,l,l); + + bool is_rail_x [] = { false, false }; /* x-1, x+1 */ + bool is_rail_z [] = { false, false }; /* z-1, z+1 */ + + MapNode n_minus_x = data->m_vmanip.getNodeNoEx(blockpos_nodes + v3s16(x-1,y,z)); + MapNode n_plus_x = data->m_vmanip.getNodeNoEx(blockpos_nodes + v3s16(x+1,y,z)); + MapNode n_minus_z = data->m_vmanip.getNodeNoEx(blockpos_nodes + v3s16(x,y,z-1)); + MapNode n_plus_z = data->m_vmanip.getNodeNoEx(blockpos_nodes + v3s16(x,y,z+1)); + + if(n_minus_x.d == CONTENT_RAIL) + is_rail_x[0] = true; + if(n_plus_x.d == CONTENT_RAIL) + is_rail_x[1] = true; + if(n_minus_z.d == CONTENT_RAIL) + is_rail_z[0] = true; + if(n_plus_z.d == CONTENT_RAIL) + is_rail_z[1] = true; + + float d = (float)BS/16; + video::S3DVertex vertices[4] = + { + video::S3DVertex(-BS/2,-BS/2+d,-BS/2, 0,0,0, c, + 0, 1), + video::S3DVertex(BS/2,-BS/2+d,-BS/2, 0,0,0, c, + 1, 1), + video::S3DVertex(BS/2,-BS/2+d,BS/2, 0,0,0, c, + 1, 0), + video::S3DVertex(-BS/2,-BS/2+d,BS/2, 0,0,0, c, + 0, 0), + }; + + video::SMaterial material_rail; + material_rail.setFlag(video::EMF_LIGHTING, false); + material_rail.setFlag(video::EMF_BACK_FACE_CULLING, false); + material_rail.setFlag(video::EMF_BILINEAR_FILTER, false); + material_rail.setFlag(video::EMF_FOG_ENABLE, true); + material_rail.MaterialType + = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF; + + int adjacencies = is_rail_x[0] + is_rail_x[1] + is_rail_z[0] + is_rail_z[1]; + + // Assign textures + if(adjacencies < 2) + material_rail.setTexture(0, g_texturesource->getTextureRaw("rail.png")); + else if(adjacencies == 2) + { + if((is_rail_x[0] && is_rail_x[1]) || (is_rail_z[0] && is_rail_z[1])) + material_rail.setTexture(0, g_texturesource->getTextureRaw("rail.png")); + else + material_rail.setTexture(0, g_texturesource->getTextureRaw("rail_curved.png")); + } + else if(adjacencies == 3) + material_rail.setTexture(0, g_texturesource->getTextureRaw("rail_t_junction.png")); + else if(adjacencies == 4) + material_rail.setTexture(0, g_texturesource->getTextureRaw("rail_crossing.png")); + + // Rotate textures + int angle = 0; + + if(adjacencies == 1) + { + if(is_rail_x[0] || is_rail_x[1]) + angle = 90; + } + else if(adjacencies == 2) + { + if(is_rail_x[0] && is_rail_x[1]) + angle = 90; + else if(is_rail_x[0] && is_rail_z[0]) + angle = 270; + else if(is_rail_x[0] && is_rail_z[1]) + angle = 180; + else if(is_rail_x[1] && is_rail_z[1]) + angle = 90; + } + else if(adjacencies == 3) + { + if(!is_rail_x[0]) + angle=0; + if(!is_rail_x[1]) + angle=180; + if(!is_rail_z[0]) + angle=90; + if(!is_rail_z[1]) + angle=270; + } + + if(angle != 0) { + for(u16 i=0; i<4; i++) + vertices[i].Pos.rotateXZBy(angle); + } + + for(s32 i=0; i<4; i++) + { + vertices[i].Pos += intToFloat(p + blockpos_nodes, BS); + } + + u16 indices[] = {0,1,2,2,3,0}; + collector.append(material_rail, vertices, 4, indices, 6); + } } diff --git a/src/mapnode.cpp b/src/mapnode.cpp index 7e97a8d04..1c0a2740b 100644 --- a/src/mapnode.cpp +++ b/src/mapnode.cpp @@ -281,6 +281,17 @@ void init_mapnode() f->solidness = 0; // drawn separately, makes no faces f->air_equivalent = true; // grass grows underneath + i = CONTENT_RAIL; + f = &g_content_features[i]; + f->setInventoryTexture("rail.png"); + f->light_propagates = true; + f->param_type = CPT_LIGHT; + f->is_ground_content = true; + f->dug_item = std::string("MaterialItem ")+itos(i)+" 1"; + f->solidness = 0; // drawn separately, makes no faces + f->air_equivalent = true; // grass grows underneath + f->walkable = false; + // Deprecated i = CONTENT_COALSTONE; f = &g_content_features[i]; diff --git a/src/mapnode.h b/src/mapnode.h index 57335b741..409fe2bcf 100644 --- a/src/mapnode.h +++ b/src/mapnode.h @@ -107,6 +107,7 @@ void init_content_inventory_texture_paths(); #define CONTENT_CLAY 25 #define CONTENT_PAPYRUS 26 #define CONTENT_BOOKSHELF 27 +#define CONTENT_RAIL 28 /* Content feature list diff --git a/src/materials.cpp b/src/materials.cpp index 7815f593e..a8a9a94a8 100644 --- a/src/materials.cpp +++ b/src/materials.cpp @@ -79,6 +79,7 @@ void initializeMaterialProperties() setWoodLikeDiggingProperties(CONTENT_PAPYRUS, 0.25); setWoodLikeDiggingProperties(CONTENT_GLASS, 0.15); setWoodLikeDiggingProperties(CONTENT_FENCE, 0.75); + setDirtLikeDiggingProperties(CONTENT_RAIL, 0.75); setWoodLikeDiggingProperties(CONTENT_WOOD, 0.75); setWoodLikeDiggingProperties(CONTENT_BOOKSHELF, 0.75); setWoodLikeDiggingProperties(CONTENT_CHEST, 1.0); diff --git a/src/server.cpp b/src/server.cpp index f40ed05a5..4e9ff076f 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -3915,6 +3915,26 @@ void Server::UpdateCrafting(u16 peer_id) } } + // Rail + if(!found) + { + ItemSpec specs[9]; + specs[0] = ItemSpec(ITEM_CRAFT, "steel_ingot"); + specs[1] = ItemSpec(ITEM_CRAFT, "Stick"); + specs[2] = ItemSpec(ITEM_CRAFT, "steel_ingot"); + specs[3] = ItemSpec(ITEM_CRAFT, "steel_ingot"); + specs[4] = ItemSpec(ITEM_CRAFT, "Stick"); + specs[5] = ItemSpec(ITEM_CRAFT, "steel_ingot"); + specs[6] = ItemSpec(ITEM_CRAFT, "steel_ingot"); + specs[7] = ItemSpec(ITEM_CRAFT, "Stick"); + specs[8] = ItemSpec(ITEM_CRAFT, "steel_ingot"); + if(checkItemCombination(items, specs)) + { + rlist->addItem(new MaterialItem(CONTENT_RAIL, 15)); + found = true; + } + } + // Chest if(!found) { @@ -4163,6 +4183,7 @@ void setCreativeInventory(Player *player) CONTENT_BOOKSHELF, CONTENT_GLASS, CONTENT_FENCE, + CONTENT_RAIL, CONTENT_MESE, CONTENT_WATERSOURCE, CONTENT_CLOUD,