diff options
-rw-r--r-- | .gitignore | 2 | ||||
-rw-r--r-- | CMakeLists.txt | 4 | ||||
-rw-r--r-- | README | 29 | ||||
-rw-r--r-- | data/book.png | bin | 0 -> 292 bytes | |||
-rw-r--r-- | data/bookshelf.png | bin | 0 -> 597 bytes | |||
-rw-r--r-- | data/brick.png | bin | 0 -> 604 bytes | |||
-rw-r--r-- | data/cactus_side.png | bin | 0 -> 279 bytes | |||
-rw-r--r-- | data/cactus_top.png | bin | 0 -> 236 bytes | |||
-rw-r--r-- | data/clay.png | bin | 0 -> 613 bytes | |||
-rw-r--r-- | data/clay_brick.png | bin | 0 -> 249 bytes | |||
-rw-r--r-- | data/fence.png | bin | 0 -> 539 bytes | |||
-rw-r--r-- | data/glass.png | bin | 1309 -> 381 bytes | |||
-rw-r--r-- | data/lump_of_clay.png | bin | 0 -> 210 bytes | |||
-rw-r--r-- | data/menulogo.png | bin | 498 -> 653 bytes | |||
-rw-r--r-- | data/oerkki1.png | bin | 212 -> 270 bytes | |||
-rw-r--r-- | data/paper.png | bin | 0 -> 242 bytes | |||
-rw-r--r-- | data/papyrus.png | bin | 0 -> 366 bytes | |||
-rw-r--r-- | data/player.png | bin | 212 -> 652 bytes | |||
-rw-r--r-- | data/player_back.png | bin | 201 -> 292 bytes | |||
-rw-r--r-- | data/rail.png | bin | 0 -> 507 bytes | |||
-rw-r--r-- | data/rail_crossing.png | bin | 0 -> 555 bytes | |||
-rw-r--r-- | data/rail_curved.png | bin | 0 -> 545 bytes | |||
-rw-r--r-- | data/rail_t_junction.png | bin | 0 -> 542 bytes | |||
-rw-r--r-- | data/rat.png | bin | 920 -> 276 bytes | |||
-rw-r--r-- | data/sandstone.png | bin | 0 -> 772 bytes | |||
-rwxr-xr-x | genmap.py | 271 | ||||
-rw-r--r-- | heart.png | bin | 0 -> 258 bytes | |||
-rw-r--r-- | minetestmapper/colors.txt | 25 | ||||
-rwxr-xr-x | minetestmapper/minetestmapper2.py | 275 | ||||
-rw-r--r-- | pnoise.py | 102 | ||||
-rw-r--r-- | src/CMakeLists.txt | 1 | ||||
-rw-r--r-- | src/client.cpp | 24 | ||||
-rw-r--r-- | src/content_craft.cpp | 106 | ||||
-rw-r--r-- | src/content_inventory.cpp | 12 | ||||
-rw-r--r-- | src/content_mapblock.cpp | 167 | ||||
-rw-r--r-- | src/content_mapnode.cpp | 73 | ||||
-rw-r--r-- | src/content_mapnode.h | 7 | ||||
-rw-r--r-- | src/environment.cpp | 78 | ||||
-rw-r--r-- | src/game.cpp | 37 | ||||
-rw-r--r-- | src/guiMainMenu.cpp | 71 | ||||
-rw-r--r-- | src/guiMainMenu.h | 20 | ||||
-rw-r--r-- | src/keycode.cpp | 45 | ||||
-rw-r--r-- | src/keycode.h | 3 |
43 files changed, 1308 insertions, 44 deletions
diff --git a/.gitignore b/.gitignore index ce00d585e..f0c372ab7 100644 --- a/.gitignore +++ b/.gitignore @@ -19,4 +19,4 @@ cmake_install.cmake src/jthread/libjthread.a debug.txt bin/debug.txt - +minetestmapper/map.png diff --git a/CMakeLists.txt b/CMakeLists.txt index 516778995..854c4b48d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -59,7 +59,7 @@ elseif(UNIX) # Linux, BSD etc set(EXAMPLE_CONF_DIR "share/doc/minetest") endif() -install(FILES "README.txt" DESTINATION "${DOCDIR}") +install(FILES "doc/README.txt" DESTINATION "${DOCDIR}") install(FILES "minetest.conf.example" DESTINATION "${DOCDIR}") # @@ -104,7 +104,7 @@ elseif(APPLE) set(CPACK_BUNDLE_ICON "") set(CPACK_BUNDLE_PLIST "") set(CPACK_BUNDLE_STARTUP_COMMAND "Contents/MacOS/minetest") - set(CPACK_GENERATOR Bundle) + set(CPACK_GENERATOR "Bundle") else() set(CPACK_PACKAGE_FILE_NAME "${PROJECT_NAME}-${VERSION_STRING}-linux") set(CPACK_GENERATOR TGZ) @@ -0,0 +1,29 @@ +Minetest Δ (“Minetest Delta”) is a fork of Minetest-c55 <http://celeron.55.lt/~celeron55/minetest/>, incorporating experimental features that are not (yet) included in Minetest-c55. + +New features: +* Submenu for key assignment (changes apply after restart) + +New bricks: +* Sandstone (crafted from 4 sand, yields sand) +* Cactus (plant that grows on sand) +* Clay (found in sand at sea level, yields 4 lumps of clay) +* Brick (made from 4 clay bricks, yields 4 clay bricks) +* Papyrus (plant that grows in shallow water, yields paper) +* Book shelf (made from 6 wood and 3 books, sandwhiched) +* Rail (made from 6 iron ingots and 3 sticks, vertically sandwhiched) + +New materials: +* Lump of clay +* Clay brick (made from lumps of clay in the furnace) +* Paper +* Book (made from 3 paper) + +Alternate graphics: +* Player +* Omsk birds (instead of Oerkki ghosts) +* Rat +* Glass + +Building on GNU/Linux or OS X: + cmake . -DRUN_IN_PLACE=1 + make -j2 diff --git a/data/book.png b/data/book.png Binary files differnew file mode 100644 index 000000000..176fb6aa9 --- /dev/null +++ b/data/book.png diff --git a/data/bookshelf.png b/data/bookshelf.png Binary files differnew file mode 100644 index 000000000..5ecc50ff3 --- /dev/null +++ b/data/bookshelf.png diff --git a/data/brick.png b/data/brick.png Binary files differnew file mode 100644 index 000000000..32d77f347 --- /dev/null +++ b/data/brick.png diff --git a/data/cactus_side.png b/data/cactus_side.png Binary files differnew file mode 100644 index 000000000..fc479fde6 --- /dev/null +++ b/data/cactus_side.png diff --git a/data/cactus_top.png b/data/cactus_top.png Binary files differnew file mode 100644 index 000000000..f9e68df51 --- /dev/null +++ b/data/cactus_top.png diff --git a/data/clay.png b/data/clay.png Binary files differnew file mode 100644 index 000000000..3557429d8 --- /dev/null +++ b/data/clay.png diff --git a/data/clay_brick.png b/data/clay_brick.png Binary files differnew file mode 100644 index 000000000..e36648e48 --- /dev/null +++ b/data/clay_brick.png diff --git a/data/fence.png b/data/fence.png Binary files differnew file mode 100644 index 000000000..0b99f0eb5 --- /dev/null +++ b/data/fence.png diff --git a/data/glass.png b/data/glass.png Binary files differindex 8598ce670..35ea596d5 100644 --- a/data/glass.png +++ b/data/glass.png diff --git a/data/lump_of_clay.png b/data/lump_of_clay.png Binary files differnew file mode 100644 index 000000000..be0bab9d7 --- /dev/null +++ b/data/lump_of_clay.png diff --git a/data/menulogo.png b/data/menulogo.png Binary files differindex 76595c48d..cb6983e5c 100644 --- a/data/menulogo.png +++ b/data/menulogo.png diff --git a/data/oerkki1.png b/data/oerkki1.png Binary files differindex c32fb99db..aad2ddb41 100644 --- a/data/oerkki1.png +++ b/data/oerkki1.png diff --git a/data/paper.png b/data/paper.png Binary files differnew file mode 100644 index 000000000..ae5c06bc6 --- /dev/null +++ b/data/paper.png diff --git a/data/papyrus.png b/data/papyrus.png Binary files differnew file mode 100644 index 000000000..bf0dec7fe --- /dev/null +++ b/data/papyrus.png diff --git a/data/player.png b/data/player.png Binary files differindex 90adf9747..60ac4854b 100644 --- a/data/player.png +++ b/data/player.png diff --git a/data/player_back.png b/data/player_back.png Binary files differindex 530aa7519..447c1fd8f 100644 --- a/data/player_back.png +++ b/data/player_back.png diff --git a/data/rail.png b/data/rail.png Binary files differnew file mode 100644 index 000000000..18176d9f3 --- /dev/null +++ b/data/rail.png diff --git a/data/rail_crossing.png b/data/rail_crossing.png Binary files differnew file mode 100644 index 000000000..984640577 --- /dev/null +++ b/data/rail_crossing.png diff --git a/data/rail_curved.png b/data/rail_curved.png Binary files differnew file mode 100644 index 000000000..62afa3d2b --- /dev/null +++ b/data/rail_curved.png diff --git a/data/rail_t_junction.png b/data/rail_t_junction.png Binary files differnew file mode 100644 index 000000000..9985f63cd --- /dev/null +++ b/data/rail_t_junction.png diff --git a/data/rat.png b/data/rat.png Binary files differindex d1a0e2ae2..96d44c3fa 100644 --- a/data/rat.png +++ b/data/rat.png diff --git a/data/sandstone.png b/data/sandstone.png Binary files differnew file mode 100644 index 000000000..c4759b4d0 --- /dev/null +++ b/data/sandstone.png diff --git a/genmap.py b/genmap.py new file mode 100755 index 000000000..a60509403 --- /dev/null +++ b/genmap.py @@ -0,0 +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 + +# 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 +# + +# Seed for generating terrain +SEED = 0 + +# 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 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 + +# 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 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)) + + # 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 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 diff --git a/heart.png b/heart.png Binary files differnew file mode 100644 index 000000000..bea1aefd6 --- /dev/null +++ b/heart.png diff --git a/minetestmapper/colors.txt b/minetestmapper/colors.txt new file mode 100644 index 000000000..e70f56e1e --- /dev/null +++ b/minetestmapper/colors.txt @@ -0,0 +1,25 @@ +0 128 128 128
+1 107 134 51
+2 39 66 106
+3 255 255 0
+4 86 58 31
+5 48 95 8
+6 102 129 38
+7 178 178 0
+8 101 84 36
+9 39 66 106
+12 104 78 42
+13 210 194 156
+14 117 86 41
+15 128 79 0
+16 118 118 118
+18 123 123 123
+19 199 199 199
+20 183 183 222
+21 103 78 42
+22 219 202 178
+23 78 154 6
+24 204 0 0
+25 211 215 207
+26 138 226 52
+27 104 78 42
diff --git a/minetestmapper/minetestmapper2.py b/minetestmapper/minetestmapper2.py new file mode 100755 index 000000000..8dc3de2f4 --- /dev/null +++ b/minetestmapper/minetestmapper2.py @@ -0,0 +1,275 @@ +#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+# Made by j0gge, modified by celeron55
+
+# This program is free software. It comes without any warranty, to
+# the extent permitted by applicable law. You can redistribute it
+# and/or modify it under the terms of the Do What The Fuck You Want
+# To Public License, Version 2, as published by Sam Hocevar. See
+# http://sam.zoy.org/wtfpl/COPYING for more details.
+
+# Requires Python Imaging Library: http://www.pythonware.com/products/pil/
+
+# Some speed-up: ...lol, actually it slows it down.
+#import psyco ; psyco.full()
+#from psyco.classes import *
+
+import zlib
+import Image, ImageDraw
+import os
+import string
+import time
+
+def hex_to_int(h):
+ i = int(h,16)
+ if(i > 2047):
+ i-=4096
+ return i
+
+def hex4_to_int(h):
+ i = int(h,16)
+ if(i > 32767):
+ i-=65536
+ return i
+
+def int_to_hex3(i):
+ if(i < 0):
+ return "%03X" % (i + 4096)
+ else:
+ return "%03X" % i
+
+def int_to_hex4(i):
+ if(i < 0):
+ return "%04X" % (i + 65536)
+ else:
+ return "%04X" % i
+
+def limit(i,l,h):
+ if(i>h):
+ i=h
+ if(i<l):
+ i=l
+ return i
+
+# Fix these!
+path="../map/"
+output="map.png"
+
+sector_xmin = -1000/16
+sector_xmax = 1000/16
+sector_zmin = -1000/16
+sector_zmax = 1000/16
+
+# Load color information for the blocks.
+colors = {}
+f = file("colors.txt")
+for line in f:
+ values = string.split(line)
+ colors[int(values[0])] = (int(values[1]), int(values[2]), int(values[3]))
+f.close()
+
+xlist = []
+zlist = []
+
+# List all sectors to memory and calculate the width and heigth of the resulting picture.
+if os.path.exists(path + "sectors2"):
+ for filename in os.listdir(path + "sectors2"):
+ for filename2 in os.listdir(path + "sectors2/" + filename):
+ x = hex_to_int(filename)
+ z = hex_to_int(filename2)
+ if x < sector_xmin or x > sector_xmax:
+ continue
+ if z < sector_zmin or z > sector_zmax:
+ continue
+ xlist.append(x)
+ zlist.append(z)
+
+if os.path.exists(path + "sectors"):
+ for filename in os.listdir(path + "sectors"):
+ x = hex4_to_int(filename[:4])
+ z = hex4_to_int(filename[-4:])
+ if x < sector_xmin or x > sector_xmax:
+ continue
+ if z < sector_zmin or z > sector_zmax:
+ continue
+ xlist.append(x)
+ zlist.append(z)
+
+w = (max(xlist) - min(xlist)) * 16 + 16
+h = (max(zlist) - min(zlist)) * 16 + 16
+
+print "w="+str(w)+" h="+str(h)
+
+im = Image.new("RGB", (w, h), "white")
+impix = im.load()
+
+stuff={}
+
+starttime = time.time()
+
+# Go through all sectors.
+for n in range(len(xlist)):
+ #if n > 500:
+ # break
+ if n % 200 == 0:
+ nowtime = time.time()
+ dtime = nowtime - starttime
+ n_per_second = 1.0 * n / dtime
+ if n_per_second != 0:
+ seconds_per_n = 1.0 / n_per_second
+ time_guess = seconds_per_n * len(xlist)
+ remaining_s = time_guess - dtime
+ remaining_minutes = int(remaining_s / 60)
+ remaining_s -= remaining_minutes * 60;
+ print("Processing sector "+str(n)+" of "+str(len(xlist))
+ +" ("+str(round(100.0*n/len(xlist), 1))+"%)"
+ +" (ETA: "+str(remaining_minutes)+"m "
+ +str(int(remaining_s))+"s)")
+
+ xpos = xlist[n]
+ zpos = zlist[n]
+
+ xhex = int_to_hex3(xpos)
+ zhex = int_to_hex3(zpos)
+ xhex4 = int_to_hex4(xpos)
+ zhex4 = int_to_hex4(zpos)
+
+ sector1 = xhex4.lower() + zhex4.lower()
+ sector2 = xhex.lower() + "/" + zhex.lower()
+
+ ylist=[]
+
+ sectortype = ""
+
+ try:
+ for filename in os.listdir(path + "sectors/" + sector1):
+ if(filename != "meta"):
+ pos = int(filename,16)
+ if(pos > 32767):
+ pos-=65536
+ ylist.append(pos)
+ sectortype = "old"
+ except OSError:
+ pass
+
+ if sectortype != "old":
+ try:
+ for filename in os.listdir(path + "sectors2/" + sector2):
+ if(filename != "meta"):
+ pos = int(filename,16)
+ if(pos > 32767):
+ pos-=65536
+ ylist.append(pos)
+ sectortype = "new"
+ except OSError:
+ pass
+
+ if sectortype == "":
+ continue
+
+ ylist.sort()
+
+ # Make a list of pixels of the sector that are to be looked for.
+ pixellist = []
+ for x in range(16):
+ for y in range(16):
+ pixellist.append((x,y))
+
+ # Go through the Y axis from top to bottom.
+ for ypos in reversed(ylist):
+
+ yhex = int_to_hex4(ypos)
+
+ filename = ""
+ if sectortype == "old":
+ filename = path + "sectors/" + sector1 + "/" + yhex.lower()
+ else:
+ filename = path + "sectors2/" + sector2 + "/" + yhex.lower()
+
+ f = file(filename, "rb")
+
+ # Let's just memorize these even though it's not really necessary.
+ version = f.read(1)
+ flags = f.read(1)
+
+ dec_o = zlib.decompressobj()
+ try:
+ mapdata = dec_o.decompress(f.read())
+ except:
+ mapdata = []
+
+ f.close()
+
+ if(len(mapdata)<4096):
+ print "bad: " + xhex+zhex+"/"+yhex + " " + len(mapdata)
+ else:
+ chunkxpos=xpos*16
+ chunkypos=ypos*16
+ chunkzpos=zpos*16
+ for (x,z) in reversed(pixellist):
+ for y in reversed(range(16)):
+ datapos=x+y*16+z*256
+ if(ord(mapdata[datapos])!=254):
+ try:
+ pixellist.remove((x,z))
+ # Memorize information on the type and height of the block and for drawing the picture.
+ stuff[(chunkxpos+x,chunkzpos+z)]=(chunkypos+y,ord(mapdata[datapos]))
+ break
+ except:
+ print "strange block: " + xhex+zhex+"/"+yhex + " x: " + str(x) + " y: " + str(y) + " z: " + str(z) + " block: " + str(ord(mapdata[datapos]))
+
+ # After finding all the pixeld in the sector, we can move on to the next sector without having to continue the Y axis.
+ if(len(pixellist)==0):
+ break
+
+print "Drawing image"
+# Drawing the picture
+starttime = time.time()
+n = 0
+minx = min(xlist)
+minz = min(zlist)
+for (x,z) in stuff.iterkeys():
+ if n % 500000 == 0:
+ nowtime = time.time()
+ dtime = nowtime - starttime
+ n_per_second = 1.0 * n / dtime
+ if n_per_second != 0:
+ listlen = len(stuff)
+ seconds_per_n = 1.0 / n_per_second
+ time_guess = seconds_per_n * listlen
+ remaining_s = time_guess - dtime
+ remaining_minutes = int(remaining_s / 60)
+ remaining_s -= remaining_minutes * 60;
+ print("Drawing pixel "+str(n)+" of "+str(listlen)
+ +" ("+str(round(100.0*n/listlen, 1))+"%)"
+ +" (ETA: "+str(remaining_minutes)+"m "
+ +str(int(remaining_s))+"s)")
+ n += 1
+
+ (r,g,b)=colors[stuff[(x,z)][1]]
+
+ # Comparing heights of a couple of adjacent blocks and changing brightness accordingly.
+ try:
+ y1=stuff[(x-1,z)][0]
+ y2=stuff[(x,z-1)][0]
+ y=stuff[(x,z)][0]
+
+ d=(y-y1+y-y2)*12
+
+ if(d>36):
+ d=36
+
+ r=limit(r+d,0,255)
+ g=limit(g+d,0,255)
+ b=limit(b+d,0,255)
+ except:
+ pass
+ #impix[w-1-(x-minx*16),h-1-(z-minz*16)]=(r,g,b)
+ impix[x-minx*16,h-1-(z-minz*16)]=(r,g,b)
+
+# Flip the picture to make it right and save.
+#print "Transposing"
+#im=im.transpose(Image.FLIP_TOP_BOTTOM)
+print "Saving"
+im.save(output)
diff --git a/pnoise.py b/pnoise.py new file mode 100644 index 000000000..fcab5ac15 --- /dev/null +++ b/pnoise.py @@ -0,0 +1,102 @@ +# +# A python perlin noise implementation, from +# http://www.fundza.com/c4serious/noise/perlin/perlin.html +# +# This is used for testing how to create maps with a python script. +# + +import math +p = ( +151,160,137,91,90,15,131,13,201,95,96,53,194,233,7,225,140,36,103, +30,69,142,8,99,37,240,21,10,23,190,6,148,247,120,234,75,0,26,197, +62,94,252,219,203,117,35,11,32,57,177,33,88,237,149,56,87,174,20, +125,136,171,168,68,175,74,165,71,134,139,48,27,166,77,146,158,231, +83,111,229,122,60,211,133,230,220,105,92,41,55,46,245,40,244,102, +143,54,65,25,63,161,1,216,80,73,209,76,132,187,208,89,18,169,200, +196,135,130,116,188,159,86,164,100,109,198,173,186,3,64,52,217,226, +250,124,123,5,202,38,147,118,126,255,82,85,212,207,206,59,227,47,16, +58,17,182,189,28,42,223,183,170,213,119,248,152,2,44,154,163,70, +221,153,101,155,167,43,172,9,129,22,39,253,19,98,108,110,79,113, +224,232,178,185,112,104,218,246,97,228,251,34,242,193,238,210,144, +12,191,179,162,241,81,51,145,235,249,14,239,107,49,192,214,31,181, +199,106,157,184,84,204,176,115,121,50,45,127,4,150,254,138,236, +205,93,222,114,67,29,24,72,243,141,128,195,78,66,215,61,156,180, +151,160,137,91,90,15,131,13,201,95,96,53,194,233,7,225,140,36,103, +30,69,142,8,99,37,240,21,10,23,190,6,148,247,120,234,75,0,26,197, +62,94,252,219,203,117,35,11,32,57,177,33,88,237,149,56,87,174,20, +125,136,171,168,68,175,74,165,71,134,139,48,27,166,77,146,158,231, +83,111,229,122,60,211,133,230,220,105,92,41,55,46,245,40,244,102, +143,54,65,25,63,161,1,216,80,73,209,76,132,187,208,89,18,169,200, +196,135,130,116,188,159,86,164,100,109,198,173,186,3,64,52,217,226, +250,124,123,5,202,38,147,118,126,255,82,85,212,207,206,59,227,47,16, +58,17,182,189,28,42,223,183,170,213,119,248,152,2,44,154,163,70, +221,153,101,155,167,43,172,9,129,22,39,253,19,98,108,110,79,113, +224,232,178,185,112,104,218,246,97,228,251,34,242,193,238,210,144, +12,191,179,162,241,81,51,145,235,249,14,239,107,49,192,214,31,181, +199,106,157,184,84,204,176,115,121,50,45,127,4,150,254,138,236, +205,93,222,114,67,29,24,72,243,141,128,195,78,66,215,61,156,180) + +def lerp(t, a, b): + return a + t * (b - a) + +def fade(t): + return t * t * t * (t * (t * 6 - 15) + 10) + +def grad(hash, x, y, z): + h = hash & 15 + if h < 8: + u = x + else: + u = y + if h < 4: + v = y + elif h == 12 or h == 14: + v = x + else: + v = z + if h & 1 != 0: + u = -u + if h & 2 != 0: + v = -v + return u + v + +def pnoise(x, y, z): + global p + X = int(math.floor(x)) & 255 + Y = int(math.floor(y)) & 255 + Z = int(math.floor(z)) & 255 + x -= math.floor(x) + y -= math.floor(y) + z -= math.floor(z) + + u = fade(x) + v = fade(y) + w = fade(z) + + A = p[X] + Y + AA = p[A] + Z + AB = p[A + 1] + Z + B = p[X + 1] + Y + BA = p[B] + Z + BB = p[B + 1] + Z + + pAA = p[AA] + pAB = p[AB] + pBA = p[BA] + pBB = p[BB] + pAA1 = p[AA + 1] + pBA1 = p[BA + 1] + pAB1 = p[AB + 1] + pBB1 = p[BB + 1] + + gradAA = grad(pAA, x, y, z) + gradBA = grad(pBA, x-1, y, z) + gradAB = grad(pAB, x, y-1, z) + gradBB = grad(pBB, x-1, y-1, z) + gradAA1 = grad(pAA1,x, y, z-1) + gradBA1 = grad(pBA1,x-1, y, z-1) + gradAB1 = grad(pAB1,x, y-1, z-1) + gradBB1 = grad(pBB1,x-1, y-1, z-1) + return lerp(w, + lerp(v, lerp(u, gradAA, gradBA), lerp(u, gradAB, gradBB)), + lerp(v, lerp(u, gradAA1,gradBA1),lerp(u, gradAB1,gradBB1))) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 73a960ecc..f62a8626b 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -108,6 +108,7 @@ set(minetest_SRCS clouds.cpp clientobject.cpp guiMainMenu.cpp + guiKeyChangeMenu.cpp guiMessageMenu.cpp guiTextInputMenu.cpp guiInventoryMenu.cpp diff --git a/src/client.cpp b/src/client.cpp index abc056505..e86b3a4f8 100644 --- a/src/client.cpp +++ b/src/client.cpp @@ -722,6 +722,7 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id) */ //dstream<<"Updating"<<std::endl; block->deSerialize(istr, ser_version); + //block->setChangedFlag(); } catch(InvalidPositionException &e) { @@ -732,6 +733,7 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id) block = new MapBlock(&m_env.getMap(), p); block->deSerialize(istr, ser_version); sector->insertBlock(block); + //block->setChangedFlag(); //DEBUG /*NodeMod mod; @@ -742,6 +744,27 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id) block->setTempMod(v3s16(8,8,8), mod); block->setTempMod(v3s16(8,7,8), mod); block->setTempMod(v3s16(8,6,8), mod);*/ +#if 0 + /* + Add some coulds + Well, this is a dumb way to do it, they should just + be drawn as separate objects. But the looks of them + can be tested this way. + */ + if(p.Y == 3) + { + NodeMod mod; + mod.type = NODEMOD_CHANGECONTENT; + mod.param = CONTENT_CLOUD; + v3s16 p2; + p2.Y = 8; + for(p2.X=3; p2.X<=13; p2.X++) + for(p2.Z=3; p2.Z<=13; p2.Z++) + { + block->setTempMod(p2, mod); + } + } +#endif } } //envlock @@ -772,7 +795,6 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id) */ //m_env.getClientMap().updateMeshes(block->getPos(), getDayNightRatio()); - /* Add it to mesh update queue and set it to be acknowledged after update. */ diff --git a/src/content_craft.cpp b/src/content_craft.cpp index 32d2e6d48..069e68300 100644 --- a/src/content_craft.cpp +++ b/src/content_craft.cpp @@ -261,6 +261,24 @@ InventoryItem *craft_get_result(InventoryItem **items) } } + // 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]; @@ -313,6 +331,87 @@ InventoryItem *craft_get_result(InventoryItem **items) } } + // 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; } @@ -353,10 +452,17 @@ void craft_set_creative_inventory(Player *player) 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, diff --git a/src/content_inventory.cpp b/src/content_inventory.cpp index 3b72b31f1..357c8ef26 100644 --- a/src/content_inventory.cpp +++ b/src/content_inventory.cpp @@ -48,12 +48,20 @@ 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 @@ -82,7 +90,7 @@ s16 item_craft_get_drop_count(const std::string &subname) 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; @@ -92,6 +100,8 @@ 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 --git a/src/content_mapblock.cpp b/src/content_mapblock.cpp index bc701aadf..9ef0599d1 100644 --- a/src/content_mapblock.cpp +++ b/src/content_mapblock.cpp @@ -188,6 +188,16 @@ void mapblock_mesh_generate_special(MeshMakeData *data, 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++) @@ -857,9 +867,8 @@ void mapblock_mesh_generate_special(MeshMakeData *data, 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), @@ -895,14 +904,56 @@ void mapblock_mesh_generate_special(MeshMakeData *data, 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++) @@ -912,11 +963,113 @@ void mapblock_mesh_generate_special(MeshMakeData *data, 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 --git a/src/content_mapnode.cpp b/src/content_mapnode.cpp index 403fb66d3..2e7a240f3 100644 --- a/src/content_mapnode.cpp +++ b/src/content_mapnode.cpp @@ -99,6 +99,33 @@ void content_mapnode_init() 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"); @@ -127,6 +154,40 @@ void content_mapnode_init() 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; @@ -148,6 +209,18 @@ void content_mapnode_init() 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); diff --git a/src/content_mapnode.h b/src/content_mapnode.h index e314807f9..e53624c21 100644 --- a/src/content_mapnode.h +++ b/src/content_mapnode.h @@ -50,6 +50,13 @@ void content_mapnode_init(); #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 --git a/src/environment.cpp b/src/environment.cpp index cd255341f..e2c704259 100644 --- a/src/environment.cpp +++ b/src/environment.cpp @@ -592,7 +592,7 @@ void ServerEnvironment::activateBlock(MapBlock *block, u32 additional_dtime) block->setTimestamp(m_game_time); //dstream<<"Block is "<<dtime_s<<" seconds old."<<std::endl; - + // Activate stored objects activateObjects(block); @@ -610,7 +610,7 @@ void ServerEnvironment::activateBlock(MapBlock *block, u32 additional_dtime) // 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++) @@ -754,8 +754,8 @@ void ServerEnvironment::step(float dtime) MapBlock *block = m_map->getBlockNoCreateNoEx(p); if(block==NULL) continue; - // Set current time as timestamp (and let it set ChangedFlag) + block->setTimestamp(m_game_time); } @@ -776,7 +776,75 @@ void ServerEnvironment::step(float dtime) 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 (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(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); + } + } + } + } } } @@ -889,8 +957,8 @@ void ServerEnvironment::step(float dtime) n.d = CONTENT_MUD; m_map->addNodeWithEvent(p, n); } + } } - } } } } diff --git a/src/game.cpp b/src/game.cpp index f3fac0c84..5632c1805 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -534,6 +534,43 @@ void getPointedNode(Client *client, v3f player_position, } } } + else if(n.d == CONTENT_RAIL) + { + v3s16 dir = unpackDir(n.dir); + v3f dir_f = v3f(dir.X, dir.Y, dir.Z); + dir_f *= BS/2 - BS/6 - BS/20; + v3f cpf = npf + dir_f; + f32 distance = (cpf - camera_position).getLength(); + + float d = (float)BS/16; + v3f vertices[4] = + { + v3f(BS/2, -BS/2+d, -BS/2), + v3f(-BS/2, -BS/2, BS/2), + }; + + for(s32 i=0; i<2; i++) + { + vertices[i] += npf; + } + + core::aabbox3d<f32> box; + + box = core::aabbox3d<f32>(vertices[0]); + box.addInternalPoint(vertices[1]); + + if(distance < mindistance) + { + if(box.intersectsWithLine(shootline)) + { + nodefound = true; + nodepos = np; + neighbourpos = np; + mindistance = distance; + nodehilightbox = box; + } + } + } /* Regular blocks */ diff --git a/src/guiMainMenu.cpp b/src/guiMainMenu.cpp index ef0a013f1..cea32860b 100644 --- a/src/guiMainMenu.cpp +++ b/src/guiMainMenu.cpp @@ -18,10 +18,13 @@ with this program; if not, write to the Free Software Foundation, Inc., */ #include "guiMainMenu.h" +#include "guiKeyChangeMenu.h" #include "debug.h" #include "serialization.h" #include <string> + + GUIMainMenu::GUIMainMenu(gui::IGUIEnvironment* env, gui::IGUIElement* parent, s32 id, IMenuManager *menumgr, @@ -34,6 +37,10 @@ GUIMainMenu::GUIMainMenu(gui::IGUIEnvironment* env, m_gamecallback(gamecallback) { assert(m_data); + this->env = env; + this->parent = parent; + this->id = id; + this->menumgr = menumgr; } GUIMainMenu::~GUIMainMenu() @@ -70,35 +77,35 @@ void GUIMainMenu::regenerateGui(v2u32 screensize) // Client options { - gui::IGUIElement *e = getElementFromId(258); + gui::IGUIElement *e = getElementFromId(GUI_ID_NAME_INPUT); if(e != NULL) text_name = e->getText(); else text_name = m_data->name; } { - gui::IGUIElement *e = getElementFromId(256); + gui::IGUIElement *e = getElementFromId(GUI_ID_ADDRESS_INPUT); if(e != NULL) text_address = e->getText(); else text_address = m_data->address; } { - gui::IGUIElement *e = getElementFromId(257); + gui::IGUIElement *e = getElementFromId(GUI_ID_PORT_INPUT); if(e != NULL) text_port = e->getText(); else text_port = m_data->port; } { - gui::IGUIElement *e = getElementFromId(263); + gui::IGUIElement *e = getElementFromId(GUI_ID_FANCYTREE_CB); if(e != NULL && e->getType() == gui::EGUIET_CHECK_BOX) fancy_trees = ((gui::IGUICheckBox*)e)->isChecked(); else fancy_trees = m_data->fancy_trees; } { - gui::IGUIElement *e = getElementFromId(262); + gui::IGUIElement *e = getElementFromId(GUI_ID_SMOOTH_LIGHTING_CB); if(e != NULL && e->getType() == gui::EGUIET_CHECK_BOX) smooth_lighting = ((gui::IGUICheckBox*)e)->isChecked(); else @@ -107,14 +114,14 @@ void GUIMainMenu::regenerateGui(v2u32 screensize) // Server options { - gui::IGUIElement *e = getElementFromId(259); + gui::IGUIElement *e = getElementFromId(GUI_ID_CREATIVE_CB); if(e != NULL && e->getType() == gui::EGUIET_CHECK_BOX) creative_mode = ((gui::IGUICheckBox*)e)->isChecked(); else creative_mode = m_data->creative_mode; } { - gui::IGUIElement *e = getElementFromId(261); + gui::IGUIElement *e = getElementFromId(GUI_ID_DAMAGE_CB); if(e != NULL && e->getType() == gui::EGUIET_CHECK_BOX) enable_damage = ((gui::IGUICheckBox*)e)->isChecked(); else @@ -175,7 +182,7 @@ void GUIMainMenu::regenerateGui(v2u32 screensize) core::rect<s32> rect(0, 0, 230, 30); rect += topleft_client + v2s32(160, 50); gui::IGUIElement *e = - Environment->addEditBox(text_name.c_str(), rect, true, this, 258); + Environment->addEditBox(text_name.c_str(), rect, true, this, GUI_ID_NAME_INPUT); if(text_name == L"") Environment->setFocus(e); } @@ -198,7 +205,7 @@ void GUIMainMenu::regenerateGui(v2u32 screensize) core::rect<s32> rect(0, 0, 230, 30); rect += topleft_client + v2s32(160, 100); gui::IGUIElement *e = - Environment->addEditBox(text_address.c_str(), rect, true, this, 256); + Environment->addEditBox(text_address.c_str(), rect, true, this, GUI_ID_ADDRESS_INPUT); if(text_name != L"") Environment->setFocus(e); } @@ -206,7 +213,7 @@ void GUIMainMenu::regenerateGui(v2u32 screensize) core::rect<s32> rect(0, 0, 120, 30); //rect += topleft_client + v2s32(160+250+20, 125); rect += topleft_client + v2s32(size_client.X-60-100, 100); - Environment->addEditBox(text_port.c_str(), rect, true, this, 257); + Environment->addEditBox(text_port.c_str(), rect, true, this, GUI_ID_PORT_INPUT); } { core::rect<s32> rect(0, 0, 400, 20); @@ -217,13 +224,13 @@ void GUIMainMenu::regenerateGui(v2u32 screensize) { core::rect<s32> rect(0, 0, 250, 30); rect += topleft_client + v2s32(35, 150); - Environment->addCheckBox(fancy_trees, rect, this, 263, + Environment->addCheckBox(fancy_trees, rect, this, GUI_ID_FANCYTREE_CB, L"Fancy trees"); } { core::rect<s32> rect(0, 0, 250, 30); rect += topleft_client + v2s32(35, 150+30); - Environment->addCheckBox(smooth_lighting, rect, this, 262, + Environment->addCheckBox(smooth_lighting, rect, this, GUI_ID_SMOOTH_LIGHTING_CB, L"Smooth Lighting"); } // Start game button @@ -231,9 +238,16 @@ void GUIMainMenu::regenerateGui(v2u32 screensize) core::rect<s32> rect(0, 0, 180, 30); //rect += topleft_client + v2s32(size_client.X/2-180/2, 225-30/2); rect += topleft_client + v2s32(size_client.X-180-40, 150+25); - Environment->addButton(rect, this, 257, L"Start Game / Connect"); + Environment->addButton(rect, this, GUI_ID_JOIN_GAME_BUTTON, L"Start Game / Connect"); } + // Key change button + { + core::rect<s32> rect(0, 0, 100, 30); + //rect += topleft_client + v2s32(size_client.X/2-180/2, 225-30/2); + rect += topleft_client + v2s32(size_client.X-180-40-100-20, 150+25); + Environment->addButton(rect, this, GUI_ID_CHANGE_KEYS_BUTTON, L"Change keys"); + } /* Server section */ @@ -254,19 +268,19 @@ void GUIMainMenu::regenerateGui(v2u32 screensize) { core::rect<s32> rect(0, 0, 250, 30); rect += topleft_server + v2s32(35, 30); - Environment->addCheckBox(creative_mode, rect, this, 259, L"Creative Mode"); + Environment->addCheckBox(creative_mode, rect, this, GUI_ID_CREATIVE_CB, L"Creative Mode"); } { core::rect<s32> rect(0, 0, 250, 30); rect += topleft_server + v2s32(35, 60); - Environment->addCheckBox(enable_damage, rect, this, 261, L"Enable Damage"); + Environment->addCheckBox(enable_damage, rect, this, GUI_ID_DAMAGE_CB, L"Enable Damage"); } // Map delete button { core::rect<s32> rect(0, 0, 130, 30); //rect += topleft_server + v2s32(size_server.X-40-130, 100+25); rect += topleft_server + v2s32(40, 100+25); - Environment->addButton(rect, this, 260, L"Delete world"); + Environment->addButton(rect, this, GUI_ID_DELETE_MAP_BUTTON, L"Delete map"); } } @@ -300,7 +314,7 @@ void GUIMainMenu::drawMenu() void GUIMainMenu::acceptInput() { { - gui::IGUIElement *e = getElementFromId(258); + gui::IGUIElement *e = getElementFromId(GUI_ID_NAME_INPUT); if(e != NULL) m_data->name = e->getText(); } @@ -310,32 +324,32 @@ void GUIMainMenu::acceptInput() m_data->password = e->getText(); } { - gui::IGUIElement *e = getElementFromId(256); + gui::IGUIElement *e = getElementFromId(GUI_ID_ADDRESS_INPUT); if(e != NULL) m_data->address = e->getText(); } { - gui::IGUIElement *e = getElementFromId(257); + gui::IGUIElement *e = getElementFromId(GUI_ID_PORT_INPUT); if(e != NULL) m_data->port = e->getText(); } { - gui::IGUIElement *e = getElementFromId(259); + gui::IGUIElement *e = getElementFromId(GUI_ID_CREATIVE_CB); if(e != NULL && e->getType() == gui::EGUIET_CHECK_BOX) m_data->creative_mode = ((gui::IGUICheckBox*)e)->isChecked(); } { - gui::IGUIElement *e = getElementFromId(261); + gui::IGUIElement *e = getElementFromId(GUI_ID_DAMAGE_CB); if(e != NULL && e->getType() == gui::EGUIET_CHECK_BOX) m_data->enable_damage = ((gui::IGUICheckBox*)e)->isChecked(); } { - gui::IGUIElement *e = getElementFromId(262); + gui::IGUIElement *e = getElementFromId(GUI_ID_SMOOTH_LIGHTING_CB); if(e != NULL && e->getType() == gui::EGUIET_CHECK_BOX) m_data->smooth_lighting = ((gui::IGUICheckBox*)e)->isChecked(); } { - gui::IGUIElement *e = getElementFromId(263); + gui::IGUIElement *e = getElementFromId(GUI_ID_FANCYTREE_CB); if(e != NULL && e->getType() == gui::EGUIET_CHECK_BOX) m_data->fancy_trees = ((gui::IGUICheckBox*)e)->isChecked(); } @@ -377,11 +391,16 @@ bool GUIMainMenu::OnEvent(const SEvent& event) { switch(event.GUIEvent.Caller->getID()) { - case 257: // Start game + case GUI_ID_JOIN_GAME_BUTTON: // Start game acceptInput(); quitMenu(); return true; - case 260: // Delete map + case GUI_ID_CHANGE_KEYS_BUTTON: { + GUIKeyChangeMenu *kmenu = new GUIKeyChangeMenu(env, parent, -1,menumgr); + kmenu->drop(); + return true; + } + case GUI_ID_DELETE_MAP_BUTTON: // Delete map // Don't accept input data, just set deletion request m_data->delete_map = true; m_accepted = true; @@ -393,7 +412,7 @@ bool GUIMainMenu::OnEvent(const SEvent& event) { switch(event.GUIEvent.Caller->getID()) { - case 256: case 257: case 258: case 264: + case GUI_ID_ADDRESS_INPUT: case GUI_ID_PORT_INPUT: case GUI_ID_NAME_INPUT: case 264: acceptInput(); quitMenu(); return true; diff --git a/src/guiMainMenu.h b/src/guiMainMenu.h index edd519024..87561f797 100644 --- a/src/guiMainMenu.h +++ b/src/guiMainMenu.h @@ -27,6 +27,21 @@ with this program; if not, write to the Free Software Foundation, Inc., // 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(): @@ -87,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 --git a/src/keycode.cpp b/src/keycode.cpp index ad3c0b401..f014914d0 100644 --- a/src/keycode.cpp +++ b/src/keycode.cpp @@ -171,6 +171,46 @@ irr::EKEY_CODE keyname_to_keycode(const char *name) 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 */ @@ -189,4 +229,7 @@ irr::EKEY_CODE getKeySetting(const char *settingname) return c; } - +void clearKeyCache() +{ + g_key_setting_cache.clear(); +} diff --git a/src/keycode.h b/src/keycode.h index f19fe3442..9c62004d8 100644 --- a/src/keycode.h +++ b/src/keycode.h @@ -21,11 +21,14 @@ with this program; if not, write to the Free Software Foundation, Inc., #define KEYCODE_HEADER #include "common_irrlicht.h" +#include <string> irr::EKEY_CODE keyname_to_keycode(const char *name); // Key configuration getter irr::EKEY_CODE getKeySetting(const char *settingname); +std::string keycode_to_keyname(s32 keycode); +void clearCache(); #endif |