cmake_install.cmake
src/jthread/libjthread.a
debug.txt
-
+bin/debug.txt
+ minetestmapper/map.png
--- /dev/null
-"""
-Map format:
-map/sectors/XXXXZZZZ/YYYY
+ #!/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
+
-XXXX,YYYY,ZZZZ = coordinates in hexadecimal
++# 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
++#
+
-fffe = -2
-ffff = -1
-0000 = 0
-0001 = 1
-"""
++# Seed for generating terrain
++SEED = 0
+
-def getrand():
++# 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 writeblock(mapdir, px,py,pz, version):
- sectordir = mapdir + "/sectors/" + to4h(px) + to4h(pz)
++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
+
- 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))
++# 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")
+
- 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))
++ 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))
+
-mapdir = "map"
++ # 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()
+
-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)
++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
+
++ # Write it on disk
++ writeblock(mapdir, x0,y0,z0, block)
+
+ #END
keycode.cpp
clouds.cpp
clientobject.cpp
- guiFurnaceMenu.cpp
guiMainMenu.cpp
+ guiKeyChangeMenu.cpp
guiMessageMenu.cpp
guiTextInputMenu.cpp
guiInventoryMenu.cpp
*/
//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)
--- /dev/null
+/*
+Minetest-c55
+Copyright (C) 2010-2011 celeron55, Perttu Ahola <celeron55@gmail.com>
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along
+with this program; if not, write to the Free Software Foundation, Inc.,
+51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#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; i<PLAYER_INVENTORY_SIZE; i++)
+ {
+ if(*mip == CONTENT_IGNORE)
+ break;
+
+ InventoryItem *item = new MaterialItem(*mip, 1);
+ player->inventory.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; i<USEFUL_CONTENT_COUNT; i++)
+ {
+ // Skip some materials
+ if(i == CONTENT_WATER || i == CONTENT_TORCH
+ || i == CONTENT_COALSTONE)
+ continue;
+
+ InventoryItem *item = new MaterialItem(i, 1);
+ player->inventory.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);
+ }*/
+}
+
--- /dev/null
- if(subname == "lump_of_iron")
+/*
+Minetest-c55
+Copyright (C) 2010-2011 celeron55, Perttu Ahola <celeron55@gmail.com>
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along
+with this program; if not, write to the Free Software Foundation, Inc.,
+51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#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" || 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;
+}
+
--- /dev/null
-
+/*
+Minetest-c55
+Copyright (C) 2010-2011 celeron55, Perttu Ahola <celeron55@gmail.com>
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along
+with this program; if not, write to the Free Software Foundation, Inc.,
+51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#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; z<MAP_BLOCKSIZE; z++)
+ for(s16 y=0; y<MAP_BLOCKSIZE; y++)
+ for(s16 x=0; x<MAP_BLOCKSIZE; x++)
+ {
+ v3s16 p(x,y,z);
+
+ MapNode n = data->m_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<v3s16, f32> neighbor_levels;
+ core::map<v3s16, u8> neighbor_contents;
+ core::map<v3s16, u8> 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] =
- vertices[i].Pos.rotateYZBy(-90);
++ {
+ /*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++)
- else if(j == 5)
++ vertices[i].Pos.rotateXZBy(45);
+ }
- vertices[i].Pos.rotateYZBy(90);
++ else if(j == 1)
+ {
+ for(u16 i=0; i<4; i++)
- collector.append(material_general, vertices, 4, indices, 6);
++ 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
- #endif
++ 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);
++ }
+ }
+}
+#endif
+
--- /dev/null
+/*
+Minetest-c55
+Copyright (C) 2010-2011 celeron55, Perttu Ahola <celeron55@gmail.com>
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along
+with this program; if not, write to the Free Software Foundation, Inc.,
+51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+// 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));
+}
+
+
--- /dev/null
+/*
+Minetest-c55
+Copyright (C) 2010-2011 celeron55, Perttu Ahola <celeron55@gmail.com>
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along
+with this program; if not, write to the Free Software Foundation, Inc.,
+51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#ifndef 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
+
}
#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 "<<dtime_s<<" seconds old."<<std::endl;
-
++
+ // Activate stored objects
+ activateObjects(block);
+
+ // Run node metadata
+ bool changed = block->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.X<MAP_BLOCKSIZE; p0.X++)
+ for(p0.Y=0; p0.Y<MAP_BLOCKSIZE; p0.Y++)
+ for(p0.Z=0; p0.Z<MAP_BLOCKSIZE; p0.Z++)
+ {
+ v3s16 p = p0 + block->getPosRelative();
+ 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);
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);
}
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 "<<dtime_s<<" seconds old."<<std::endl;
-
++
+ // Activate stored objects
+ activateObjects(block);
+
++ // Run node metadata
++ bool changed = block->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.X<MAP_BLOCKSIZE; p0.X++)
+ for(p0.Y=0; p0.Y<MAP_BLOCKSIZE; p0.Y++)
+ for(p0.Z=0; p0.Z<MAP_BLOCKSIZE; p0.Z++)
+ {
+ v3s16 p = p0 + block->getPosRelative();
+ 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);
++ }
++ }
++ }
+ }
}
}
}
}
}
- }
+ /*
+ 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);
+ }
++ }
+ }
}
}
}
// 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;
MainMenuData *m_data;
bool m_accepted;
IGameCallback *m_gamecallback;
++
++ gui::IGUIEnvironment* env;
++ gui::IGUIElement* parent;
++ s32 id;
++ IMenuManager *menumgr;
};
#endif
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<std::string, irr::EKEY_CODE> g_key_setting_cache;
return c;
}
-
+ void clearKeyCache()
+ {
+ g_key_setting_cache.clear();
+ }
-
// Key configuration getter
irr::EKEY_CODE getKeySetting(const char *settingname);
+ std::string keycode_to_keyname(s32 keycode);
+ void clearCache();
+
#endif