From: Sebastian Rühl Date: Sun, 26 Jun 2011 10:24:32 +0000 (+0200) Subject: Merge branch 'master' of https://github.com/erlehmann/minetest-delta.git into upstrea... X-Git-Url: http://81.2.79.47:8989/gitweb/?a=commitdiff_plain;h=033ae0dcaecc37fee487e44896a0c0fb4c844e4e;p=zefram%2Fminetest%2Fminetest_engine.git Merge branch 'master' of https://github.com/erlehmann/minetest-delta.git into upstream_merge Conflicts: .gitignore CMakeLists.txt data/heart.png src/CMakeLists.txt src/game.cpp src/guiMainMenu.cpp src/inventory.cpp src/map.cpp src/mapblock.cpp src/mapnode.cpp src/mapnode.h src/materials.cpp src/server.cpp Signed-off-by: Sebastian Rühl --- 033ae0dcaecc37fee487e44896a0c0fb4c844e4e diff --cc .gitignore index ce00d585,ee3aa43c..f0c372ab --- a/.gitignore +++ b/.gitignore @@@ -18,5 -17,4 +18,5 @@@ Makefil cmake_install.cmake src/jthread/libjthread.a debug.txt +bin/debug.txt - + minetestmapper/map.png diff --cc genmap.py index 00000000,aaa35690..a6050940 mode 000000,100755..100755 --- a/genmap.py +++ b/genmap.py @@@ -1,0 -1,91 +1,271 @@@ + #!/usr/bin/python2 + + # This is an example script that generates some valid map data. + + import struct + import random + import os + import sys ++import zlib ++import array + from pnoise import pnoise + -""" -Map format: -map/sectors/XXXXZZZZ/YYYY ++# Old directory format: ++# world/sectors/XXXXZZZZ/YYYY ++# XXXX,YYYY,ZZZZ = coordinates in hexadecimal ++# fffe = -2 ++# ffff = -1 ++# 0000 = 0 ++# 0001 = 1 ++# ++# New directory format: ++# world/sectors2/XXX/ZZZ/YYYY ++# XXX,YYYY,ZZZ = coordinates in hexadecimal ++# fffe = -2 ++# ffff = -1 ++# 0000 = 0 ++# 0001 = 1 ++# ffe = -2 ++# fff = -1 ++# 000 = 0 ++# 001 = 1 ++# ++# For more proper file format documentation, refer to mapformat.txt ++# For node type documentation, refer to mapnode.h ++# NodeMetadata documentation is not complete, refer to nodemeta.cpp ++# + -XXXX,YYYY,ZZZZ = coordinates in hexadecimal ++# Seed for generating terrain ++SEED = 0 + -fffe = -2 -ffff = -1 -0000 = 0 -0001 = 1 -""" ++# 0=old, 1=new ++SECTOR_DIR_FORMAT = 1 ++ ++mapdir = "world" + + def to4h(i): + s = ""; + s += '{0:1x}'.format((i>>12) & 0x000f) + s += '{0:1x}'.format((i>>8) & 0x000f) + s += '{0:1x}'.format((i>>4) & 0x000f) + s += '{0:1x}'.format((i>>0) & 0x000f) + return s + -def getrand(): ++def to3h(i): ++ s = ""; ++ s += '{0:1x}'.format((i>>8) & 0x000f) ++ s += '{0:1x}'.format((i>>4) & 0x000f) ++ s += '{0:1x}'.format((i>>0) & 0x000f) ++ return s ++ ++def get_sector_dir(px, pz): ++ global SECTOR_DIR_FORMAT ++ if SECTOR_DIR_FORMAT == 0: ++ return "/sectors/"+to4h(px)+to4h(pz) ++ elif SECTOR_DIR_FORMAT == 1: ++ return "/sectors2/"+to3h(px)+"/"+to3h(pz) ++ else: ++ assert(0) ++ ++def getrand_air_stone(): + i = random.randrange(0,2) + if i==0: + return 0 + return 254 + -def writeblock(mapdir, px,py,pz, version): - sectordir = mapdir + "/sectors/" + to4h(px) + to4h(pz) ++# 3-dimensional vector (position) ++class v3: ++ def __init__(self, x=0, y=0, z=0): ++ self.X = x ++ self.Y = y ++ self.Z = z ++ ++class NodeMeta: ++ def __init__(self, type_id, data): ++ self.type_id = type_id ++ self.data = data ++ ++class StaticObject: ++ def __init__(self): ++ self.type_id = 0 ++ self.data = "" ++ ++def ser_u16(i): ++ return chr((i>>8)&0xff) + chr((i>>0)&0xff) ++def ser_u32(i): ++ return (chr((i>>24)&0xff) + chr((i>>16)&0xff) ++ + chr((i>>8)&0xff) + chr((i>>0)&0xff)) ++ ++# A 16x16x16 chunk of map ++class MapBlock: ++ def __init__(self): ++ self.content = array.array('B') ++ self.param1 = array.array('B') ++ self.param2 = array.array('B') ++ for i in range(16*16*16): ++ # Initialize to air ++ self.content.append(254) ++ # Full light on sunlight, none when no sunlight ++ self.param1.append(15) ++ # No additional parameters ++ self.param2.append(0) ++ ++ # key = v3 pos ++ # value = NodeMeta ++ self.nodemeta = {} ++ ++ # key = v3 pos ++ # value = StaticObject ++ self.static_objects = {} ++ ++ def set_content(self, v3, b): ++ self.content[v3.Z*16*16+v3.Y*16+v3.X] = b ++ def set_param1(self, v3, b): ++ self.param1[v3.Z*16*16+v3.Y*16+v3.X] = b ++ def set_param2(self, v3, b): ++ self.param2[v3.Z*16*16+v3.Y*16+v3.X] = b ++ ++ # Get data for serialization. Returns a string. ++ def serialize_data(self): ++ s = "" ++ for i in range(16*16*16): ++ s += chr(self.content[i]) ++ for i in range(16*16*16): ++ s += chr(self.param1[i]) ++ for i in range(16*16*16): ++ s += chr(self.param2[i]) ++ return s ++ ++ def serialize_nodemeta(self): ++ s = "" ++ s += ser_u16(1) ++ s += ser_u16(len(self.nodemeta)) ++ for pos, meta in self.nodemeta.items(): ++ pos_i = pos.Z*16*16 + pos.Y*16 + pos.X ++ s += ser_u16(pos_i) ++ s += ser_u16(meta.type_id) ++ s += ser_u16(len(meta.data)) ++ s += meta.data ++ return s ++ ++ def serialize_staticobj(self): ++ s = "" ++ s += chr(0) ++ s += ser_u16(len(self.static_objects)) ++ for pos, obj in self.static_objects.items(): ++ pos_i = pos.Z*16*16 + pos.Y*16 + pos.X ++ s += ser_s32(pos.X*1000) ++ s += ser_s32(pos.Y*1000) ++ s += ser_s32(pos.Z*1000) ++ s += ser_u16(obj.type_id) ++ s += ser_u16(len(obj.data)) ++ s += obj.data ++ return s ++ ++def writeblock(mapdir, px,py,pz, block): ++ ++ sectordir = mapdir + get_sector_dir(px, pz); + + try: + os.makedirs(sectordir) + except OSError: + pass ++ ++ path = sectordir+"/"+to4h(py) ++ ++ print("writing block file "+path) + + f = open(sectordir+"/"+to4h(py), "wb") + - if version == 0: - # version - f.write(struct.pack('B', 0)) - # is_underground - f.write(struct.pack('B', 0)) - elif version == 2: - # version - f.write(struct.pack('B', 2)) - # is_underground - f.write(struct.pack('B', 0)) ++ if f == None: ++ return ++ ++ # version ++ version = 17 ++ f.write(struct.pack('B', version)) ++ ++ # flags ++ # 0x01=is_undg, 0x02=dn_diff, 0x04=lighting_expired ++ flags = 0 + 0x02 + 0x04 ++ f.write(struct.pack('B', flags)) + - for z in range(0,16): - for y in range(0,16): - for x in range(0,16): - b = 254 - r = 20.0*pnoise((px*16+x)/100.,(pz*16+z)/100.,0) - r += 5.0*pnoise((px*16+x)/25.,(pz*16+z)/25.,0) - #print("r="+str(r)) - y1 = py*16+y - if y1 <= r-3: - b = 0 #stone - elif y1 <= r: - b = 1 #grass - elif y1 <= 1: - b = 9 #water - if version == 0: - # Material content - f.write(struct.pack('B', b)) - elif version == 2: - # Material content - f.write(struct.pack('B', b)) - # Brightness - f.write(struct.pack('B', 15)) ++ # data ++ c_obj = zlib.compressobj() ++ c_obj.compress(block.serialize_data()) ++ f.write(struct.pack('BB', 0x78, 0x9c)) # zlib magic number ++ f.write(c_obj.flush()) ++ ++ # node metadata ++ c_obj = zlib.compressobj() ++ c_obj.compress(block.serialize_nodemeta()) ++ f.write(struct.pack('BB', 0x78, 0x9c)) # zlib magic number ++ f.write(c_obj.flush()) ++ ++ # mapblockobject count ++ f.write(ser_u16(0)) ++ ++ # static objects ++ f.write(block.serialize_staticobj()) ++ ++ # timestamp ++ f.write(ser_u32(0xffffffff)) + + f.close() + -mapdir = "map" ++for z0 in range(-1,3): ++ for x0 in range(-1,3): ++ for y0 in range(-1,3): ++ print("generating block "+str(x0)+","+str(y0)+","+str(z0)) ++ #v3 blockp = v3(x0,y0,z0) ++ ++ # Create a MapBlock ++ block = MapBlock() ++ ++ # Generate stuff in it ++ for z in range(0,16): ++ for x in range(0,16): ++ h = 20.0*pnoise((x0*16+x)/100.,(z0*16+z)/100.,SEED+0) ++ h += 5.0*pnoise((x0*16+x)/25.,(z0*16+z)/25.,SEED+0) ++ if pnoise((x0*16+x)/25.,(z0*16+z)/25.,SEED+92412) > 0.05: ++ h += 10 ++ #print("r="+str(r)) ++ # This enables comparison by == ++ h = int(h) ++ for y in range(0,16): ++ p = v3(x,y,z) ++ b = 254 ++ y1 = y0*16+y ++ if y1 <= h-3: ++ b = 0 #stone ++ elif y1 <= h and y1 <= 0: ++ b = 8 #mud ++ elif y1 == h: ++ b = 1 #grass ++ elif y1 < h: ++ b = 8 #mud ++ elif y1 <= 1: ++ b = 9 #water ++ ++ # Material content ++ block.set_content(p, b) ++ ++ # Place a sign at the center at surface level. ++ # Placing a sign means placing the sign node and ++ # adding node metadata to the mapblock. ++ if x == 8 and z == 8 and y0*16 <= h-1 and (y0+1)*16-1 > h: ++ p = v3(8,h+1-y0*16,8) ++ # 14 = Sign ++ content_type = 14 ++ block.set_content(p, content_type) ++ # This places the sign to the bottom of the cube. ++ # Working values: 0x01, 0x02, 0x04, 0x08, 0x10, 0x20 ++ block.set_param2(p, 0x08) ++ # Then add metadata to hold the text of the sign ++ s = "Hello at sector ("+str(x0)+","+str(z0)+")" ++ meta = NodeMeta(content_type, ser_u16(len(s))+s) ++ block.nodemeta[p] = meta + -for z in range(-2,3): - for y in range(-1,2): - for x in range(-2,3): - print("generating block "+str(x)+","+str(y)+","+str(z)) - writeblock(mapdir, x,y,z, 0) ++ # Write it on disk ++ writeblock(mapdir, x0,y0,z0, block) + + #END diff --cc heart.png index 00000000,00000000..bea1aefd new file mode 100644 Binary files differ diff --cc src/CMakeLists.txt index 73a960ec,9d5cf7d2..f62a8626 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@@ -107,7 -98,9 +107,8 @@@ set(minetest_SRC keycode.cpp clouds.cpp clientobject.cpp - guiFurnaceMenu.cpp guiMainMenu.cpp + guiKeyChangeMenu.cpp guiMessageMenu.cpp guiTextInputMenu.cpp guiInventoryMenu.cpp diff --cc src/client.cpp index abc05650,5869dc77..e86b3a4f --- a/src/client.cpp +++ b/src/client.cpp @@@ -772,10 -780,7 +795,9 @@@ void Client::ProcessData(u8 *data, u32 */ //m_env.getClientMap().updateMeshes(block->getPos(), getDayNightRatio()); -- + /* + Add it to mesh update queue and set it to be acknowledged after update. + */ addUpdateMeshTaskWithEdge(p, true); } else if(command == TOCLIENT_PLAYERPOS) diff --cc src/content_craft.cpp index 32d2e6d4,00000000..069e6830 mode 100644,000000..100644 --- a/src/content_craft.cpp +++ b/src/content_craft.cpp @@@ -1,480 -1,0 +1,586 @@@ +/* +Minetest-c55 +Copyright (C) 2010-2011 celeron55, Perttu Ahola + +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. +*/ + +#include "content_craft.h" +#include "inventory.h" +#include "content_mapnode.h" +#include "player.h" + +/* + items: actually *items[9] + return value: allocates a new item, or returns NULL. +*/ +InventoryItem *craft_get_result(InventoryItem **items) +{ + // Wood + { + ItemSpec specs[9]; + specs[0] = ItemSpec(ITEM_MATERIAL, CONTENT_TREE); + if(checkItemCombination(items, specs)) + { + return new MaterialItem(CONTENT_WOOD, 4); + } + } + + // Stick + { + ItemSpec specs[9]; + specs[0] = ItemSpec(ITEM_MATERIAL, CONTENT_WOOD); + if(checkItemCombination(items, specs)) + { + return new CraftItem("Stick", 4); + } + } + + // Fence + { + ItemSpec specs[9]; + specs[3] = ItemSpec(ITEM_CRAFT, "Stick"); + specs[4] = ItemSpec(ITEM_CRAFT, "Stick"); + specs[5] = ItemSpec(ITEM_CRAFT, "Stick"); + specs[6] = ItemSpec(ITEM_CRAFT, "Stick"); + specs[7] = ItemSpec(ITEM_CRAFT, "Stick"); + specs[8] = ItemSpec(ITEM_CRAFT, "Stick"); + if(checkItemCombination(items, specs)) + { + return new MaterialItem(CONTENT_FENCE, 2); + } + } + + // Sign + { + 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)) + { + //return new MapBlockObjectItem("Sign"); + return new MaterialItem(CONTENT_SIGN_WALL, 1); + } + } + + // Torch + { + ItemSpec specs[9]; + specs[0] = ItemSpec(ITEM_CRAFT, "lump_of_coal"); + specs[3] = ItemSpec(ITEM_CRAFT, "Stick"); + if(checkItemCombination(items, specs)) + { + return new MaterialItem(CONTENT_TORCH, 4); + } + } + + // Wooden pick + { + 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)) + { + return new ToolItem("WPick", 0); + } + } + + // Stone pick + { + ItemSpec specs[9]; + specs[0] = ItemSpec(ITEM_MATERIAL, CONTENT_COBBLE); + specs[1] = ItemSpec(ITEM_MATERIAL, CONTENT_COBBLE); + specs[2] = ItemSpec(ITEM_MATERIAL, CONTENT_COBBLE); + specs[4] = ItemSpec(ITEM_CRAFT, "Stick"); + specs[7] = ItemSpec(ITEM_CRAFT, "Stick"); + if(checkItemCombination(items, specs)) + { + return new ToolItem("STPick", 0); + } + } + + // Steel pick + { + ItemSpec specs[9]; + specs[0] = ItemSpec(ITEM_CRAFT, "steel_ingot"); + specs[1] = ItemSpec(ITEM_CRAFT, "steel_ingot"); + specs[2] = ItemSpec(ITEM_CRAFT, "steel_ingot"); + specs[4] = ItemSpec(ITEM_CRAFT, "Stick"); + specs[7] = ItemSpec(ITEM_CRAFT, "Stick"); + if(checkItemCombination(items, specs)) + { + return new ToolItem("SteelPick", 0); + } + } + + // Mese pick + { + ItemSpec specs[9]; + specs[0] = ItemSpec(ITEM_MATERIAL, CONTENT_MESE); + specs[1] = ItemSpec(ITEM_MATERIAL, CONTENT_MESE); + specs[2] = ItemSpec(ITEM_MATERIAL, CONTENT_MESE); + specs[4] = ItemSpec(ITEM_CRAFT, "Stick"); + specs[7] = ItemSpec(ITEM_CRAFT, "Stick"); + if(checkItemCombination(items, specs)) + { + return new ToolItem("MesePick", 0); + } + } + + // Wooden shovel + { + ItemSpec specs[9]; + specs[1] = ItemSpec(ITEM_MATERIAL, CONTENT_WOOD); + specs[4] = ItemSpec(ITEM_CRAFT, "Stick"); + specs[7] = ItemSpec(ITEM_CRAFT, "Stick"); + if(checkItemCombination(items, specs)) + { + return new ToolItem("WShovel", 0); + } + } + + // Stone shovel + { + ItemSpec specs[9]; + specs[1] = ItemSpec(ITEM_MATERIAL, CONTENT_COBBLE); + specs[4] = ItemSpec(ITEM_CRAFT, "Stick"); + specs[7] = ItemSpec(ITEM_CRAFT, "Stick"); + if(checkItemCombination(items, specs)) + { + return new ToolItem("STShovel", 0); + } + } + + // Steel shovel + { + ItemSpec specs[9]; + specs[1] = ItemSpec(ITEM_CRAFT, "steel_ingot"); + specs[4] = ItemSpec(ITEM_CRAFT, "Stick"); + specs[7] = ItemSpec(ITEM_CRAFT, "Stick"); + if(checkItemCombination(items, specs)) + { + return new ToolItem("SteelShovel", 0); + } + } + + // Wooden axe + { + ItemSpec specs[9]; + specs[0] = ItemSpec(ITEM_MATERIAL, CONTENT_WOOD); + specs[1] = ItemSpec(ITEM_MATERIAL, CONTENT_WOOD); + specs[3] = ItemSpec(ITEM_MATERIAL, CONTENT_WOOD); + specs[4] = ItemSpec(ITEM_CRAFT, "Stick"); + specs[7] = ItemSpec(ITEM_CRAFT, "Stick"); + if(checkItemCombination(items, specs)) + { + return new ToolItem("WAxe", 0); + } + } + + // Stone axe + { + ItemSpec specs[9]; + specs[0] = ItemSpec(ITEM_MATERIAL, CONTENT_COBBLE); + specs[1] = ItemSpec(ITEM_MATERIAL, CONTENT_COBBLE); + specs[3] = ItemSpec(ITEM_MATERIAL, CONTENT_COBBLE); + specs[4] = ItemSpec(ITEM_CRAFT, "Stick"); + specs[7] = ItemSpec(ITEM_CRAFT, "Stick"); + if(checkItemCombination(items, specs)) + { + return new ToolItem("STAxe", 0); + } + } + + // Steel axe + { + ItemSpec specs[9]; + specs[0] = ItemSpec(ITEM_CRAFT, "steel_ingot"); + specs[1] = ItemSpec(ITEM_CRAFT, "steel_ingot"); + specs[3] = ItemSpec(ITEM_CRAFT, "steel_ingot"); + specs[4] = ItemSpec(ITEM_CRAFT, "Stick"); + specs[7] = ItemSpec(ITEM_CRAFT, "Stick"); + if(checkItemCombination(items, specs)) + { + return new ToolItem("SteelAxe", 0); + } + } + + // Wooden sword + { + ItemSpec specs[9]; + specs[1] = ItemSpec(ITEM_MATERIAL, CONTENT_WOOD); + specs[4] = ItemSpec(ITEM_MATERIAL, CONTENT_WOOD); + specs[7] = ItemSpec(ITEM_CRAFT, "Stick"); + if(checkItemCombination(items, specs)) + { + return new ToolItem("WSword", 0); + } + } + + // Stone sword + { + ItemSpec specs[9]; + specs[1] = ItemSpec(ITEM_MATERIAL, CONTENT_COBBLE); + specs[4] = ItemSpec(ITEM_MATERIAL, CONTENT_COBBLE); + specs[7] = ItemSpec(ITEM_CRAFT, "Stick"); + if(checkItemCombination(items, specs)) + { + return new ToolItem("STSword", 0); + } + } + + // Steel sword + { + ItemSpec specs[9]; + specs[1] = ItemSpec(ITEM_CRAFT, "steel_ingot"); + specs[4] = ItemSpec(ITEM_CRAFT, "steel_ingot"); + specs[7] = ItemSpec(ITEM_CRAFT, "Stick"); + if(checkItemCombination(items, specs)) + { + return new ToolItem("SteelSword", 0); + } + } + ++ // Rail ++ { ++ 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)) ++ { ++ return new MaterialItem(CONTENT_RAIL, 15); ++ } ++ } ++ + // 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[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_CHEST, 1); + } + } + + // Furnace + { + ItemSpec specs[9]; + specs[0] = ItemSpec(ITEM_MATERIAL, CONTENT_COBBLE); + specs[1] = ItemSpec(ITEM_MATERIAL, CONTENT_COBBLE); + specs[2] = ItemSpec(ITEM_MATERIAL, CONTENT_COBBLE); + specs[3] = ItemSpec(ITEM_MATERIAL, CONTENT_COBBLE); + specs[5] = ItemSpec(ITEM_MATERIAL, CONTENT_COBBLE); + specs[6] = ItemSpec(ITEM_MATERIAL, CONTENT_COBBLE); + specs[7] = ItemSpec(ITEM_MATERIAL, CONTENT_COBBLE); + specs[8] = ItemSpec(ITEM_MATERIAL, CONTENT_COBBLE); + if(checkItemCombination(items, specs)) + { + return new MaterialItem(CONTENT_FURNACE, 1); + } + } + + // Steel block + { + ItemSpec specs[9]; + specs[0] = ItemSpec(ITEM_CRAFT, "steel_ingot"); + specs[1] = ItemSpec(ITEM_CRAFT, "steel_ingot"); + specs[2] = ItemSpec(ITEM_CRAFT, "steel_ingot"); + specs[3] = ItemSpec(ITEM_CRAFT, "steel_ingot"); + specs[4] = ItemSpec(ITEM_CRAFT, "steel_ingot"); + specs[5] = ItemSpec(ITEM_CRAFT, "steel_ingot"); + specs[6] = ItemSpec(ITEM_CRAFT, "steel_ingot"); + specs[7] = ItemSpec(ITEM_CRAFT, "steel_ingot"); + specs[8] = ItemSpec(ITEM_CRAFT, "steel_ingot"); + if(checkItemCombination(items, specs)) + { + return new MaterialItem(CONTENT_STEEL, 1); + } + } + ++ // Sandstone ++ { ++ ItemSpec specs[9]; ++ specs[3] = ItemSpec(ITEM_MATERIAL, CONTENT_SAND); ++ specs[4] = ItemSpec(ITEM_MATERIAL, CONTENT_SAND); ++ specs[6] = ItemSpec(ITEM_MATERIAL, CONTENT_SAND); ++ specs[7] = ItemSpec(ITEM_MATERIAL, CONTENT_SAND); ++ if(checkItemCombination(items, specs)) ++ { ++ return new MaterialItem(CONTENT_SANDSTONE, 1); ++ } ++ } ++ ++ // Clay ++ { ++ ItemSpec specs[9]; ++ specs[3] = ItemSpec(ITEM_CRAFT, "lump_of_clay"); ++ specs[4] = ItemSpec(ITEM_CRAFT, "lump_of_clay"); ++ specs[6] = ItemSpec(ITEM_CRAFT, "lump_of_clay"); ++ specs[7] = ItemSpec(ITEM_CRAFT, "lump_of_clay"); ++ if(checkItemCombination(items, specs)) ++ { ++ return new MaterialItem(CONTENT_CLAY, 1); ++ } ++ } ++ ++ // Brick ++ { ++ ItemSpec specs[9]; ++ specs[3] = ItemSpec(ITEM_CRAFT, "clay_brick"); ++ specs[4] = ItemSpec(ITEM_CRAFT, "clay_brick"); ++ specs[6] = ItemSpec(ITEM_CRAFT, "clay_brick"); ++ specs[7] = ItemSpec(ITEM_CRAFT, "clay_brick"); ++ if(checkItemCombination(items, specs)) ++ { ++ return new MaterialItem(CONTENT_BRICK, 1); ++ } ++ } ++ ++ // Paper ++ { ++ ItemSpec specs[9]; ++ specs[3] = ItemSpec(ITEM_MATERIAL, CONTENT_PAPYRUS); ++ specs[4] = ItemSpec(ITEM_MATERIAL, CONTENT_PAPYRUS); ++ specs[5] = ItemSpec(ITEM_MATERIAL, CONTENT_PAPYRUS); ++ if(checkItemCombination(items, specs)) ++ { ++ return new CraftItem("paper", 1); ++ } ++ } ++ ++ // Book ++ { ++ ItemSpec specs[9]; ++ specs[1] = ItemSpec(ITEM_CRAFT, "paper"); ++ specs[4] = ItemSpec(ITEM_CRAFT, "paper"); ++ specs[7] = ItemSpec(ITEM_CRAFT, "paper"); ++ if(checkItemCombination(items, specs)) ++ { ++ return new CraftItem("book", 1); ++ } ++ } ++ ++ // Book shelf ++ { ++ 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_CRAFT, "book"); ++ specs[4] = ItemSpec(ITEM_CRAFT, "book"); ++ specs[5] = ItemSpec(ITEM_CRAFT, "book"); ++ 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_BOOKSHELF, 1); ++ } ++ } ++ + return NULL; +} + +void craft_set_creative_inventory(Player *player) +{ + player->resetInventory(); + + // Give some good tools + { + InventoryItem *item = new ToolItem("MesePick", 0); + void* r = player->inventory.addItem("main", item); + assert(r == NULL); + } + { + InventoryItem *item = new ToolItem("SteelPick", 0); + void* r = player->inventory.addItem("main", item); + assert(r == NULL); + } + { + InventoryItem *item = new ToolItem("SteelAxe", 0); + void* r = player->inventory.addItem("main", item); + assert(r == NULL); + } + { + InventoryItem *item = new ToolItem("SteelShovel", 0); + void* r = player->inventory.addItem("main", item); + assert(r == NULL); + } + + /* + Give materials + */ + + // CONTENT_IGNORE-terminated list + u8 material_items[] = { + CONTENT_TORCH, + CONTENT_COBBLE, + CONTENT_MUD, + CONTENT_STONE, + CONTENT_SAND, ++ CONTENT_SANDSTONE, ++ CONTENT_CLAY, ++ CONTENT_BRICK, + CONTENT_TREE, + CONTENT_LEAVES, ++ CONTENT_CACTUS, ++ CONTENT_PAPYRUS, ++ CONTENT_BOOKSHELF, + CONTENT_GLASS, + CONTENT_FENCE, ++ CONTENT_RAIL, + CONTENT_MESE, + CONTENT_WATERSOURCE, + CONTENT_CLOUD, + CONTENT_CHEST, + CONTENT_FURNACE, + CONTENT_SIGN_WALL, + CONTENT_IGNORE + }; + + u8 *mip = material_items; + for(u16 i=0; iinventory.addItem("main", item); + + mip++; + } + +#if 0 + assert(USEFUL_CONTENT_COUNT <= PLAYER_INVENTORY_SIZE); + + // add torch first + InventoryItem *item = new MaterialItem(CONTENT_TORCH, 1); + player->inventory.addItem("main", item); + + // Then others + for(u16 i=0; iinventory.addItem("main", item); + } +#endif + + /*// Sign + { + InventoryItem *item = new MapBlockObjectItem("Sign Example text"); + void* r = player->inventory.addItem("main", item); + assert(r == NULL); + }*/ +} + +void craft_give_initial_stuff(Player *player) +{ + { + InventoryItem *item = new ToolItem("SteelPick", 0); + void* r = player->inventory.addItem("main", item); + assert(r == NULL); + } + { + InventoryItem *item = new MaterialItem(CONTENT_TORCH, 99); + void* r = player->inventory.addItem("main", item); + assert(r == NULL); + } + { + InventoryItem *item = new ToolItem("SteelAxe", 0); + void* r = player->inventory.addItem("main", item); + assert(r == NULL); + } + { + InventoryItem *item = new ToolItem("SteelShovel", 0); + void* r = player->inventory.addItem("main", item); + assert(r == NULL); + } + { + InventoryItem *item = new MaterialItem(CONTENT_COBBLE, 99); + void* r = player->inventory.addItem("main", item); + assert(r == NULL); + } + /*{ + InventoryItem *item = new MaterialItem(CONTENT_MESE, 6); + void* r = player->inventory.addItem("main", item); + assert(r == NULL); + } + { + 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); + 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); + }*/ + /*// 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); + }*/ +} + diff --cc src/content_inventory.cpp index 3b72b31f,00000000..357c8ef2 mode 100644,000000..100644 --- a/src/content_inventory.cpp +++ b/src/content_inventory.cpp @@@ -1,98 -1,0 +1,108 @@@ +/* +Minetest-c55 +Copyright (C) 2010-2011 celeron55, Perttu Ahola + +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. +*/ + +#include "content_inventory.h" +#include "inventory.h" +#include "serverobject.h" +#include "content_mapnode.h" + +bool item_material_is_cookable(u8 content) +{ + if(content == CONTENT_TREE) + return true; + else if(content == CONTENT_COBBLE) + return true; + else if(content == CONTENT_SAND) + return true; + return false; +} + +InventoryItem* item_material_create_cook_result(u8 content) +{ + if(content == CONTENT_TREE) + return new CraftItem("lump_of_coal", 1); + else if(content == CONTENT_COBBLE) + return new MaterialItem(CONTENT_STONE, 1); + else if(content == CONTENT_SAND) + return new MaterialItem(CONTENT_GLASS, 1); + return NULL; +} + +std::string item_craft_get_image_name(const std::string &subname) +{ + if(subname == "Stick") + return "stick.png"; ++ else if(subname == "paper") ++ return "paper.png"; ++ else if(subname == "book") ++ return "book.png"; + else if(subname == "lump_of_coal") + return "lump_of_coal.png"; + else if(subname == "lump_of_iron") + return "lump_of_iron.png"; ++ else if(subname == "lump_of_clay") ++ return "lump_of_clay.png"; + else if(subname == "steel_ingot") + return "steel_ingot.png"; ++ else if(subname == "clay_brick") ++ return "clay_brick.png"; + else if(subname == "rat") + return "rat.png"; + else + return "cloud.png"; // just something +} + +ServerActiveObject* item_craft_create_object(const std::string &subname, + ServerEnvironment *env, u16 id, v3f pos) +{ + if(subname == "rat") + { + ServerActiveObject *obj = new RatSAO(env, id, pos); + return obj; + } + + return NULL; +} + +s16 item_craft_get_drop_count(const std::string &subname) +{ + if(subname == "rat") + return 1; + + return -1; +} + +bool item_craft_is_cookable(const std::string &subname) +{ - if(subname == "lump_of_iron") ++ if(subname == "lump_of_iron" || subname == "lump_of_clay") + return true; + + return false; +} + +InventoryItem* item_craft_create_cook_result(const std::string &subname) +{ + if(subname == "lump_of_iron") + return new CraftItem("steel_ingot", 1); ++ else if(subname == "lump_of_clay") ++ return new CraftItem("clay_brick", 1); + + return NULL; +} + diff --cc src/content_mapblock.cpp index bc701aad,00000000..9ef0599d mode 100644,000000..100644 --- a/src/content_mapblock.cpp +++ b/src/content_mapblock.cpp @@@ -1,923 -1,0 +1,1076 @@@ +/* +Minetest-c55 +Copyright (C) 2010-2011 celeron55, Perttu Ahola + +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. +*/ + +#include "content_mapblock.h" +#include "content_mapnode.h" +#include "main.h" // For g_settings and g_texturesource +#include "mineral.h" + +#ifndef SERVER +// Create a cuboid. +// material - the material to use (for all 6 faces) +// collector - the MeshCollector for the resulting polygons +// pa - texture atlas pointer for the material +// c - vertex colour - used for all +// pos - the position of the centre of the cuboid +// rz,ry,rz - the radius of the cuboid in each dimension +// txc - texture coordinates - this is a list of texture coordinates +// for the opposite corners of each face - therefore, there +// should be (2+2)*6=24 values in the list. Alternatively, pass +// NULL to use the entire texture for each face. The order of +// the faces in the list is top-backi-right-front-left-bottom +// If you specified 0,0,1,1 for each face, that would be the +// same as passing NULL. +void makeCuboid(video::SMaterial &material, MeshCollector *collector, + AtlasPointer* pa, video::SColor &c, + v3f &pos, f32 rx, f32 ry, f32 rz, f32* txc) +{ + f32 tu0=pa->x0(); + f32 tu1=pa->x1(); + f32 tv0=pa->y0(); + f32 tv1=pa->y1(); + f32 txus=tu1-tu0; + f32 txvs=tv1-tv0; + + video::S3DVertex v[4] = + { + video::S3DVertex(0,0,0, 0,0,0, c, tu0, tv1), + video::S3DVertex(0,0,0, 0,0,0, c, tu1, tv1), + video::S3DVertex(0,0,0, 0,0,0, c, tu1, tv0), + video::S3DVertex(0,0,0, 0,0,0, c, tu0, tv0) + }; + + for(int i=0;i<6;i++) + { + switch(i) + { + case 0: // top + v[0].Pos.X=-rx; v[0].Pos.Y= ry; v[0].Pos.Z=-rz; + v[1].Pos.X=-rx; v[1].Pos.Y= ry; v[1].Pos.Z= rz; + v[2].Pos.X= rx; v[2].Pos.Y= ry; v[2].Pos.Z= rz; + v[3].Pos.X= rx; v[3].Pos.Y= ry, v[3].Pos.Z=-rz; + break; + case 1: // back + v[0].Pos.X=-rx; v[0].Pos.Y= ry; v[0].Pos.Z=-rz; + v[1].Pos.X= rx; v[1].Pos.Y= ry; v[1].Pos.Z=-rz; + v[2].Pos.X= rx; v[2].Pos.Y=-ry; v[2].Pos.Z=-rz; + v[3].Pos.X=-rx; v[3].Pos.Y=-ry, v[3].Pos.Z=-rz; + break; + case 2: //right + v[0].Pos.X= rx; v[0].Pos.Y= ry; v[0].Pos.Z=-rz; + v[1].Pos.X= rx; v[1].Pos.Y= ry; v[1].Pos.Z= rz; + v[2].Pos.X= rx; v[2].Pos.Y=-ry; v[2].Pos.Z= rz; + v[3].Pos.X= rx; v[3].Pos.Y=-ry, v[3].Pos.Z=-rz; + break; + case 3: // front + v[0].Pos.X= rx; v[0].Pos.Y= ry; v[0].Pos.Z= rz; + v[1].Pos.X=-rx; v[1].Pos.Y= ry; v[1].Pos.Z= rz; + v[2].Pos.X=-rx; v[2].Pos.Y=-ry; v[2].Pos.Z= rz; + v[3].Pos.X= rx; v[3].Pos.Y=-ry, v[3].Pos.Z= rz; + break; + case 4: // left + v[0].Pos.X=-rx; v[0].Pos.Y= ry; v[0].Pos.Z= rz; + v[1].Pos.X=-rx; v[1].Pos.Y= ry; v[1].Pos.Z=-rz; + v[2].Pos.X=-rx; v[2].Pos.Y=-ry; v[2].Pos.Z=-rz; + v[3].Pos.X=-rx; v[3].Pos.Y=-ry, v[3].Pos.Z= rz; + break; + case 5: // bottom + v[0].Pos.X= rx; v[0].Pos.Y=-ry; v[0].Pos.Z= rz; + v[1].Pos.X=-rx; v[1].Pos.Y=-ry; v[1].Pos.Z= rz; + v[2].Pos.X=-rx; v[2].Pos.Y=-ry; v[2].Pos.Z=-rz; + v[3].Pos.X= rx; v[3].Pos.Y=-ry, v[3].Pos.Z=-rz; + break; + } + + if(txc!=NULL) + { + v[0].TCoords.X=tu0+txus*txc[0]; v[0].TCoords.Y=tv0+txvs*txc[3]; + v[1].TCoords.X=tu0+txus*txc[2]; v[1].TCoords.Y=tv0+txvs*txc[3]; + v[2].TCoords.X=tu0+txus*txc[2]; v[2].TCoords.Y=tv0+txvs*txc[1]; + v[3].TCoords.X=tu0+txus*txc[0]; v[3].TCoords.Y=tv0+txvs*txc[1]; + txc+=4; + } + + for(u16 i=0; i<4; i++) + v[i].Pos += pos; + u16 indices[] = {0,1,2,2,3,0}; + collector->append(material, v, 4, indices, 6); + + } + +} +#endif + +#ifndef SERVER +void mapblock_mesh_generate_special(MeshMakeData *data, + MeshCollector &collector) +{ + // 0ms + //TimeTaker timer("mapblock_mesh_generate_special()"); + + /* + Some settings + */ + bool new_style_water = g_settings.getBool("new_style_water"); + bool new_style_leaves = g_settings.getBool("new_style_leaves"); + //bool smooth_lighting = g_settings.getBool("smooth_lighting"); + bool invisible_stone = g_settings.getBool("invisible_stone"); + + float node_water_level = 1.0; + if(new_style_water) + node_water_level = 0.85; + + v3s16 blockpos_nodes = data->m_blockpos*MAP_BLOCKSIZE; + + // Flowing water material + video::SMaterial material_water1; + material_water1.setFlag(video::EMF_LIGHTING, false); + material_water1.setFlag(video::EMF_BACK_FACE_CULLING, false); + material_water1.setFlag(video::EMF_BILINEAR_FILTER, false); + material_water1.setFlag(video::EMF_FOG_ENABLE, true); + material_water1.MaterialType = video::EMT_TRANSPARENT_VERTEX_ALPHA; + AtlasPointer pa_water1 = g_texturesource->getTexture( + g_texturesource->getTextureId("water.png")); + material_water1.setTexture(0, pa_water1.atlas); + + // New-style leaves material + video::SMaterial material_leaves1; + material_leaves1.setFlag(video::EMF_LIGHTING, false); + //material_leaves1.setFlag(video::EMF_BACK_FACE_CULLING, false); + material_leaves1.setFlag(video::EMF_BILINEAR_FILTER, false); + material_leaves1.setFlag(video::EMF_FOG_ENABLE, true); + material_leaves1.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF; + AtlasPointer pa_leaves1 = g_texturesource->getTexture( + g_texturesource->getTextureId("leaves.png")); + material_leaves1.setTexture(0, pa_leaves1.atlas); + + // Glass material + video::SMaterial material_glass; + material_glass.setFlag(video::EMF_LIGHTING, false); + material_glass.setFlag(video::EMF_BILINEAR_FILTER, false); + material_glass.setFlag(video::EMF_FOG_ENABLE, true); + material_glass.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF; + AtlasPointer pa_glass = g_texturesource->getTexture( + g_texturesource->getTextureId("glass.png")); + material_glass.setTexture(0, pa_glass.atlas); + + // Wood material + video::SMaterial material_wood; + material_wood.setFlag(video::EMF_LIGHTING, false); + material_wood.setFlag(video::EMF_BILINEAR_FILTER, false); + material_wood.setFlag(video::EMF_FOG_ENABLE, true); + material_wood.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF; + AtlasPointer pa_wood = g_texturesource->getTexture( + g_texturesource->getTextureId("wood.png")); + material_wood.setTexture(0, pa_wood.atlas); + + // General ground material for special output + // Texture is modified just before usage + video::SMaterial material_general; + material_general.setFlag(video::EMF_LIGHTING, false); + material_general.setFlag(video::EMF_BILINEAR_FILTER, false); + material_general.setFlag(video::EMF_FOG_ENABLE, true); + material_general.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF; + ++ ++ // Papyrus material ++ video::SMaterial material_papyrus; ++ material_papyrus.setFlag(video::EMF_LIGHTING, false); ++ material_papyrus.setFlag(video::EMF_BILINEAR_FILTER, false); ++ material_papyrus.setFlag(video::EMF_FOG_ENABLE, true); ++ material_papyrus.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF; ++ AtlasPointer pa_papyrus = g_texturesource->getTexture( ++ g_texturesource->getTextureId("papyrus.png")); ++ material_papyrus.setTexture(0, pa_papyrus.atlas); + for(s16 z=0; zm_vmanip.getNodeNoEx(blockpos_nodes+p); + + /* + Add torches to mesh + */ + if(n.d == CONTENT_TORCH) + { + video::SColor c(255,255,255,255); + + // Wall at X+ of node + video::S3DVertex vertices[4] = + { + video::S3DVertex(-BS/2,-BS/2,0, 0,0,0, c, 0,1), + video::S3DVertex(BS/2,-BS/2,0, 0,0,0, c, 1,1), + video::S3DVertex(BS/2,BS/2,0, 0,0,0, c, 1,0), + video::S3DVertex(-BS/2,BS/2,0, 0,0,0, c, 0,0), + }; + + v3s16 dir = unpackDir(n.dir); + + for(s32 i=0; i<4; i++) + { + if(dir == v3s16(1,0,0)) + vertices[i].Pos.rotateXZBy(0); + if(dir == v3s16(-1,0,0)) + vertices[i].Pos.rotateXZBy(180); + if(dir == v3s16(0,0,1)) + vertices[i].Pos.rotateXZBy(90); + if(dir == v3s16(0,0,-1)) + vertices[i].Pos.rotateXZBy(-90); + if(dir == v3s16(0,-1,0)) + vertices[i].Pos.rotateXZBy(45); + if(dir == v3s16(0,1,0)) + vertices[i].Pos.rotateXZBy(-45); + + vertices[i].Pos += intToFloat(p + blockpos_nodes, BS); + } + + // Set material + video::SMaterial material; + material.setFlag(video::EMF_LIGHTING, false); + material.setFlag(video::EMF_BACK_FACE_CULLING, false); + material.setFlag(video::EMF_BILINEAR_FILTER, false); + //material.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL; + material.MaterialType + = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF; + + if(dir == v3s16(0,-1,0)) + material.setTexture(0, + g_texturesource->getTextureRaw("torch_on_floor.png")); + else if(dir == v3s16(0,1,0)) + material.setTexture(0, + g_texturesource->getTextureRaw("torch_on_ceiling.png")); + // For backwards compatibility + else if(dir == v3s16(0,0,0)) + material.setTexture(0, + g_texturesource->getTextureRaw("torch_on_floor.png")); + else + material.setTexture(0, + g_texturesource->getTextureRaw("torch.png")); + + u16 indices[] = {0,1,2,2,3,0}; + // Add to mesh collector + collector.append(material, vertices, 4, indices, 6); + } + /* + Signs on walls + */ + if(n.d == CONTENT_SIGN_WALL) + { + u8 l = decode_light(n.getLightBlend(data->m_daynight_ratio)); + video::SColor c(255,l,l,l); + + float d = (float)BS/16; + // Wall at X+ of node + video::S3DVertex vertices[4] = + { + video::S3DVertex(BS/2-d,-BS/2,-BS/2, 0,0,0, c, 0,1), + video::S3DVertex(BS/2-d,-BS/2,BS/2, 0,0,0, c, 1,1), + video::S3DVertex(BS/2-d,BS/2,BS/2, 0,0,0, c, 1,0), + video::S3DVertex(BS/2-d,BS/2,-BS/2, 0,0,0, c, 0,0), + }; + + v3s16 dir = unpackDir(n.dir); + + for(s32 i=0; i<4; i++) + { + if(dir == v3s16(1,0,0)) + vertices[i].Pos.rotateXZBy(0); + if(dir == v3s16(-1,0,0)) + vertices[i].Pos.rotateXZBy(180); + if(dir == v3s16(0,0,1)) + vertices[i].Pos.rotateXZBy(90); + if(dir == v3s16(0,0,-1)) + vertices[i].Pos.rotateXZBy(-90); + if(dir == v3s16(0,-1,0)) + vertices[i].Pos.rotateXYBy(-90); + if(dir == v3s16(0,1,0)) + vertices[i].Pos.rotateXYBy(90); + + vertices[i].Pos += intToFloat(p + blockpos_nodes, BS); + } + + // Set material + video::SMaterial material; + material.setFlag(video::EMF_LIGHTING, false); + material.setFlag(video::EMF_BACK_FACE_CULLING, false); + material.setFlag(video::EMF_BILINEAR_FILTER, false); + material.setFlag(video::EMF_FOG_ENABLE, true); + //material.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL; + material.MaterialType + = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF; + + material.setTexture(0, + g_texturesource->getTextureRaw("sign_wall.png")); + + u16 indices[] = {0,1,2,2,3,0}; + // Add to mesh collector + collector.append(material, vertices, 4, indices, 6); + } + /* + Add flowing water to mesh + */ + else if(n.d == CONTENT_WATER) + { + bool top_is_water = false; + MapNode ntop = data->m_vmanip.getNodeNoEx(blockpos_nodes + v3s16(x,y+1,z)); + if(ntop.d == CONTENT_WATER || ntop.d == CONTENT_WATERSOURCE) + top_is_water = true; + + u8 l = 0; + // Use the light of the node on top if possible + if(content_features(ntop.d).param_type == CPT_LIGHT) + l = decode_light(ntop.getLightBlend(data->m_daynight_ratio)); + // Otherwise use the light of this node (the water) + else + l = decode_light(n.getLightBlend(data->m_daynight_ratio)); + video::SColor c(WATER_ALPHA,l,l,l); + + // Neighbor water levels (key = relative position) + // Includes current node + core::map neighbor_levels; + core::map neighbor_contents; + core::map neighbor_flags; + const u8 neighborflag_top_is_water = 0x01; + v3s16 neighbor_dirs[9] = { + v3s16(0,0,0), + v3s16(0,0,1), + v3s16(0,0,-1), + v3s16(1,0,0), + v3s16(-1,0,0), + v3s16(1,0,1), + v3s16(-1,0,-1), + v3s16(1,0,-1), + v3s16(-1,0,1), + }; + for(u32 i=0; i<9; i++) + { + u8 content = CONTENT_AIR; + float level = -0.5 * BS; + u8 flags = 0; + // Check neighbor + v3s16 p2 = p + neighbor_dirs[i]; + MapNode n2 = data->m_vmanip.getNodeNoEx(blockpos_nodes + p2); + if(n2.d != CONTENT_IGNORE) + { + content = n2.d; + + if(n2.d == CONTENT_WATERSOURCE) + level = (-0.5+node_water_level) * BS; + else if(n2.d == CONTENT_WATER) + level = (-0.5 + ((float)n2.param2 + 0.5) / 8.0 + * node_water_level) * BS; + + // Check node above neighbor. + // NOTE: This doesn't get executed if neighbor + // doesn't exist + p2.Y += 1; + n2 = data->m_vmanip.getNodeNoEx(blockpos_nodes + p2); + if(n2.d == CONTENT_WATERSOURCE || n2.d == CONTENT_WATER) + flags |= neighborflag_top_is_water; + } + + neighbor_levels.insert(neighbor_dirs[i], level); + neighbor_contents.insert(neighbor_dirs[i], content); + neighbor_flags.insert(neighbor_dirs[i], flags); + } + + //float water_level = (-0.5 + ((float)n.param2 + 0.5) / 8.0) * BS; + //float water_level = neighbor_levels[v3s16(0,0,0)]; + + // Corner heights (average between four waters) + f32 corner_levels[4]; + + v3s16 halfdirs[4] = { + v3s16(0,0,0), + v3s16(1,0,0), + v3s16(1,0,1), + v3s16(0,0,1), + }; + for(u32 i=0; i<4; i++) + { + v3s16 cornerdir = halfdirs[i]; + float cornerlevel = 0; + u32 valid_count = 0; + for(u32 j=0; j<4; j++) + { + v3s16 neighbordir = cornerdir - halfdirs[j]; + u8 content = neighbor_contents[neighbordir]; + // Special case for source nodes + if(content == CONTENT_WATERSOURCE) + { + cornerlevel = (-0.5+node_water_level)*BS; + valid_count = 1; + break; + } + else if(content == CONTENT_WATER) + { + cornerlevel += neighbor_levels[neighbordir]; + valid_count++; + } + else if(content == CONTENT_AIR) + { + cornerlevel += -0.5*BS; + valid_count++; + } + } + if(valid_count > 0) + cornerlevel /= valid_count; + corner_levels[i] = cornerlevel; + } + + /* + Generate sides + */ + + v3s16 side_dirs[4] = { + v3s16(1,0,0), + v3s16(-1,0,0), + v3s16(0,0,1), + v3s16(0,0,-1), + }; + s16 side_corners[4][2] = { + {1, 2}, + {3, 0}, + {2, 3}, + {0, 1}, + }; + for(u32 i=0; i<4; i++) + { + v3s16 dir = side_dirs[i]; + + /* + If our topside is water and neighbor's topside + is water, don't draw side face + */ + if(top_is_water && + neighbor_flags[dir] & neighborflag_top_is_water) + continue; + + u8 neighbor_content = neighbor_contents[dir]; + + // Don't draw face if neighbor is not air or water + if(neighbor_content != CONTENT_AIR + && neighbor_content != CONTENT_WATER) + continue; + + bool neighbor_is_water = (neighbor_content == CONTENT_WATER); + + // Don't draw any faces if neighbor is water and top is water + if(neighbor_is_water == true && top_is_water == false) + continue; + + video::S3DVertex vertices[4] = + { + /*video::S3DVertex(-BS/2,0,BS/2, 0,0,0, c, 0,1), + video::S3DVertex(BS/2,0,BS/2, 0,0,0, c, 1,1), + video::S3DVertex(BS/2,0,BS/2, 0,0,0, c, 1,0), + video::S3DVertex(-BS/2,0,BS/2, 0,0,0, c, 0,0),*/ + video::S3DVertex(-BS/2,0,BS/2, 0,0,0, c, + pa_water1.x0(), pa_water1.y1()), + video::S3DVertex(BS/2,0,BS/2, 0,0,0, c, + pa_water1.x1(), pa_water1.y1()), + video::S3DVertex(BS/2,0,BS/2, 0,0,0, c, + pa_water1.x1(), pa_water1.y0()), + video::S3DVertex(-BS/2,0,BS/2, 0,0,0, c, + pa_water1.x0(), pa_water1.y0()), + }; + + /* + If our topside is water, set upper border of face + at upper border of node + */ + if(top_is_water) + { + vertices[2].Pos.Y = 0.5*BS; + vertices[3].Pos.Y = 0.5*BS; + } + /* + Otherwise upper position of face is corner levels + */ + else + { + vertices[2].Pos.Y = corner_levels[side_corners[i][0]]; + vertices[3].Pos.Y = corner_levels[side_corners[i][1]]; + } + + /* + If neighbor is water, lower border of face is corner + water levels + */ + if(neighbor_is_water) + { + vertices[0].Pos.Y = corner_levels[side_corners[i][1]]; + vertices[1].Pos.Y = corner_levels[side_corners[i][0]]; + } + /* + If neighbor is not water, lower border of face is + lower border of node + */ + else + { + vertices[0].Pos.Y = -0.5*BS; + vertices[1].Pos.Y = -0.5*BS; + } + + for(s32 j=0; j<4; j++) + { + if(dir == v3s16(0,0,1)) + vertices[j].Pos.rotateXZBy(0); + if(dir == v3s16(0,0,-1)) + vertices[j].Pos.rotateXZBy(180); + if(dir == v3s16(-1,0,0)) + vertices[j].Pos.rotateXZBy(90); + if(dir == v3s16(1,0,-0)) + vertices[j].Pos.rotateXZBy(-90); + + vertices[j].Pos += intToFloat(p + blockpos_nodes, BS); + } + + u16 indices[] = {0,1,2,2,3,0}; + // Add to mesh collector + collector.append(material_water1, vertices, 4, indices, 6); + } + + /* + Generate top side, if appropriate + */ + + if(top_is_water == false) + { + video::S3DVertex vertices[4] = + { + /*video::S3DVertex(-BS/2,0,-BS/2, 0,0,0, c, 0,1), + video::S3DVertex(BS/2,0,-BS/2, 0,0,0, c, 1,1), + video::S3DVertex(BS/2,0,BS/2, 0,0,0, c, 1,0), + video::S3DVertex(-BS/2,0,BS/2, 0,0,0, c, 0,0),*/ + video::S3DVertex(-BS/2,0,BS/2, 0,0,0, c, + pa_water1.x0(), pa_water1.y1()), + video::S3DVertex(BS/2,0,BS/2, 0,0,0, c, + pa_water1.x1(), pa_water1.y1()), + video::S3DVertex(BS/2,0,-BS/2, 0,0,0, c, + pa_water1.x1(), pa_water1.y0()), + video::S3DVertex(-BS/2,0,-BS/2, 0,0,0, c, + pa_water1.x0(), pa_water1.y0()), + }; + + // This fixes a strange bug + s32 corner_resolve[4] = {3,2,1,0}; + + for(s32 i=0; i<4; i++) + { + //vertices[i].Pos.Y += water_level; + //vertices[i].Pos.Y += neighbor_levels[v3s16(0,0,0)]; + s32 j = corner_resolve[i]; + vertices[i].Pos.Y += corner_levels[j]; + vertices[i].Pos += intToFloat(p + blockpos_nodes, BS); + } + + u16 indices[] = {0,1,2,2,3,0}; + // Add to mesh collector + collector.append(material_water1, vertices, 4, indices, 6); + } + } + /* + Add water sources to mesh if using new style + */ + else if(n.d == CONTENT_WATERSOURCE && new_style_water) + { + //bool top_is_water = false; + bool top_is_air = false; + MapNode n = data->m_vmanip.getNodeNoEx(blockpos_nodes + v3s16(x,y+1,z)); + /*if(n.d == CONTENT_WATER || n.d == CONTENT_WATERSOURCE) + top_is_water = true;*/ + if(n.d == CONTENT_AIR) + top_is_air = true; + + /*if(top_is_water == true) + continue;*/ + if(top_is_air == false) + continue; + + u8 l = decode_light(n.getLightBlend(data->m_daynight_ratio)); + video::SColor c(WATER_ALPHA,l,l,l); + + video::S3DVertex vertices[4] = + { + /*video::S3DVertex(-BS/2,0,-BS/2, 0,0,0, c, 0,1), + video::S3DVertex(BS/2,0,-BS/2, 0,0,0, c, 1,1), + video::S3DVertex(BS/2,0,BS/2, 0,0,0, c, 1,0), + video::S3DVertex(-BS/2,0,BS/2, 0,0,0, c, 0,0),*/ + video::S3DVertex(-BS/2,0,BS/2, 0,0,0, c, + pa_water1.x0(), pa_water1.y1()), + video::S3DVertex(BS/2,0,BS/2, 0,0,0, c, + pa_water1.x1(), pa_water1.y1()), + video::S3DVertex(BS/2,0,-BS/2, 0,0,0, c, + pa_water1.x1(), pa_water1.y0()), + video::S3DVertex(-BS/2,0,-BS/2, 0,0,0, c, + pa_water1.x0(), pa_water1.y0()), + }; + + for(s32 i=0; i<4; i++) + { + vertices[i].Pos.Y += (-0.5+node_water_level)*BS; + vertices[i].Pos += intToFloat(p + blockpos_nodes, BS); + } + + u16 indices[] = {0,1,2,2,3,0}; + // Add to mesh collector + collector.append(material_water1, vertices, 4, indices, 6); + } + /* + Add leaves if using new style + */ + else if(n.d == CONTENT_LEAVES && new_style_leaves) + { + /*u8 l = decode_light(n.getLightBlend(data->m_daynight_ratio));*/ + u8 l = decode_light(undiminish_light(n.getLightBlend(data->m_daynight_ratio))); + video::SColor c(255,l,l,l); + + for(u32 j=0; j<6; j++) + { + video::S3DVertex vertices[4] = + { + /*video::S3DVertex(-BS/2,-BS/2,BS/2, 0,0,0, c, 0,1), + video::S3DVertex(BS/2,-BS/2,BS/2, 0,0,0, c, 1,1), + video::S3DVertex(BS/2,BS/2,BS/2, 0,0,0, c, 1,0), + video::S3DVertex(-BS/2,BS/2,BS/2, 0,0,0, c, 0,0),*/ + video::S3DVertex(-BS/2,-BS/2,BS/2, 0,0,0, c, + pa_leaves1.x0(), pa_leaves1.y1()), + video::S3DVertex(BS/2,-BS/2,BS/2, 0,0,0, c, + pa_leaves1.x1(), pa_leaves1.y1()), + video::S3DVertex(BS/2,BS/2,BS/2, 0,0,0, c, + pa_leaves1.x1(), pa_leaves1.y0()), + video::S3DVertex(-BS/2,BS/2,BS/2, 0,0,0, c, + pa_leaves1.x0(), pa_leaves1.y0()), + }; + + if(j == 0) + { + for(u16 i=0; i<4; i++) + vertices[i].Pos.rotateXZBy(0); + } + else if(j == 1) + { + for(u16 i=0; i<4; i++) + vertices[i].Pos.rotateXZBy(180); + } + else if(j == 2) + { + for(u16 i=0; i<4; i++) + vertices[i].Pos.rotateXZBy(-90); + } + else if(j == 3) + { + for(u16 i=0; i<4; i++) + vertices[i].Pos.rotateXZBy(90); + } + else if(j == 4) + { + for(u16 i=0; i<4; i++) + vertices[i].Pos.rotateYZBy(-90); + } + else if(j == 5) + { + for(u16 i=0; i<4; i++) + vertices[i].Pos.rotateYZBy(90); + } + + 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_leaves1, vertices, 4, indices, 6); + } + } + /* + Add glass + */ + else if(n.d == CONTENT_GLASS) + { + u8 l = decode_light(undiminish_light(n.getLightBlend(data->m_daynight_ratio))); + video::SColor c(255,l,l,l); + + for(u32 j=0; j<6; j++) + { + video::S3DVertex vertices[4] = + { + video::S3DVertex(-BS/2,-BS/2,BS/2, 0,0,0, c, + pa_glass.x0(), pa_glass.y1()), + video::S3DVertex(BS/2,-BS/2,BS/2, 0,0,0, c, + pa_glass.x1(), pa_glass.y1()), + video::S3DVertex(BS/2,BS/2,BS/2, 0,0,0, c, + pa_glass.x1(), pa_glass.y0()), + video::S3DVertex(-BS/2,BS/2,BS/2, 0,0,0, c, + pa_glass.x0(), pa_glass.y0()), + }; + + if(j == 0) + { + for(u16 i=0; i<4; i++) + vertices[i].Pos.rotateXZBy(0); + } + else if(j == 1) + { + for(u16 i=0; i<4; i++) + vertices[i].Pos.rotateXZBy(180); + } + else if(j == 2) + { + for(u16 i=0; i<4; i++) + vertices[i].Pos.rotateXZBy(-90); + } + else if(j == 3) + { + for(u16 i=0; i<4; i++) + vertices[i].Pos.rotateXZBy(90); + } + else if(j == 4) + { + for(u16 i=0; i<4; i++) + vertices[i].Pos.rotateYZBy(-90); + } + else if(j == 5) + { + for(u16 i=0; i<4; i++) + vertices[i].Pos.rotateYZBy(90); + } + + 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_glass, vertices, 4, indices, 6); + } + } + /* + Add fence + */ + else if(n.d == CONTENT_FENCE) + { + u8 l = decode_light(undiminish_light(n.getLightBlend(data->m_daynight_ratio))); + video::SColor c(255,l,l,l); + + const f32 post_rad=(f32)BS/10; + const f32 bar_rad=(f32)BS/20; + const f32 bar_len=(f32)(BS/2)-post_rad; + + // The post - always present + v3f pos = intToFloat(p+blockpos_nodes, BS); + f32 postuv[24]={ + 0.4,0.4,0.6,0.6, + 0.35,0,0.65,1, + 0.35,0,0.65,1, + 0.35,0,0.65,1, + 0.35,0,0.65,1, + 0.4,0.4,0.6,0.6}; + makeCuboid(material_wood, &collector, + &pa_wood, c, pos, + post_rad,BS/2,post_rad, postuv); + + // Now a section of fence, +X, if there's a post there + v3s16 p2 = p; + p2.X++; + MapNode n2 = data->m_vmanip.getNodeNoEx(blockpos_nodes + p2); + if(n2.d == CONTENT_FENCE) + { + pos = intToFloat(p+blockpos_nodes, BS); + pos.X += BS/2; + pos.Y += BS/4; + f32 xrailuv[24]={ + 0,0.4,1,0.6, + 0,0.4,1,0.6, + 0,0.4,1,0.6, + 0,0.4,1,0.6, + 0,0.4,1,0.6, + 0,0.4,1,0.6}; + makeCuboid(material_wood, &collector, + &pa_wood, c, pos, + bar_len,bar_rad,bar_rad, xrailuv); + + pos.Y -= BS/2; + makeCuboid(material_wood, &collector, + &pa_wood, c, pos, + bar_len,bar_rad,bar_rad, xrailuv); + } + + // Now a section of fence, +Z, if there's a post there + p2 = p; + p2.Z++; + n2 = data->m_vmanip.getNodeNoEx(blockpos_nodes + p2); + if(n2.d == CONTENT_FENCE) + { + pos = intToFloat(p+blockpos_nodes, BS); + pos.Z += BS/2; + pos.Y += BS/4; + f32 zrailuv[24]={ + 0,0.4,1,0.6, + 0,0.4,1,0.6, + 0,0.4,1,0.6, + 0,0.4,1,0.6, + 0,0.4,1,0.6, + 0,0.4,1,0.6}; + makeCuboid(material_wood, &collector, + &pa_wood, c, pos, + bar_rad,bar_rad,bar_len, zrailuv); + pos.Y -= BS/2; + makeCuboid(material_wood, &collector, + &pa_wood, c, pos, + bar_rad,bar_rad,bar_len, zrailuv); + + } + + } +#if 1 + /* + Add stones with minerals if stone is invisible + */ + else if(n.d == CONTENT_STONE && invisible_stone && n.getMineral() != MINERAL_NONE) + { + for(u32 j=0; j<6; j++) + { + // NOTE: Hopefully g_6dirs[j] is the right direction... + v3s16 dir = g_6dirs[j]; + /*u8 l = 0; + MapNode n2 = data->m_vmanip.getNodeNoEx(blockpos_nodes + dir); + if(content_features(n2.d).param_type == CPT_LIGHT) + l = decode_light(n2.getLightBlend(data->m_daynight_ratio)); + else + l = 255;*/ + u8 l = 255; + video::SColor c(255,l,l,l); + + // Get the right texture + TileSpec ts = n.getTile(dir); + AtlasPointer ap = ts.texture; + material_general.setTexture(0, ap.atlas); - + video::S3DVertex vertices[4] = - { ++ { + /*video::S3DVertex(-BS/2,-BS/2,BS/2, 0,0,0, c, 0,1), + video::S3DVertex(BS/2,-BS/2,BS/2, 0,0,0, c, 1,1), + video::S3DVertex(BS/2,BS/2,BS/2, 0,0,0, c, 1,0), + video::S3DVertex(-BS/2,BS/2,BS/2, 0,0,0, c, 0,0),*/ + video::S3DVertex(-BS/2,-BS/2,BS/2, 0,0,0, c, + ap.x0(), ap.y1()), + video::S3DVertex(BS/2,-BS/2,BS/2, 0,0,0, c, + ap.x1(), ap.y1()), + video::S3DVertex(BS/2,BS/2,BS/2, 0,0,0, c, + ap.x1(), ap.y0()), + video::S3DVertex(-BS/2,BS/2,BS/2, 0,0,0, c, + ap.x0(), ap.y0()), + }; + + if(j == 0) + { + for(u16 i=0; i<4; i++) + vertices[i].Pos.rotateXZBy(0); + } + else if(j == 1) + { + for(u16 i=0; i<4; i++) + vertices[i].Pos.rotateXZBy(180); + } + else if(j == 2) + { + for(u16 i=0; i<4; i++) + vertices[i].Pos.rotateXZBy(-90); + } + else if(j == 3) + { + for(u16 i=0; i<4; i++) + vertices[i].Pos.rotateXZBy(90); + } + else if(j == 4) ++ ++ 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_general, vertices, 4, indices, 6); ++ } ++ } ++#endif ++ else if(n.d == CONTENT_PAPYRUS) ++ { ++ u8 l = decode_light(undiminish_light(n.getLightBlend(data->m_daynight_ratio))); ++ video::SColor c(255,l,l,l); ++ ++ for(u32 j=0; j<4; j++) ++ { ++ video::S3DVertex vertices[4] = ++ { ++ video::S3DVertex(-BS/2,-BS/2,0, 0,0,0, c, ++ pa_papyrus.x0(), pa_papyrus.y1()), ++ video::S3DVertex(BS/2,-BS/2,0, 0,0,0, c, ++ pa_papyrus.x1(), pa_papyrus.y1()), ++ video::S3DVertex(BS/2,BS/2,0, 0,0,0, c, ++ pa_papyrus.x1(), pa_papyrus.y0()), ++ video::S3DVertex(-BS/2,BS/2,0, 0,0,0, c, ++ pa_papyrus.x0(), pa_papyrus.y0()), ++ }; ++ ++ if(j == 0) + { + for(u16 i=0; i<4; i++) - vertices[i].Pos.rotateYZBy(-90); ++ vertices[i].Pos.rotateXZBy(45); + } - else if(j == 5) ++ else if(j == 1) + { + for(u16 i=0; i<4; i++) - vertices[i].Pos.rotateYZBy(90); ++ 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_general, vertices, 4, indices, 6); ++ collector.append(material_papyrus, vertices, 4, indices, 6); + } + } - #endif ++ 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); ++ } + } +} +#endif + diff --cc src/content_mapnode.cpp index 403fb66d,00000000..2e7a240f mode 100644,000000..100644 --- a/src/content_mapnode.cpp +++ b/src/content_mapnode.cpp @@@ -1,377 -1,0 +1,450 @@@ +/* +Minetest-c55 +Copyright (C) 2010-2011 celeron55, Perttu Ahola + +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. +*/ + +// For g_settings +#include "main.h" + +#include "content_mapnode.h" +#include "mapnode.h" +#include "content_nodemeta.h" + +// TODO: Get rid of these and set up some attributes like toughness, +// fluffyness, and a funciton to calculate time and durability loss +// (and sound? and whatever else) from them +void setStoneLikeDiggingProperties(DiggingPropertiesList &list, float toughness); +void setDirtLikeDiggingProperties(DiggingPropertiesList &list, float toughness); +void setWoodLikeDiggingProperties(DiggingPropertiesList &list, float toughness); + +void content_mapnode_init() +{ + // Read some settings + bool new_style_water = g_settings.getBool("new_style_water"); + bool new_style_leaves = g_settings.getBool("new_style_leaves"); + bool invisible_stone = g_settings.getBool("invisible_stone"); + + u8 i; + ContentFeatures *f = NULL; + + i = CONTENT_STONE; + f = &content_features(i); + f->setAllTextures("stone.png"); + f->setInventoryTextureCube("stone.png", "stone.png", "stone.png"); + f->param_type = CPT_MINERAL; + f->is_ground_content = true; + f->dug_item = std::string("MaterialItem ")+itos(CONTENT_COBBLE)+" 1"; + setStoneLikeDiggingProperties(f->digging_properties, 1.0); + if(invisible_stone) + f->solidness = 0; // For debugging, hides regular stone + + i = CONTENT_GRASS; + f = &content_features(i); + f->setAllTextures("mud.png^grass_side.png"); + f->setTexture(0, "grass.png"); + f->setTexture(1, "mud.png"); + f->param_type = CPT_MINERAL; + f->is_ground_content = true; + f->dug_item = std::string("MaterialItem ")+itos(CONTENT_MUD)+" 1"; + setDirtLikeDiggingProperties(f->digging_properties, 1.0); + + i = CONTENT_GRASS_FOOTSTEPS; + f = &content_features(i); + f->setAllTextures("mud.png^grass_side.png"); + f->setTexture(0, "grass_footsteps.png"); + f->setTexture(1, "mud.png"); + f->param_type = CPT_MINERAL; + f->is_ground_content = true; + f->dug_item = std::string("MaterialItem ")+itos(CONTENT_MUD)+" 1"; + setDirtLikeDiggingProperties(f->digging_properties, 1.0); + + i = CONTENT_MUD; + f = &content_features(i); + f->setAllTextures("mud.png"); + f->setInventoryTextureCube("mud.png", "mud.png", "mud.png"); + f->param_type = CPT_MINERAL; + f->is_ground_content = true; + f->dug_item = std::string("MaterialItem ")+itos(i)+" 1"; + setDirtLikeDiggingProperties(f->digging_properties, 1.0); + + i = CONTENT_SAND; + f = &content_features(i); + f->setAllTextures("sand.png"); + f->setInventoryTextureCube("sand.png", "sand.png", "sand.png"); + f->param_type = CPT_MINERAL; + f->is_ground_content = true; + f->dug_item = std::string("MaterialItem ")+itos(i)+" 1"; + setDirtLikeDiggingProperties(f->digging_properties, 1.0); + + i = CONTENT_GRAVEL; + f = &content_features(i); + f->setAllTextures("gravel.png"); + f->setInventoryTextureCube("gravel.png", "gravel.png", "gravel.png"); + f->param_type = CPT_MINERAL; + f->is_ground_content = true; + f->dug_item = std::string("MaterialItem ")+itos(i)+" 1"; + setDirtLikeDiggingProperties(f->digging_properties, 1.75); + ++ i = CONTENT_SANDSTONE; ++ f = &content_features(i); ++ f->setAllTextures("sandstone.png"); ++ f->setInventoryTextureCube("sandstone.png", "sandstone.png", "sandstone.png"); ++ f->param_type = CPT_MINERAL; ++ f->is_ground_content = true; ++ f->dug_item = std::string("MaterialItem ")+itos(CONTENT_SAND)+" 1"; ++ setDirtLikeDiggingProperties(f->digging_properties, 1.0); ++ ++ i = CONTENT_CLAY; ++ f = &content_features(i); ++ f->setAllTextures("clay.png"); ++ f->setInventoryTextureCube("clay.png", "clay.png", "clay.png"); ++ f->param_type = CPT_MINERAL; ++ f->is_ground_content = true; ++ f->dug_item = std::string("CraftItem lump_of_clay 4"); ++ setDirtLikeDiggingProperties(f->digging_properties, 1.0); ++ ++ i = CONTENT_BRICK; ++ f = &content_features(i); ++ f->setAllTextures("brick.png"); ++ f->setInventoryTextureCube("brick.png", "brick.png", "brick.png"); ++ f->param_type = CPT_MINERAL; ++ f->is_ground_content = true; ++ f->dug_item = std::string("CraftItem clay_brick 4"); ++ setStoneLikeDiggingProperties(f->digging_properties, 1.0); ++ + i = CONTENT_TREE; + f = &content_features(i); + f->setAllTextures("tree.png"); + f->setTexture(0, "tree_top.png"); + f->setTexture(1, "tree_top.png"); + f->param_type = CPT_MINERAL; + f->is_ground_content = true; + f->dug_item = std::string("MaterialItem ")+itos(i)+" 1"; + setWoodLikeDiggingProperties(f->digging_properties, 1.0); + + i = CONTENT_LEAVES; + f = &content_features(i); + f->light_propagates = true; + //f->param_type = CPT_MINERAL; + f->param_type = CPT_LIGHT; + f->is_ground_content = true; + if(new_style_leaves) + { + f->solidness = 0; // drawn separately, makes no faces + f->setInventoryTextureCube("leaves.png", "leaves.png", "leaves.png"); + } + else + { + f->setAllTextures("[noalpha:leaves.png"); + } + f->dug_item = std::string("MaterialItem ")+itos(i)+" 1"; + setWoodLikeDiggingProperties(f->digging_properties, 0.15); + ++ i = CONTENT_CACTUS; ++ f = &content_features(i); ++ f->setAllTextures("cactus_side.png"); ++ f->setTexture(0, "cactus_top.png"); ++ f->setTexture(1, "cactus_top.png"); ++ f->setInventoryTextureCube("cactus_top.png", "cactus_side.png", "cactus_side.png"); ++ f->param_type = CPT_MINERAL; ++ f->is_ground_content = true; ++ f->dug_item = std::string("MaterialItem ")+itos(i)+" 1"; ++ setWoodLikeDiggingProperties(f->digging_properties, 0.75); ++ ++ i = CONTENT_PAPYRUS; ++ f = &content_features(i); ++ f->setInventoryTexture("papyrus.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->walkable = false; ++ setWoodLikeDiggingProperties(f->digging_properties, 0.25); ++ ++ i = CONTENT_BOOKSHELF; ++ f = &content_features(i); ++ f->setAllTextures("bookshelf.png"); ++ f->setTexture(0, "wood.png"); ++ f->setTexture(1, "wood.png"); ++ // FIXME: setInventoryTextureCube() only cares for the first texture ++ f->setInventoryTextureCube("bookshelf.png", "bookshelf.png", "bookshelf.png"); ++ //f->setInventoryTextureCube("wood.png", "bookshelf.png", "bookshelf.png"); ++ f->param_type = CPT_MINERAL; ++ f->is_ground_content = true; ++ setWoodLikeDiggingProperties(f->digging_properties, 0.75); ++ + i = CONTENT_GLASS; + f = &content_features(i); + 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->setInventoryTextureCube("glass.png", "glass.png", "glass.png"); + setWoodLikeDiggingProperties(f->digging_properties, 0.15); + + i = CONTENT_FENCE; + f = &content_features(i); + 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->setInventoryTexture("item_fence.png"); + setWoodLikeDiggingProperties(f->digging_properties, 0.75); + ++ i = CONTENT_RAIL; ++ f = &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; ++ setDirtLikeDiggingProperties(f->digging_properties, 0.75); ++ + // Deprecated + i = CONTENT_COALSTONE; + f = &content_features(i); + //f->translate_to = new MapNode(CONTENT_STONE, MINERAL_COAL); + f->setAllTextures("stone.png^mineral_coal.png"); + f->is_ground_content = true; + setStoneLikeDiggingProperties(f->digging_properties, 1.5); + + i = CONTENT_WOOD; + f = &content_features(i); + f->setAllTextures("wood.png"); + f->setInventoryTextureCube("wood.png", "wood.png", "wood.png"); + f->is_ground_content = true; + f->dug_item = std::string("MaterialItem ")+itos(i)+" 1"; + setWoodLikeDiggingProperties(f->digging_properties, 0.75); + + i = CONTENT_MESE; + f = &content_features(i); + f->setAllTextures("mese.png"); + f->setInventoryTextureCube("mese.png", "mese.png", "mese.png"); + f->is_ground_content = true; + f->dug_item = std::string("MaterialItem ")+itos(i)+" 1"; + setStoneLikeDiggingProperties(f->digging_properties, 0.5); + + i = CONTENT_CLOUD; + f = &content_features(i); + f->setAllTextures("cloud.png"); + f->setInventoryTextureCube("cloud.png", "cloud.png", "cloud.png"); + f->is_ground_content = true; + f->dug_item = std::string("MaterialItem ")+itos(i)+" 1"; + + i = CONTENT_AIR; + f = &content_features(i); + f->param_type = CPT_LIGHT; + f->light_propagates = true; + f->sunlight_propagates = true; + f->solidness = 0; + f->walkable = false; + f->pointable = false; + f->diggable = false; + f->buildable_to = true; + f->air_equivalent = true; + + i = CONTENT_WATER; + f = &content_features(i); + f->setInventoryTextureCube("water.png", "water.png", "water.png"); + f->param_type = CPT_LIGHT; + f->light_propagates = true; + f->solidness = 0; // Drawn separately, makes no faces + f->walkable = false; + f->pointable = false; + f->diggable = false; + f->buildable_to = true; + f->liquid_type = LIQUID_FLOWING; + f->liquid_alternative_flowing = CONTENT_WATER; + + i = CONTENT_WATERSOURCE; + f = &content_features(i); + //f->setInventoryTexture("water.png"); + f->setInventoryTextureCube("water.png", "water.png", "water.png"); + if(new_style_water) + { + f->solidness = 0; // drawn separately, makes no faces + } + else // old style + { + f->solidness = 1; + + TileSpec t; + if(g_texturesource) + t.texture = g_texturesource->getTexture("water.png"); + + t.alpha = WATER_ALPHA; + t.material_type = MATERIAL_ALPHA_VERTEX; + t.material_flags &= ~MATERIAL_FLAG_BACKFACE_CULLING; + f->setAllTiles(t); + } + f->param_type = CPT_LIGHT; + f->light_propagates = true; + f->walkable = false; + f->pointable = false; + f->diggable = false; + f->buildable_to = true; + f->liquid_type = LIQUID_SOURCE; + f->dug_item = std::string("MaterialItem ")+itos(i)+" 1"; + f->liquid_alternative_flowing = CONTENT_WATER; + + i = CONTENT_TORCH; + f = &content_features(i); + f->setInventoryTexture("torch_on_floor.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->wall_mounted = true; + f->air_equivalent = true; + f->dug_item = std::string("MaterialItem ")+itos(i)+" 1"; + f->light_source = LIGHT_MAX-1; + f->digging_properties.set("", DiggingProperties(true, 0.0, 0)); + + i = CONTENT_SIGN_WALL; + f = &content_features(i); + f->setInventoryTexture("sign_wall.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->wall_mounted = true; + f->air_equivalent = true; + f->dug_item = std::string("MaterialItem ")+itos(i)+" 1"; + if(f->initial_metadata == NULL) + f->initial_metadata = new SignNodeMetadata("Some sign"); + f->digging_properties.set("", DiggingProperties(true, 0.5, 0)); + + i = CONTENT_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_front.png"); // Z- + f->setInventoryTexture("chest_top.png"); + //f->setInventoryTextureCube("chest_top.png", "chest_side.png", "chest_side.png"); + f->dug_item = std::string("MaterialItem ")+itos(i)+" 1"; + if(f->initial_metadata == NULL) + f->initial_metadata = new ChestNodeMetadata(); + setWoodLikeDiggingProperties(f->digging_properties, 1.0); + + i = CONTENT_FURNACE; + f = &content_features(i); + f->param_type = CPT_FACEDIR_SIMPLE; + f->setAllTextures("furnace_side.png"); + f->setTexture(5, "furnace_front.png"); // Z- + f->setInventoryTexture("furnace_front.png"); + //f->dug_item = std::string("MaterialItem ")+itos(i)+" 1"; + f->dug_item = std::string("MaterialItem ")+itos(CONTENT_COBBLE)+" 6"; + if(f->initial_metadata == NULL) + f->initial_metadata = new FurnaceNodeMetadata(); + setStoneLikeDiggingProperties(f->digging_properties, 3.0); + + i = CONTENT_COBBLE; + f = &content_features(i); + f->setAllTextures("cobble.png"); + f->setInventoryTextureCube("cobble.png", "cobble.png", "cobble.png"); + f->param_type = CPT_NONE; + f->is_ground_content = true; + f->dug_item = std::string("MaterialItem ")+itos(i)+" 1"; + setStoneLikeDiggingProperties(f->digging_properties, 0.9); + + i = CONTENT_MOSSYCOBBLE; + f = &content_features(i); + f->setAllTextures("mossycobble.png"); + f->setInventoryTextureCube("mossycobble.png", "mossycobble.png", "mossycobble.png"); + f->param_type = CPT_NONE; + f->is_ground_content = true; + f->dug_item = std::string("MaterialItem ")+itos(i)+" 1"; + setStoneLikeDiggingProperties(f->digging_properties, 0.8); + + i = CONTENT_STEEL; + f = &content_features(i); + f->setAllTextures("steel_block.png"); + f->setInventoryTextureCube("steel_block.png", "steel_block.png", + "steel_block.png"); + f->param_type = CPT_NONE; + f->is_ground_content = true; + f->dug_item = std::string("MaterialItem ")+itos(i)+" 1"; + setStoneLikeDiggingProperties(f->digging_properties, 5.0); + + // NOTE: Remember to add frequently used stuff to the texture atlas in tile.cpp + + + /* + Add MesePick to everything + */ + for(u16 i=0; i<256; i++) + { + content_features(i).digging_properties.set("MesePick", + DiggingProperties(true, 0.0, 65535./1337)); + } + +} + +void setStoneLikeDiggingProperties(DiggingPropertiesList &list, float toughness) +{ + list.set("", + DiggingProperties(true, 15.0*toughness, 0)); + + list.set("WPick", + DiggingProperties(true, 1.3*toughness, 65535./30.*toughness)); + list.set("STPick", + DiggingProperties(true, 0.75*toughness, 65535./100.*toughness)); + list.set("SteelPick", + DiggingProperties(true, 0.50*toughness, 65535./333.*toughness)); + + /*list.set("MesePick", + DiggingProperties(true, 0.0*toughness, 65535./20.*toughness));*/ +} + +void setDirtLikeDiggingProperties(DiggingPropertiesList &list, float toughness) +{ + list.set("", + DiggingProperties(true, 0.75*toughness, 0)); + + list.set("WShovel", + DiggingProperties(true, 0.4*toughness, 65535./50.*toughness)); + list.set("STShovel", + DiggingProperties(true, 0.2*toughness, 65535./150.*toughness)); + list.set("SteelShovel", + DiggingProperties(true, 0.15*toughness, 65535./400.*toughness)); +} + +void setWoodLikeDiggingProperties(DiggingPropertiesList &list, float toughness) +{ + list.set("", + DiggingProperties(true, 3.0*toughness, 0)); + + list.set("WAxe", + DiggingProperties(true, 1.5*toughness, 65535./30.*toughness)); + list.set("STAxe", + DiggingProperties(true, 0.75*toughness, 65535./100.*toughness)); + list.set("SteelAxe", + DiggingProperties(true, 0.5*toughness, 65535./333.*toughness)); +} + + diff --cc src/content_mapnode.h index e314807f,00000000..e53624c2 mode 100644,000000..100644 --- a/src/content_mapnode.h +++ b/src/content_mapnode.h @@@ -1,55 -1,0 +1,62 @@@ +/* +Minetest-c55 +Copyright (C) 2010-2011 celeron55, Perttu Ahola + +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 CONTENT_MAPNODE_HEADER +#define CONTENT_MAPNODE_HEADER + +void content_mapnode_init(); + +/* + Node content type IDs +*/ +#define CONTENT_STONE 0 +#define CONTENT_GRASS 1 +#define CONTENT_WATER 2 +#define CONTENT_TORCH 3 +#define CONTENT_TREE 4 +#define CONTENT_LEAVES 5 +#define CONTENT_GRASS_FOOTSTEPS 6 +#define CONTENT_MESE 7 +#define CONTENT_MUD 8 +#define CONTENT_WATERSOURCE 9 +// Pretty much useless, clouds won't be drawn this way +#define CONTENT_CLOUD 10 +#define CONTENT_COALSTONE 11 +#define CONTENT_WOOD 12 +#define CONTENT_SAND 13 +#define CONTENT_SIGN_WALL 14 +#define CONTENT_CHEST 15 +#define CONTENT_FURNACE 16 +//#define CONTENT_WORKBENCH 17 +#define CONTENT_COBBLE 18 +#define CONTENT_STEEL 19 +#define CONTENT_GLASS 20 +#define CONTENT_FENCE 21 +#define CONTENT_MOSSYCOBBLE 22 +#define CONTENT_GRAVEL 23 ++#define CONTENT_SANDSTONE 24 ++#define CONTENT_CACTUS 25 ++#define CONTENT_BRICK 26 ++#define CONTENT_CLAY 27 ++#define CONTENT_PAPYRUS 28 ++#define CONTENT_BOOKSHELF 29 ++#define CONTENT_RAIL 30 + +#endif + diff --cc src/environment.cpp index cd255341,3ebfef0c..e2c70425 --- a/src/environment.cpp +++ b/src/environment.cpp @@@ -579,66 -571,6 +579,66 @@@ void spawnRandomObjects(MapBlock *block } #endif +void ServerEnvironment::activateBlock(MapBlock *block, u32 additional_dtime) +{ + // Get time difference + u32 dtime_s = 0; + u32 stamp = block->getTimestamp(); + if(m_game_time > stamp && stamp != BLOCK_TIMESTAMP_UNDEFINED) + dtime_s = m_game_time - block->getTimestamp(); + dtime_s += additional_dtime; + + // Set current time as timestamp (and let it set ChangedFlag) + block->setTimestamp(m_game_time); + + //dstream<<"Block is "<m_node_metadata.step((float)dtime_s); + if(changed) + { + MapEditEvent event; + event.type = MEET_BLOCK_NODE_METADATA_CHANGED; + event.p = block->getPos(); + m_map->dispatchEvent(&event); + + block->setChangedFlag(); + } + + // TODO: Do something + // TODO: Implement usage of ActiveBlockModifier - ++ + // Here's a quick demonstration + v3s16 p0; + for(p0.X=0; p0.XgetPosRelative(); + MapNode n = block->getNodeNoEx(p0); +#if 1 + // Test something: + // Convert all mud under proper day lighting to grass + if(n.d == CONTENT_MUD) + { + if(dtime_s > 300) + { + MapNode n_top = block->getNodeNoEx(p0+v3s16(0,1,0)); + if(content_features(n_top.d).air_equivalent && + n_top.getLight(LIGHTBANK_DAY) >= 13) + { + n.d = CONTENT_GRASS; + m_map->addNodeWithEvent(p, n); + } + } + } +#endif + } +} + void ServerEnvironment::step(float dtime) { DSTACK(__FUNCTION_NAME); @@@ -754,8 -686,8 +754,8 @@@ MapBlock *block = m_map->getBlockNoCreateNoEx(p); if(block==NULL) continue; -- - // Set current time as timestamp + // Set current time as timestamp (and let it set ChangedFlag) ++ block->setTimestamp(m_game_time); } @@@ -775,8 -707,47 +775,76 @@@ MapBlock *block = m_map->getBlockNoCreateNoEx(p); if(block==NULL) continue; - + - activateBlock(block); + // Get time difference + u32 dtime_s = 0; + u32 stamp = block->getTimestamp(); + if(m_game_time > stamp && stamp != BLOCK_TIMESTAMP_UNDEFINED) + dtime_s = m_game_time - block->getTimestamp(); + - // Set current time as timestamp ++ // Set current time as timestamp (and let it set ChangedFlag) + block->setTimestamp(m_game_time); + + //dstream<<"Block is "<m_node_metadata.step((float)dtime_s); ++ if(changed) ++ { ++ MapEditEvent event; ++ event.type = MEET_BLOCK_NODE_METADATA_CHANGED; ++ event.p = p; ++ m_map->dispatchEvent(&event); ++ ++ block->setChangedFlag(); ++ } ++ + // TODO: Do something - ++ // TODO: Implement usage of ActiveBlockModifier ++ + // Here's a quick demonstration + v3s16 p0; + for(p0.X=0; p0.XgetPosRelative(); + MapNode n = block->getNodeNoEx(p0); + // Test something: + // Convert all mud under proper day lighting to grass + if(n.d == CONTENT_MUD) + { - if(1) ++ if(dtime_s > 300) + { + MapNode n_top = block->getNodeNoEx(p0+v3s16(0,1,0)); + if(content_features(n_top.d).air_equivalent && + n_top.getLight(LIGHTBANK_DAY) >= 13) + { + n.d = CONTENT_GRASS; + m_map->addNodeWithEvent(p, n); + } + } + } ++ /* ++ Convert grass into mud if under something else than air ++ */ ++ else if(n.d == CONTENT_GRASS) ++ { ++ //if(myrand()%20 == 0) ++ { ++ MapNode n_top = block->getNodeNoEx(p0+v3s16(0,1,0)); ++ if(n_top.d != CONTENT_AIR ++ && n_top.d != CONTENT_IGNORE) ++ { ++ n.d = CONTENT_MUD; ++ m_map->addNodeWithEvent(p, n); ++ } ++ } ++ } + } } } @@@ -875,22 -807,6 +943,22 @@@ } } } + /* + Convert grass into mud if under something else than air + */ + else if(n.d == CONTENT_GRASS) + { + //if(myrand()%20 == 0) + { + MapNode n_top = block->getNodeNoEx(p0+v3s16(0,1,0)); + if(n_top.d != CONTENT_AIR + && n_top.d != CONTENT_IGNORE) + { + n.d = CONTENT_MUD; + m_map->addNodeWithEvent(p, n); + } ++ } + } - } } } } diff --cc src/guiMainMenu.h index edd51902,6c028c6e..87561f79 --- a/src/guiMainMenu.h +++ b/src/guiMainMenu.h @@@ -27,21 -27,35 +27,36 @@@ with this program; if not, write to th // For IGameCallback #include "guiPauseMenu.h" + enum + { + GUI_ID_QUIT_BUTTON = 101, + GUI_ID_NAME_INPUT, + GUI_ID_ADDRESS_INPUT, + GUI_ID_PORT_INPUT, + GUI_ID_FANCYTREE_CB, + GUI_ID_SMOOTH_LIGHTING_CB, + GUI_ID_DAMAGE_CB, + GUI_ID_CREATIVE_CB, + GUI_ID_JOIN_GAME_BUTTON, + GUI_ID_CHANGE_KEYS_BUTTON, + GUI_ID_DELETE_MAP_BUTTON + }; + struct MainMenuData { - MainMenuData() : + MainMenuData(): // Client opts - fancy_trees(false), smooth_lighting(false), - // Server opts - creative_mode(false), enable_damage(false), - // Actions - delete_map(false) - { - } + fancy_trees(false), + smooth_lighting(false), + // Server opts + creative_mode(false), + enable_damage(false), + // Actions + delete_map(false) + {} // These are in the native format of the gui elements - + // Client options std::wstring address; std::wstring port; @@@ -87,6 -104,6 +102,11 @@@ private MainMenuData *m_data; bool m_accepted; IGameCallback *m_gamecallback; ++ ++ gui::IGUIEnvironment* env; ++ gui::IGUIElement* parent; ++ s32 id; ++ IMenuManager *menumgr; }; #endif diff --cc src/keycode.cpp index ad3c0b40,99342605..f014914d --- a/src/keycode.cpp +++ b/src/keycode.cpp @@@ -171,9 -170,48 +171,49 @@@ irr::EKEY_CODE keyname_to_keycode(cons return irr::KEY_KEY_CODES_COUNT; } + static const char *KeyNames[] = + { "-", "KEY_LBUTTON", "KEY_RBUTTON", "Cancel", "Middle Button", "X Button 1", + "X Button 2", "-", "Back", "Tab", "-", "-", "Clear", "Return", "-", + "-", "KEY_SHIFT", "Control", "Menu", "Pause", "Capital", "Kana", "-", + "Junja", "Final", "Kanji", "-", "Escape", "Convert", "Nonconvert", + "Accept", "Mode Change", "KEY_SPACE", "Priot", "Next", "KEY_END", + "KEY_HOME", "Left", "Up", "Right", "Down", "Select", "KEY_PRINT", + "Execute", "Snapshot", "Insert", "Delete", "Help", "KEY_KEY_0", + "KEY_KEY_1", "KEY_KEY_2", "KEY_KEY_3", "KEY_KEY_4", "KEY_KEY_5", + "KEY_KEY_6", "KEY_KEY_7", "KEY_KEY_8", "KEY_KEY_9", "-", "-", "-", "-", + "-", "-", "-", "KEY_KEY_A", "KEY_KEY_B", "KEY_KEY_C", "KEY_KEY_D", + "KEY_KEY_E", "KEY_KEY_F", "KEY_KEY_G", "KEY_KEY_H", "KEY_KEY_I", + "KEY_KEY_J", "KEY_KEY_K", "KEY_KEY_L", "KEY_KEY_M", "KEY_KEY_N", + "KEY_KEY_O", "KEY_KEY_P", "KEY_KEY_Q", "KEY_KEY_R", "KEY_KEY_S", + "KEY_KEY_T", "KEY_KEY_U", "KEY_KEY_V", "KEY_KEY_W", "KEY_KEY_X", + "KEY_KEY_Y", "KEY_KEY_Z", "Left Windows", "Right Windows", "Apps", "-", + "Sleep", "KEY_NUMPAD0", "KEY_NUMPAD1", "KEY_NUMPAD2", "KEY_NUMPAD3", + "KEY_NUMPAD4", "KEY_NUMPAD5", "KEY_NUMPAD6", "KEY_NUMPAD7", + "KEY_NUMPAD8", "KEY_NUMPAD9", "Numpad *", "Numpad +", "Numpad /", + "Numpad -", "Numpad .", "Numpad /", "KEY_F1", "KEY_F2", "KEY_F3", + "KEY_F4", "KEY_F5", "KEY_F6", "KEY_F7", "KEY_F8", "KEY_F9", "KEY_F10", + "KEY_F11", "KEY_F12", "KEY_F13", "KEY_F14", "KEY_F15", "KEY_F16", + "KEY_F17", "KEY_F18", "KEY_F19", "KEY_F20", "KEY_F21", "KEY_F22", + "KEY_F23", "KEY_F24", "-", "-", "-", "-", "-", "-", "-", "-", + "Num Lock", "Scroll Lock", "-", "-", "-", "-", "-", "-", "-", "-", "-", + "-", "-", "-", "-", "-", "KEY_LSHIFT", "KEY_RSHIFT", "Left Control", + "Right Control", "Left Menu", "Right Menu", "-", "-", "-", "-", "-", + "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", + "-", "-", "Plus", "Comma", "Minus", "Period", "-", "-", "-", "-", "-", + "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", + "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", + "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", + "-", "-", "-", "-", "-", "-", "-", "-", "Attn", "CrSel", "ExSel", + "Erase OEF", "Play", "Zoom", "PA1", "OEM Clear", "-" }; + + std::string keycode_to_keyname(s32 keycode) + { + return KeyNames[keycode]; + } ++ /* - Key config - */ + Key config +*/ // A simple cache for quicker lookup core::map g_key_setting_cache; @@@ -189,4 -227,8 +229,7 @@@ irr::EKEY_CODE getKeySetting(const cha return c; } - + void clearKeyCache() + { + g_key_setting_cache.clear(); + } - diff --cc src/keycode.h index f19fe344,614f2e58..9c62004d --- a/src/keycode.h +++ b/src/keycode.h @@@ -26,6 -27,7 +27,8 @@@ irr::EKEY_CODE keyname_to_keycode(cons // Key configuration getter irr::EKEY_CODE getKeySetting(const char *settingname); + std::string keycode_to_keyname(s32 keycode); + void clearCache(); + #endif