Merge branch 'master' of git://github.com/celeron55/minetest

Conflicts:
	src/game.cpp
This commit is contained in:
jachoo 2011-11-19 05:32:08 +01:00
commit 21fa08bba3
24 changed files with 675 additions and 515 deletions

View File

@ -10,7 +10,7 @@ project(minetest)
# Also remember to set PROTOCOL_VERSION in clientserver.h when releasing
set(VERSION_MAJOR 0)
set(VERSION_MINOR 3)
set(VERSION_PATCH dev-20111021)
set(VERSION_PATCH 1)
set(VERSION_STRING "${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}")
MESSAGE(STATUS "*** Will build version ${VERSION_STRING} ***")
@ -66,7 +66,7 @@ elseif(UNIX) # Linux, BSD etc
set(EXAMPLE_CONF_DIR "share/doc/${PROJECT_NAME}")
endif()
install(FILES "doc/README.txt" DESTINATION "${DOCDIR}")
install(FILES "README.txt" DESTINATION "${DOCDIR}")
install(FILES "doc/changelog.txt" DESTINATION "${DOCDIR}")
install(FILES "minetest.conf.example" DESTINATION "${DOCDIR}")

View File

@ -54,12 +54,12 @@ Compiling on GNU/Linux:
-----------------------
Install dependencies. Here's an example for Debian/Ubuntu:
$ apt-get install build-essential libirrlicht-dev cmake libbz2-dev libpng12-dev libjpeg8-dev libxxf86vm-dev libgl1-mesa-dev
$ apt-get install build-essential libirrlicht-dev cmake libbz2-dev libpng12-dev libjpeg8-dev libxxf86vm-dev libgl1-mesa-dev libsqlite3-dev
Download source, extract (this is the URL to the latest of source repository, which might not work at all times):
$ wget https://bitbucket.org/celeron55/minetest/get/tip.tar.gz
$ tar xf tip.tar.gz
$ cd minetest
$ wget https://github.com/celeron55/minetest/tarball/master -O master.tar.gz
$ tar xf master.tar.gz
$ cd celeron55-minetest-286edd4 (or similar)
Build a version that runs directly from the source directory:
$ cmake . -DRUN_IN_PLACE=1
@ -73,7 +73,7 @@ $ ./minetest
- If you want to install it system-wide (or are making a distribution package), you will want to use -DRUN_IN_PLACE=0
- You can build a bare server or a bare client by specifying -DBUILD_CLIENT=0 or -DBUILD_SERVER=0
- You can select between Release and Debug build by -DCMAKE_BUILD_TYPE=<Debug or Release>
- Note that the Debug build is considerably slower
- Debug build is slower, but gives much more useful output in a debugger
Compiling on Windows:
---------------------
@ -90,16 +90,18 @@ Compiling on Windows:
http://www.winimage.com/zLibDll/index.html
* Zlib library (zlibwapi.lib and zlibwapi.dll from zlib125dll.zip):
http://www.winimage.com/zLibDll/index.html
* gettext bibrary and tools:
* Optional: gettext bibrary and tools:
http://gnuwin32.sourceforge.net/downlinks/gettext.php
- This is used for other UI languages. Feel free to leave it out.
* And, of course, Minetest-c55:
http://celeron.55.lt/~celeron55/minetest/download
- Steps:
- Select a directory called DIR hereafter in which you will operate.
- Make sure you have CMake and a compiler installed.
- Download all the other stuff to DIR and extract them into there. All those
packages contain a nice base directory in them, which should end up being
the direct subdirectories of DIR.
- Download all the other stuff to DIR and extract them into there.
("extract here", not "extract to packagename/")
- All those packages contain a nice base directory in them, which
should end up being the direct subdirectories of DIR.
- You will end up with a directory structure like this (+=dir, -=file):
-----------------
+ DIR
@ -119,7 +121,7 @@ Compiling on Windows:
+ lib
+ include
...
+ gettext
+ gettext (optional)
+bin
+include
+lib
@ -163,7 +165,8 @@ Compiling on Windows:
If using MSVC:
- Open the generated minetest.sln
- The project defaults to the "Debug" configuration. Make very sure to
select "Release", unless you want to debug some stuff (it's slower)
select "Release", unless you want to debug some stuff (it's slower
and might not even work at all)
- Build the ALL_BUILD project
- Build the INSTALL project
- You should now have a working game with the executable in
@ -176,6 +179,30 @@ Compiling on Windows:
- You should now have a working game with the executable in
DIR/minetest/bin/minetest.exe
Windows releases of minetest are built using a bat script like this:
--------------------------------------------------------------------
set installpath="C:\tmp\minetest_install"
set irrlichtpath="C:\tmp\irrlicht-1.7.2"
set sourcedir=%CD%
set builddir=%sourcedir%\bvc10
mkdir %builddir%
pushd %builddir%
cmake %sourcedir% -G "Visual Studio 10" -DIRRLICHT_SOURCE_DIR=%irrlichtpath% -DRUN_IN_PLACE=1 -DCMAKE_INSTALL_PREFIX=%installpath%
"C:\WINDOWS\Microsoft.NET\Framework\v4.0.30319\MSBuild.exe" ALL_BUILD.vcxproj /p:Configuration=Release
"C:\WINDOWS\Microsoft.NET\Framework\v4.0.30319\MSBuild.exe" INSTALL.vcxproj /p:Configuration=Release
"C:\WINDOWS\Microsoft.NET\Framework\v4.0.30319\MSBuild.exe" PACKAGE.vcxproj /p:Configuration=Release
popd
License of Minetest-c55 textures
--------------------------------
This does not apply to texture packs made by others.
Attribution-ShareAlike 3.0 Unported (CC BY-SA 3.0)
http://creativecommons.org/licenses/by-sa/3.0/
License of Minetest-c55
-----------------------

View File

@ -1,254 +0,0 @@
Minetest-c55
---------------
An InfiniMiner/Minecraft inspired game.
Copyright (c) 2010-2011 Perttu Ahola <celeron55@gmail.com>
Further documentation:
----------------------
- Website: http://celeron.55.lt/~celeron55/minetest/
- Wiki: http://celeron.55.lt/~celeron55/minetest/wiki/
- Forum: http://celeron.55.lt/~celeron55/minetest/forum/
This is a development version:
------------------------------
- Don't expect it to work as well as a finished game will.
- Please report any bugs to me. That way I can fix them to the next release.
- debug.txt is useful when the game crashes.
Controls:
---------
- See the in-game pause menu
- Settable in the configuration file, see the section below.
Map directory:
--------------
- Map is stored in a directory, which can be removed to generate a new map.
- There is a command-line option for it: --map-dir
- For a RUN_IN_PLACE build, it is located in:
../map
- Otherwise something like this:
Windows: C:\Documents and Settings\user\Application Data\minetest\map
Linux: ~/.minetest/map
OS X: ~/Library/Application Support/minetest/map
Configuration file:
-------------------
- An optional configuration file can be used. See minetest.conf.example.
- Path to file can be passed as a parameter to the executable:
--config <path-to-file>
- Defaults:
- If built with -DRUN_IN_PLACE=1:
../minetest.conf
../../minetest.conf
- Otherwise something like this:
Windows: C:\Documents and Settings\user\Application Data\minetest\minetest.conf
Linux: ~/.minetest/minetest.conf
OS X: ~/Library/Application Support/minetest.conf
Command-line options:
---------------------
- Use --help
Compiling on GNU/Linux:
-----------------------
Install dependencies. Here's an example for Debian/Ubuntu:
$ apt-get install build-essential libirrlicht-dev cmake libbz2-dev libpng12-dev libjpeg8-dev libxxf86vm-dev libgl1-mesa-dev libsqlite3-dev
Download source, extract (this is the URL to the latest of source repository, which might not work at all times):
$ wget https://github.com/celeron55/minetest/tarball/master -O master.tar.gz
$ tar xf master.tar.gz
$ cd celeron55-minetest-286edd4 (or similar)
Build a version that runs directly from the source directory:
$ cmake . -DRUN_IN_PLACE=1
$ make -j2
Run it:
$ cd bin
$ ./minetest
- Use cmake . -LH to see all CMake options and their current state
- If you want to install it system-wide (or are making a distribution package), you will want to use -DRUN_IN_PLACE=0
- You can build a bare server or a bare client by specifying -DBUILD_CLIENT=0 or -DBUILD_SERVER=0
- You can select between Release and Debug build by -DCMAKE_BUILD_TYPE=<Debug or Release>
- Note that the Debug build is considerably slower
Compiling on Windows:
---------------------
- You need:
* CMake:
http://www.cmake.org/cmake/resources/software.html
* MinGW or Visual Studio
http://www.mingw.org/
http://msdn.microsoft.com/en-us/vstudio/default
* Irrlicht SDK 1.7:
http://irrlicht.sourceforge.net/downloads.html
* Zlib headers (zlib125.zip)
http://www.winimage.com/zLibDll/index.html
* Zlib library (zlibwapi.lib and zlibwapi.dll from zlib125dll.zip):
http://www.winimage.com/zLibDll/index.html
* And, of course, Minetest-c55:
http://celeron.55.lt/~celeron55/minetest/download
- Steps:
- Select a directory called DIR hereafter in which you will operate.
- Make sure you have CMake and a compiler installed.
- Download all the other stuff to DIR and extract them into there. All those
packages contain a nice base directory in them, which should end up being
the direct subdirectories of DIR.
- You will end up with a directory structure like this (+=dir, -=file):
-----------------
+ DIR
- zlib-1.2.5.tar.gz
- zlib125dll.zip
- irrlicht-1.7.1.zip
- 110214175330.zip (or whatever, this is the minetest source)
+ zlib-1.2.5
- zlib.h
+ win32
...
+ zlib125dll
- readme.txt
+ dll32
...
+ irrlicht-1.7.1
+ lib
+ include
...
+ minetest
+ src
+ doc
- CMakeLists.txt
...
-----------------
- Start up the CMake GUI
- Select "Browse Source..." and select DIR/minetest
- Now, if using MSVC:
- Select "Browse Build..." and select DIR/minetest-build
- Else if using MinGW:
- Select "Browse Build..." and select DIR/minetest
- Select "Configure"
- Select your compiler
- It will warn about missing stuff, ignore that at this point. (later don't)
- Make sure the configuration is as follows
(note that the versions may differ for you):
-----------------
BUILD_CLIENT [X]
BUILD_SERVER [ ]
CMAKE_BUILD_TYPE Release
CMAKE_INSTALL_PREFIX DIR/minetest-install
IRRLICHT_SOURCE_DIR DIR/irrlicht-1.7.1
RUN_IN_PLACE [X]
WARN_ALL [ ]
ZLIB_DLL DIR/zlib125dll/dll32/zlibwapi.dll
ZLIB_INCLUDE_DIR DIR/zlib-1.2.5
ZLIB_LIBRARIES DIR/zlib125dll/dll32/zlibwapi.lib
-----------------
- Hit "Configure"
- Hit "Generate"
If using MSVC:
- Open the generated minetest.sln
- The project defaults to the "Debug" configuration. Make very sure to
select "Release", unless you want to debug some stuff (it's slower)
- Build the ALL_BUILD project
- Build the INSTALL project
- You should now have a working game with the executable in
DIR/minetest-install/bin/minetest.exe
- Additionally you may create a zip package by building the PACKAGE
project.
If using MinGW:
- Using the command line, browse to the build directory and run 'make'
(or mingw32-make or whatever it happens to be)
- You should now have a working game with the executable in
DIR/minetest/bin/minetest.exe
Windows releases of minetest are built using a bat script like this:
--------------------------------------------------------------------
set installpath="C:\tmp\minetest_install"
set irrlichtpath="C:\tmp\irrlicht-1.7.2"
set sourcedir=%CD%
set builddir=%sourcedir%\bvc10
mkdir %builddir%
pushd %builddir%
cmake %sourcedir% -G "Visual Studio 10" -DIRRLICHT_SOURCE_DIR=%irrlichtpath% -DRUN_IN_PLACE=1 -DCMAKE_INSTALL_PREFIX=%installpath%
"C:\WINDOWS\Microsoft.NET\Framework\v4.0.30319\MSBuild.exe" ALL_BUILD.vcxproj /p:Configuration=Release
"C:\WINDOWS\Microsoft.NET\Framework\v4.0.30319\MSBuild.exe" INSTALL.vcxproj /p:Configuration=Release
"C:\WINDOWS\Microsoft.NET\Framework\v4.0.30319\MSBuild.exe" PACKAGE.vcxproj /p:Configuration=Release
popd
License of Minetest-c55
-----------------------
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.
Irrlicht
---------------
This program uses the Irrlicht Engine. http://irrlicht.sourceforge.net/
The Irrlicht Engine License
Copyright © 2002-2005 Nikolaus Gebhardt
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute
it freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you
must not claim that you wrote the original software. If you use
this software in a product, an acknowledgment in the product
documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must
not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source
distribution.
JThread
---------------
This program uses the JThread library. License for JThread follows:
Copyright (c) 2000-2006 Jori Liesenborgs (jori.liesenborgs@gmail.com)
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.

View File

@ -3,17 +3,29 @@ Minetest-c55 changelog
This should contain all the major changes.
For minor stuff, refer to the commit log of the repository.
0.3.1: (released on 2011-11-09)
- Fix frustum culling (previous versions have rendered too much stuff that is not actually visible (about 180 degrees, while should have been more like 100.))
- Add occlusion culling (improves performance a lot)
- Add “3d clouds” on/off checkbox in main menu
- Add “opaque water” on/off checkbox
- Fix some random minor stuff
- Turn mipmapping off (This makes far-away textures a bit noisier but better looking)
- Add Command-line signal handler for Windows (contributed by SpeedProg)
- Fix network layer segmentation fault introduced in 0.3.dev-20111021
- Fix water-glass and water-lava and lava-glass surfaces
0.3.0: (released on 2011-11-01)
- Some small fixes
0.3.dev-20111021:
- Modify dungeon masters to only try to shoot players
- Fix object duplication bug at block load/unload bug
- Improve network layer
0.3.dev-20111016:
- Locked chest
- Locked chest (contributed)
- Server user limit setting (max_users)
- Wielded tool is shown in HUD
- View bobbing
- Saplings that drop from leaf blocks and when placed on ground will grow to trees
- Wielded tool is shown in HUD (contributed)
- View bobbing (contributed)
- Saplings that drop from leaf blocks and when placed on ground will grow to trees (contributed)
- Optimized map saving (does not re-save everything all the time)
- New mob system and new mob: dungeon master
- Death/respawn screen

View File

@ -665,14 +665,13 @@ void Client::ReceiveAll()
void Client::Receive()
{
DSTACK(__FUNCTION_NAME);
u32 data_maxsize = 200000;
Buffer<u8> data(data_maxsize);
SharedBuffer<u8> data;
u16 sender_peer_id;
u32 datasize;
{
//TimeTaker t1("con mutex and receive", m_device);
//JMutexAutoLock lock(m_con_mutex); //bulk comment-out
datasize = m_con.Receive(sender_peer_id, *data, data_maxsize);
datasize = m_con.Receive(sender_peer_id, data);
}
//TimeTaker t1("ProcessData", m_device);
ProcessData(*data, datasize, sender_peer_id);

View File

@ -81,9 +81,9 @@ void Clouds::render()
ScopeProfiler sp(g_profiler, "Rendering of clouds, avg", SPT_AVG);
int num_faces_to_draw = 6;
if(g_settings->getBool("enable_2d_clouds"))
num_faces_to_draw = 1;
int num_faces_to_draw = 1;
if(g_settings->getBool("enable_3d_clouds"))
num_faces_to_draw = 6;
driver->setTransform(video::ETS_WORLD, AbsoluteTransformation);
driver->setMaterial(m_material);

View File

@ -670,7 +670,7 @@ void Connection::receive()
// TODO: We can not know how many layers of header there are.
// For now, just assume there are no other than the base headers.
u32 packet_maxsize = datasize + BASE_HEADER_SIZE;
Buffer<u8> packetdata(packet_maxsize);
SharedBuffer<u8> packetdata(packet_maxsize);
bool single_wait_done = false;
@ -1577,7 +1577,7 @@ void Connection::Disconnect()
putCommand(c);
}
u32 Connection::Receive(u16 &peer_id, u8 *data, u32 datasize)
u32 Connection::Receive(u16 &peer_id, SharedBuffer<u8> &data)
{
for(;;){
ConnectionEvent e = waitEvent(m_bc_receive_timeout);
@ -1589,7 +1589,7 @@ u32 Connection::Receive(u16 &peer_id, u8 *data, u32 datasize)
throw NoIncomingDataException("No incoming data");
case CONNEVENT_DATA_RECEIVED:
peer_id = e.peer_id;
memcpy(data, *e.data, e.data.getSize());
data = SharedBuffer<u8>(e.data);
return e.data.getSize();
case CONNEVENT_PEER_ADDED: {
Peer tmp(e.peer_id, e.address);

View File

@ -430,7 +430,7 @@ struct ConnectionEvent
{
enum ConnectionEventType type;
u16 peer_id;
SharedBuffer<u8> data;
Buffer<u8> data;
bool timeout;
Address address;
@ -489,7 +489,7 @@ struct ConnectionCommand
Address address;
u16 peer_id;
u8 channelnum;
SharedBuffer<u8> data;
Buffer<u8> data;
bool reliable;
ConnectionCommand(): type(CONNCMD_NONE) {}
@ -551,7 +551,7 @@ public:
void Connect(Address address);
bool Connected();
void Disconnect();
u32 Receive(u16 &peer_id, u8 *data, u32 datasize);
u32 Receive(u16 &peer_id, SharedBuffer<u8> &data);
void SendToAll(u8 channelnum, SharedBuffer<u8> data, bool reliable);
void Send(u16 peer_id, u8 channelnum, SharedBuffer<u8> data, bool reliable);
void RunTimeouts(float dtime); // dummy

View File

@ -446,6 +446,9 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
assert(content_features(n).special_material);
video::SMaterial &liquid_material =
*content_features(n).special_material;
video::SMaterial &liquid_material_bfculled =
*content_features(n).special_material2;
assert(content_features(n).special_atlas);
AtlasPointer &pa_liquid1 =
*content_features(n).special_atlas;
@ -598,10 +601,10 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
continue;
content_t neighbor_content = neighbor_contents[dir];
ContentFeatures &n_feat = content_features(neighbor_content);
// Don't draw face if neighbor is not air or liquid
if(neighbor_content != CONTENT_AIR
&& content_liquid(neighbor_content) == false)
// Don't draw face if neighbor is blocking the view
if(n_feat.solidness == 2)
continue;
bool neighbor_is_same_liquid = (neighbor_content == c_source
@ -612,6 +615,12 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
if(neighbor_is_same_liquid == true
&& top_is_same_liquid == false)
continue;
// Use backface culled material if neighbor doesn't have a
// solidness of 0
video::SMaterial *current_material = &liquid_material;
if(n_feat.solidness != 0 || n_feat.visual_solidness != 0)
current_material = &liquid_material_bfculled;
video::S3DVertex vertices[4] =
{
@ -675,17 +684,17 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
// Do this to not cause glitches when two liquids are
// side-by-side
if(neighbor_is_same_liquid == false){
/*if(neighbor_is_same_liquid == false){
vertices[j].Pos.X *= 0.98;
vertices[j].Pos.Z *= 0.98;
}
}*/
vertices[j].Pos += intToFloat(p + blockpos_nodes, BS);
}
u16 indices[] = {0,1,2,2,3,0};
// Add to mesh collector
collector.append(liquid_material, vertices, 4, indices, 6);
collector.append(*current_material, vertices, 4, indices, 6);
}
/*

View File

@ -107,6 +107,7 @@ void content_mapnode_init()
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");
bool opaque_water = g_settings->getBool("opaque_water");
content_t i;
ContentFeatures *f = NULL;
@ -398,7 +399,8 @@ void content_mapnode_init()
f->liquid_alternative_source = CONTENT_WATERSOURCE;
f->liquid_viscosity = WATER_VISC;
#ifndef SERVER
f->vertex_alpha = WATER_ALPHA;
if(!opaque_water)
f->vertex_alpha = WATER_ALPHA;
f->post_effect_color = video::SColor(64, 100, 100, 200);
if(f->special_material == NULL && g_texturesource)
{
@ -408,10 +410,17 @@ void content_mapnode_init()
f->special_material->setFlag(video::EMF_BACK_FACE_CULLING, false);
f->special_material->setFlag(video::EMF_BILINEAR_FILTER, false);
f->special_material->setFlag(video::EMF_FOG_ENABLE, true);
f->special_material->MaterialType = video::EMT_TRANSPARENT_VERTEX_ALPHA;
if(!opaque_water)
f->special_material->MaterialType = video::EMT_TRANSPARENT_VERTEX_ALPHA;
AtlasPointer *pa_water1 = new AtlasPointer(g_texturesource->getTexture(
g_texturesource->getTextureId("water.png")));
f->special_material->setTexture(0, pa_water1->atlas);
// Flowing water material, backface culled
f->special_material2 = new video::SMaterial;
*f->special_material2 = *f->special_material;
f->special_material2->setFlag(video::EMF_BACK_FACE_CULLING, true);
f->special_atlas = pa_water1;
}
#endif
@ -432,8 +441,10 @@ void content_mapnode_init()
if(g_texturesource)
t.texture = g_texturesource->getTexture("water.png");
t.alpha = WATER_ALPHA;
t.material_type = MATERIAL_ALPHA_VERTEX;
if(!opaque_water){
t.alpha = WATER_ALPHA;
t.material_type = MATERIAL_ALPHA_VERTEX;
}
t.material_flags &= ~MATERIAL_FLAG_BACKFACE_CULLING;
f->setAllTiles(t);
#endif
@ -450,11 +461,12 @@ void content_mapnode_init()
f->liquid_alternative_source = CONTENT_WATERSOURCE;
f->liquid_viscosity = WATER_VISC;
#ifndef SERVER
f->vertex_alpha = WATER_ALPHA;
if(!opaque_water)
f->vertex_alpha = WATER_ALPHA;
f->post_effect_color = video::SColor(64, 100, 100, 200);
if(f->special_material == NULL && g_texturesource)
{
// Flowing water material
// New-style water source material (mostly unused)
f->special_material = new video::SMaterial;
f->special_material->setFlag(video::EMF_LIGHTING, false);
f->special_material->setFlag(video::EMF_BACK_FACE_CULLING, false);
@ -476,7 +488,7 @@ void content_mapnode_init()
f->light_propagates = false;
f->light_source = LIGHT_MAX-1;
f->solidness = 0; // Drawn separately, makes no faces
f->visual_solidness = 2;
f->visual_solidness = 1; // Does not completely cover block boundaries
f->walkable = false;
f->pointable = false;
f->diggable = false;
@ -497,10 +509,17 @@ void content_mapnode_init()
f->special_material->setFlag(video::EMF_BILINEAR_FILTER, false);
f->special_material->setFlag(video::EMF_FOG_ENABLE, true);
f->special_material->MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
AtlasPointer *pa_lava1 = new AtlasPointer(
g_texturesource->getTexture(
g_texturesource->getTextureId("lava.png")));
f->special_material->setTexture(0, pa_lava1->atlas);
// Flowing lava material, backface culled
f->special_material2 = new video::SMaterial;
*f->special_material2 = *f->special_material;
f->special_material2->setFlag(video::EMF_BACK_FACE_CULLING, true);
f->special_atlas = pa_lava1;
}
#endif
@ -544,7 +563,7 @@ void content_mapnode_init()
f->post_effect_color = video::SColor(192, 255, 64, 0);
if(f->special_material == NULL && g_texturesource)
{
// Flowing lava material
// New-style lava source material (mostly unused)
f->special_material = new video::SMaterial;
f->special_material->setFlag(video::EMF_LIGHTING, false);
f->special_material->setFlag(video::EMF_BACK_FACE_CULLING, false);
@ -555,6 +574,7 @@ void content_mapnode_init()
g_texturesource->getTexture(
g_texturesource->getTextureId("lava.png")));
f->special_material->setTexture(0, pa_lava1->atlas);
f->special_atlas = pa_lava1;
}
#endif

View File

@ -46,6 +46,7 @@ void set_default_settings(Settings *settings)
settings->setDefault("keymap_screenshot", "KEY_F12");
settings->setDefault("keymap_toggle_profiler", "KEY_F2");
settings->setDefault("keymap_toggle_force_fog_off", "KEY_F3");
settings->setDefault("keymap_toggle_update_camera", "KEY_F4");
// Some (temporary) keys for debugging
settings->setDefault("keymap_print_debug_stacks", "KEY_KEY_P");
@ -62,7 +63,7 @@ void set_default_settings(Settings *settings)
settings->setDefault("fov", "72");
settings->setDefault("view_bobbing", "true");
settings->setDefault("new_style_water", "false");
settings->setDefault("new_style_leaves", "true");
settings->setDefault("new_style_leaves", "false");
settings->setDefault("smooth_lighting", "true");
settings->setDefault("frametime_graph", "false");
settings->setDefault("enable_texture_atlas", "true");
@ -77,7 +78,8 @@ void set_default_settings(Settings *settings)
settings->setDefault("invisible_stone", "false");
settings->setDefault("screenshot_path", ".");
settings->setDefault("view_bobbing_amount", "1.0");
settings->setDefault("enable_2d_clouds", "false");
settings->setDefault("enable_3d_clouds", "false");
settings->setDefault("opaque_water", "false");
// Server stuff
// "map-dir" doesn't exist by default.

View File

@ -956,11 +956,11 @@ void the_game(
//guitext_chat->setBackgroundColor(video::SColor(96,0,0,0));
core::list<ChatLine> chat_lines;
// Profiler text
// Profiler text (size is updated when text is updated)
gui::IGUIStaticText *guitext_profiler = guienv->addStaticText(
L"<Profiler>",
core::rect<s32>(6, 4+(text_height+5)*3, 400,
(text_height+5)*3 + text_height*35),
core::rect<s32>(6, 4+(text_height+5)*2, 400,
(text_height+5)*2 + text_height*35),
false, false);
guitext_profiler->setBackgroundColor(video::SColor(80,0,0,0));
guitext_profiler->setVisible(false);
@ -1019,8 +1019,8 @@ void the_game(
bool respawn_menu_active = false;
bool show_profiler = false;
bool force_fog_off = false;
bool disable_camera_update = false;
/*
Main loop
@ -1259,9 +1259,18 @@ void the_game(
std::ostringstream os(std::ios_base::binary);
g_profiler->print(os);
guitext_profiler->setText(narrow_to_wide(os.str()).c_str());
std::wstring text = narrow_to_wide(os.str());
guitext_profiler->setText(text.c_str());
g_profiler->clear();
s32 w = font->getDimension(text.c_str()).Width;
if(w < 400)
w = 400;
core::rect<s32> rect(6, 4+(text_height+5)*2, 12+w,
8+(text_height+5)*2 +
font->getDimension(text.c_str()).Height);
guitext_profiler->setRelativePosition(rect);
}
/*
@ -1395,10 +1404,26 @@ void the_game(
{
show_profiler = !show_profiler;
guitext_profiler->setVisible(show_profiler);
if(show_profiler)
chat_lines.push_back(ChatLine(L"Profiler disabled"));
else
chat_lines.push_back(ChatLine(L"Profiler enabled"));
}
else if(input->wasKeyDown(getKeySetting("keymap_toggle_force_fog_off")))
{
force_fog_off = !force_fog_off;
if(force_fog_off)
chat_lines.push_back(ChatLine(L"Fog disabled"));
else
chat_lines.push_back(ChatLine(L"Fog enabled"));
}
else if(input->wasKeyDown(getKeySetting("keymap_toggle_update_camera")))
{
disable_camera_update = !disable_camera_update;
if(disable_camera_update)
chat_lines.push_back(ChatLine(L"Camera update disabled"));
else
chat_lines.push_back(ChatLine(L"Camera update enabled"));
}
// Item selection with mouse wheel
@ -1645,11 +1670,10 @@ void the_game(
v3f camera_direction = camera.getDirection();
f32 camera_fov = camera.getFovMax();
if(FIELD_OF_VIEW_TEST)
client.updateCamera(v3f(0,0,0), v3f(0,0,1), camera_fov);
else
if(!disable_camera_update){
client.updateCamera(camera_position,
camera_direction, camera_fov);
}
//timer2.stop();
//TimeTaker //timer3("//timer3");
@ -2566,4 +2590,3 @@ void the_game(
}
}

View File

@ -80,6 +80,8 @@ void GUIMainMenu::regenerateGui(v2u32 screensize)
bool enable_damage;
bool fancy_trees;
bool smooth_lighting;
bool clouds_3d;
bool opaque_water;
// Client options
{
@ -117,6 +119,20 @@ void GUIMainMenu::regenerateGui(v2u32 screensize)
else
smooth_lighting = m_data->smooth_lighting;
}
{
gui::IGUIElement *e = getElementFromId(GUI_ID_3D_CLOUDS_CB);
if(e != NULL && e->getType() == gui::EGUIET_CHECK_BOX)
clouds_3d = ((gui::IGUICheckBox*)e)->isChecked();
else
clouds_3d = m_data->clouds_3d;
}
{
gui::IGUIElement *e = getElementFromId(GUI_ID_OPAQUE_WATER_CB);
if(e != NULL && e->getType() == gui::EGUIET_CHECK_BOX)
opaque_water = ((gui::IGUICheckBox*)e)->isChecked();
else
opaque_water = m_data->opaque_water;
}
// Server options
{
@ -242,10 +258,22 @@ void GUIMainMenu::regenerateGui(v2u32 screensize)
}
{
core::rect<s32> rect(0, 0, 250, 30);
rect += topleft_client + v2s32(35, 150+30);
rect += topleft_client + v2s32(35, 150+20);
Environment->addCheckBox(smooth_lighting, rect, this, GUI_ID_SMOOTH_LIGHTING_CB,
wgettext("Smooth Lighting"));
}
{
core::rect<s32> rect(0, 0, 250, 30);
rect += topleft_client + v2s32(35, 150+40);
Environment->addCheckBox(clouds_3d, rect, this, GUI_ID_3D_CLOUDS_CB,
wgettext("3D Clouds"));
}
{
core::rect<s32> rect(0, 0, 250, 30);
rect += topleft_client + v2s32(35, 150+60);
Environment->addCheckBox(opaque_water, rect, this, GUI_ID_OPAQUE_WATER_CB,
wgettext("Opaque water"));
}
// Start game button
{
core::rect<s32> rect(0, 0, 180, 30);
@ -362,15 +390,25 @@ void GUIMainMenu::acceptInput()
if(e != NULL && e->getType() == gui::EGUIET_CHECK_BOX)
m_data->enable_damage = ((gui::IGUICheckBox*)e)->isChecked();
}
{
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();
}
{
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(GUI_ID_FANCYTREE_CB);
gui::IGUIElement *e = getElementFromId(GUI_ID_3D_CLOUDS_CB);
if(e != NULL && e->getType() == gui::EGUIET_CHECK_BOX)
m_data->fancy_trees = ((gui::IGUICheckBox*)e)->isChecked();
m_data->clouds_3d = ((gui::IGUICheckBox*)e)->isChecked();
}
{
gui::IGUIElement *e = getElementFromId(GUI_ID_OPAQUE_WATER_CB);
if(e != NULL && e->getType() == gui::EGUIET_CHECK_BOX)
m_data->opaque_water = ((gui::IGUICheckBox*)e)->isChecked();
}
m_accepted = true;

View File

@ -35,6 +35,8 @@ enum
GUI_ID_PORT_INPUT,
GUI_ID_FANCYTREE_CB,
GUI_ID_SMOOTH_LIGHTING_CB,
GUI_ID_3D_CLOUDS_CB,
GUI_ID_OPAQUE_WATER_CB,
GUI_ID_DAMAGE_CB,
GUI_ID_CREATIVE_CB,
GUI_ID_JOIN_GAME_BUTTON,
@ -64,6 +66,8 @@ struct MainMenuData
std::wstring password;
bool fancy_trees;
bool smooth_lighting;
bool clouds_3d;
bool opaque_water;
// Server options
bool creative_mode;
bool enable_damage;

View File

@ -1407,6 +1407,21 @@ int main(int argc, char *argv[])
if (device == 0)
return 1; // could not create selected driver.
/*
Continue initialization
*/
video::IVideoDriver* driver = device->getVideoDriver();
// Disable mipmaps (because some of them look ugly)
driver->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, false);
/*
This changes the minimum allowed number of vertices in a VBO.
Default is 500.
*/
//driver->setMinHardwareBufferVertexCount(50);
// Set the window caption
device->setWindowCaption(L"Minetest [Main Menu]");
@ -1439,18 +1454,6 @@ int main(int argc, char *argv[])
else
input = new RealInputHandler(device, &receiver);
/*
Continue initialization
*/
//video::IVideoDriver* driver = device->getVideoDriver();
/*
This changes the minimum allowed number of vertices in a VBO.
Default is 500.
*/
//driver->setMinHardwareBufferVertexCount(50);
scene::ISceneManager* smgr = device->getSceneManager();
guienv = device->getGUIEnvironment();
@ -1543,6 +1546,8 @@ int main(int argc, char *argv[])
menudata.port = narrow_to_wide(itos(port));
menudata.fancy_trees = g_settings->getBool("new_style_leaves");
menudata.smooth_lighting = g_settings->getBool("smooth_lighting");
menudata.clouds_3d = g_settings->getBool("enable_3d_clouds");
menudata.opaque_water = g_settings->getBool("opaque_water");
menudata.creative_mode = g_settings->getBool("creative_mode");
menudata.enable_damage = g_settings->getBool("enable_damage");
@ -1615,6 +1620,8 @@ int main(int argc, char *argv[])
port = newport;
g_settings->set("new_style_leaves", itos(menudata.fancy_trees));
g_settings->set("smooth_lighting", itos(menudata.smooth_lighting));
g_settings->set("enable_3d_clouds", itos(menudata.clouds_3d));
g_settings->set("opaque_water", itos(menudata.opaque_water));
g_settings->set("creative_mode", itos(menudata.creative_mode));
g_settings->set("enable_damage", itos(menudata.enable_damage));

View File

@ -3649,6 +3649,35 @@ void ClientMap::OnRegisterSceneNode()
ISceneNode::OnRegisterSceneNode();
}
static bool isOccluded(Map *map, v3s16 p0, v3s16 p1, float step, float stepfac,
float start_off, float end_off, u32 needed_count)
{
float d0 = (float)BS * p0.getDistanceFrom(p1);
v3s16 u0 = p1 - p0;
v3f uf = v3f(u0.X, u0.Y, u0.Z) * BS;
uf.normalize();
v3f p0f = v3f(p0.X, p0.Y, p0.Z) * BS;
u32 count = 0;
for(float s=start_off; s<d0+end_off; s+=step){
v3f pf = p0f + uf * s;
v3s16 p = floatToInt(pf, BS);
MapNode n = map->getNodeNoEx(p);
bool is_transparent = false;
ContentFeatures &f = content_features(n);
if(f.solidness == 0)
is_transparent = (f.visual_solidness != 2);
else
is_transparent = (f.solidness != 2);
if(!is_transparent){
count++;
if(count >= needed_count)
return true;
}
step *= stepfac;
}
return false;
}
void ClientMap::renderMap(video::IVideoDriver* driver, s32 pass)
{
//m_dout<<DTIME<<"Rendering map..."<<std::endl;
@ -3656,6 +3685,12 @@ void ClientMap::renderMap(video::IVideoDriver* driver, s32 pass)
bool is_transparent_pass = pass == scene::ESNRP_TRANSPARENT;
std::string prefix;
if(pass == scene::ESNRP_SOLID)
prefix = "CM: solid: ";
else
prefix = "CM: transparent: ";
/*
This is called two times per frame, reset on the non-transparent one
*/
@ -3684,11 +3719,8 @@ void ClientMap::renderMap(video::IVideoDriver* driver, s32 pass)
Get all blocks and draw all visible ones
*/
v3s16 cam_pos_nodes(
camera_position.X / BS,
camera_position.Y / BS,
camera_position.Z / BS);
v3s16 cam_pos_nodes = floatToInt(camera_position, BS);
v3s16 box_nodes_d = m_control.wanted_range * v3s16(1,1,1);
v3s16 p_nodes_min = cam_pos_nodes - box_nodes_d;
@ -3713,6 +3745,8 @@ void ClientMap::renderMap(video::IVideoDriver* driver, s32 pass)
// Number of blocks in rendering range
u32 blocks_in_range = 0;
// Number of blocks occlusion culled
u32 blocks_occlusion_culled = 0;
// Number of blocks in rendering range but don't have a mesh
u32 blocks_in_range_without_mesh = 0;
// Blocks that had mesh that would have been drawn according to
@ -3725,27 +3759,19 @@ void ClientMap::renderMap(video::IVideoDriver* driver, s32 pass)
// Blocks from which stuff was actually drawn
u32 blocks_without_stuff = 0;
int timecheck_counter = 0;
core::map<v2s16, MapSector*>::Iterator si;
si = m_sectors.getIterator();
for(; si.atEnd() == false; si++)
{
{
timecheck_counter++;
if(timecheck_counter > 50)
{
timecheck_counter = 0;
int time2 = time(0);
if(time2 > time1 + 4)
{
infostream<<"ClientMap::renderMap(): "
"Rendering takes ages, returning."
<<std::endl;
return;
}
}
}
/*
Collect a set of blocks for drawing
*/
core::map<v3s16, MapBlock*> drawset;
{
ScopeProfiler sp(g_profiler, prefix+"collecting blocks for drawing", SPT_AVG);
for(core::map<v2s16, MapSector*>::Iterator
si = m_sectors.getIterator();
si.atEnd() == false; si++)
{
MapSector *sector = si.getNode()->getValue();
v2s16 sp = sector->getPos();
@ -3762,11 +3788,11 @@ void ClientMap::renderMap(video::IVideoDriver* driver, s32 pass)
sector->getBlocks(sectorblocks);
/*
Draw blocks
Loop through blocks in sector
*/
u32 sector_blocks_drawn = 0;
u32 sector_blocks_drawn = 0;
core::list< MapBlock * >::Iterator i;
for(i=sectorblocks.begin(); i!=sectorblocks.end(); i++)
{
@ -3780,7 +3806,7 @@ void ClientMap::renderMap(video::IVideoDriver* driver, s32 pass)
float range = 100000 * BS;
if(m_control.range_all == false)
range = m_control.wanted_range * BS;
float d = 0.0;
if(isBlockInSight(block->getPos(), camera_position,
camera_direction, camera_fov,
@ -3789,16 +3815,13 @@ void ClientMap::renderMap(video::IVideoDriver* driver, s32 pass)
continue;
}
// Okay, this block will be drawn. Reset usage timer.
block->resetUsageTimer();
// This is ugly (spherical distance limit?)
/*if(m_control.range_all == false &&
d - 0.5*BS*MAP_BLOCKSIZE > range)
continue;*/
blocks_in_range++;
blocks_in_range++;
#if 1
/*
Update expired mesh (used for day/night change)
@ -3848,10 +3871,51 @@ void ClientMap::renderMap(video::IVideoDriver* driver, s32 pass)
mesh_expired = false;
}
#endif
/*
Draw the faces of the block
Occlusion culling
*/
v3s16 cpn = block->getPos() * MAP_BLOCKSIZE;
cpn += v3s16(MAP_BLOCKSIZE/2, MAP_BLOCKSIZE/2, MAP_BLOCKSIZE/2);
float step = BS*1;
float stepfac = 1.1;
float startoff = BS*1;
float endoff = -BS*MAP_BLOCKSIZE*1.42*1.42;
v3s16 spn = cam_pos_nodes + v3s16(0,0,0);
s16 bs2 = MAP_BLOCKSIZE/2 + 1;
u32 needed_count = 1;
if(
isOccluded(this, spn, cpn + v3s16(0,0,0),
step, stepfac, startoff, endoff, needed_count) &&
isOccluded(this, spn, cpn + v3s16(bs2,bs2,bs2),
step, stepfac, startoff, endoff, needed_count) &&
isOccluded(this, spn, cpn + v3s16(bs2,bs2,-bs2),
step, stepfac, startoff, endoff, needed_count) &&
isOccluded(this, spn, cpn + v3s16(bs2,-bs2,bs2),
step, stepfac, startoff, endoff, needed_count) &&
isOccluded(this, spn, cpn + v3s16(bs2,-bs2,-bs2),
step, stepfac, startoff, endoff, needed_count) &&
isOccluded(this, spn, cpn + v3s16(-bs2,bs2,bs2),
step, stepfac, startoff, endoff, needed_count) &&
isOccluded(this, spn, cpn + v3s16(-bs2,bs2,-bs2),
step, stepfac, startoff, endoff, needed_count) &&
isOccluded(this, spn, cpn + v3s16(-bs2,-bs2,bs2),
step, stepfac, startoff, endoff, needed_count) &&
isOccluded(this, spn, cpn + v3s16(-bs2,-bs2,-bs2),
step, stepfac, startoff, endoff, needed_count)
)
{
blocks_occlusion_culled++;
continue;
}
// This block is in range. Reset usage timer.
block->resetUsageTimer();
/*
Ignore if mesh doesn't exist
*/
{
JMutexAutoLock lock(block->mesh_mutex);
@ -3862,72 +3926,112 @@ void ClientMap::renderMap(video::IVideoDriver* driver, s32 pass)
blocks_in_range_without_mesh++;
continue;
}
blocks_would_have_drawn++;
if(blocks_drawn >= m_control.wanted_max_blocks
&& m_control.range_all == false
&& d > m_control.wanted_min_range * BS)
continue;
blocks_drawn++;
sector_blocks_drawn++;
u32 c = mesh->getMeshBufferCount();
bool stuff_actually_drawn = false;
for(u32 i=0; i<c; i++)
{
scene::IMeshBuffer *buf = mesh->getMeshBuffer(i);
const video::SMaterial& material = buf->getMaterial();
video::IMaterialRenderer* rnd =
driver->getMaterialRenderer(material.MaterialType);
bool transparent = (rnd && rnd->isTransparent());
// Render transparent on transparent pass and likewise.
if(transparent == is_transparent_pass)
{
if(buf->getVertexCount() == 0)
errorstream<<"Block ["<<analyze_block(block)
<<"] contains an empty meshbuf"<<std::endl;
/*
This *shouldn't* hurt too much because Irrlicht
doesn't change opengl textures if the old
material has the same texture.
*/
driver->setMaterial(buf->getMaterial());
driver->drawMeshBuffer(buf);
vertex_count += buf->getVertexCount();
meshbuffer_count++;
stuff_actually_drawn = true;
}
}
if(stuff_actually_drawn)
blocks_had_pass_meshbuf++;
else
blocks_without_stuff++;
}
// Limit block count in case of a sudden increase
blocks_would_have_drawn++;
if(blocks_drawn >= m_control.wanted_max_blocks
&& m_control.range_all == false
&& d > m_control.wanted_min_range * BS)
continue;
// Add to set
drawset[block->getPos()] = block;
sector_blocks_drawn++;
blocks_drawn++;
} // foreach sectorblocks
if(sector_blocks_drawn != 0)
{
m_last_drawn_sectors[sp] = true;
}
} // ScopeProfiler
/*
Draw the selected MapBlocks
*/
{
ScopeProfiler sp(g_profiler, prefix+"drawing blocks", SPT_AVG);
int timecheck_counter = 0;
for(core::map<v3s16, MapBlock*>::Iterator
i = drawset.getIterator();
i.atEnd() == false; i++)
{
{
timecheck_counter++;
if(timecheck_counter > 50)
{
timecheck_counter = 0;
int time2 = time(0);
if(time2 > time1 + 4)
{
infostream<<"ClientMap::renderMap(): "
"Rendering takes ages, returning."
<<std::endl;
return;
}
}
}
MapBlock *block = i.getNode()->getValue();
/*
Draw the faces of the block
*/
{
JMutexAutoLock lock(block->mesh_mutex);
scene::SMesh *mesh = block->mesh;
assert(mesh);
u32 c = mesh->getMeshBufferCount();
bool stuff_actually_drawn = false;
for(u32 i=0; i<c; i++)
{
scene::IMeshBuffer *buf = mesh->getMeshBuffer(i);
const video::SMaterial& material = buf->getMaterial();
video::IMaterialRenderer* rnd =
driver->getMaterialRenderer(material.MaterialType);
bool transparent = (rnd && rnd->isTransparent());
// Render transparent on transparent pass and likewise.
if(transparent == is_transparent_pass)
{
if(buf->getVertexCount() == 0)
errorstream<<"Block ["<<analyze_block(block)
<<"] contains an empty meshbuf"<<std::endl;
/*
This *shouldn't* hurt too much because Irrlicht
doesn't change opengl textures if the old
material has the same texture.
*/
driver->setMaterial(buf->getMaterial());
driver->drawMeshBuffer(buf);
vertex_count += buf->getVertexCount();
meshbuffer_count++;
stuff_actually_drawn = true;
}
}
if(stuff_actually_drawn)
blocks_had_pass_meshbuf++;
else
blocks_without_stuff++;
}
}
} // ScopeProfiler
std::string prefix = "CM: ";
// Log only on solid pass because values are the same
if(pass == scene::ESNRP_SOLID){
g_profiler->avg(prefix+"blocks in range", blocks_in_range);
g_profiler->avg("CM: blocks in range", blocks_in_range);
g_profiler->avg("CM: blocks occlusion culled", blocks_occlusion_culled);
if(blocks_in_range != 0)
g_profiler->avg(prefix+"blocks in range without mesh (frac)",
g_profiler->avg("CM: blocks in range without mesh (frac)",
(float)blocks_in_range_without_mesh/blocks_in_range);
g_profiler->avg(prefix+"blocks drawn", blocks_drawn);
g_profiler->avg("CM: blocks drawn", blocks_drawn);
}
if(pass == scene::ESNRP_SOLID)
prefix = "CM: solid: ";
else
prefix = "CM: transparent: ";
g_profiler->avg(prefix+"vertices drawn", vertex_count);
if(blocks_had_pass_meshbuf != 0)
g_profiler->avg(prefix+"meshbuffers per block",

View File

@ -427,7 +427,8 @@ void getTileInfo(
// This is hackish
content_t content0 = getNodeContent(p, n0, temp_mods);
content_t content1 = getNodeContent(p + face_dir, n1, temp_mods);
u8 mf = face_contents(content0, content1);
bool equivalent = false;
u8 mf = face_contents(content0, content1, &equivalent);
if(mf == 0)
{
@ -450,6 +451,10 @@ void getTileInfo(
face_dir_corrected = -face_dir;
}
// eg. water and glass
if(equivalent)
tile.material_flags |= MATERIAL_FLAG_BACKFACE_CULLING;
if(smooth_lighting == false)
{
lights[0] = lights[1] = lights[2] = lights[3] =

View File

@ -168,6 +168,9 @@ void init_mapnode()
f->dug_item = std::string("MaterialItem2 ")+itos(i)+" 1";
}
// Make CONTENT_IGNORE to not block the view when occlusion culling
content_features(CONTENT_IGNORE).solidness = 0;
/*
Initialize mapnode content
*/
@ -175,6 +178,57 @@ void init_mapnode()
}
/*
Nodes make a face if contents differ and solidness differs.
Return value:
0: No face
1: Face uses m1's content
2: Face uses m2's content
equivalent: Whether the blocks share the same face (eg. water and glass)
*/
u8 face_contents(content_t m1, content_t m2, bool *equivalent)
{
*equivalent = false;
if(m1 == CONTENT_IGNORE || m2 == CONTENT_IGNORE)
return 0;
bool contents_differ = (m1 != m2);
// Contents don't differ for different forms of same liquid
if(content_liquid(m1) && content_liquid(m2)
&& make_liquid_flowing(m1) == make_liquid_flowing(m2))
contents_differ = false;
u8 c1 = content_solidness(m1);
u8 c2 = content_solidness(m2);
bool solidness_differs = (c1 != c2);
bool makes_face = contents_differ && solidness_differs;
if(makes_face == false)
return 0;
if(c1 == 0)
c1 = content_features(m1).visual_solidness;
if(c2 == 0)
c2 = content_features(m2).visual_solidness;
if(c1 == c2){
*equivalent = true;
// If same solidness, liquid takes precense
if(content_features(m1).liquid_type != LIQUID_NONE)
return 1;
if(content_features(m2).liquid_type != LIQUID_NONE)
return 2;
}
if(c1 > c2)
return 1;
else
return 2;
}
v3s16 facedir_rotate(u8 facedir, v3s16 dir)
{
/*

View File

@ -121,6 +121,7 @@ struct ContentFeatures
video::SColor post_effect_color;
// Special irrlicht material, used sometimes
video::SMaterial *special_material;
video::SMaterial *special_material2;
AtlasPointer *special_atlas;
#endif
@ -199,6 +200,7 @@ struct ContentFeatures
vertex_alpha = 255;
post_effect_color = video::SColor(0, 0, 0, 0);
special_material = NULL;
special_material2 = NULL;
special_atlas = NULL;
#endif
param_type = CPT_NONE;
@ -377,30 +379,9 @@ inline bool content_buildable_to(content_t m)
0: No face
1: Face uses m1's content
2: Face uses m2's content
equivalent: Whether the blocks share the same face (eg. water and glass)
*/
inline u8 face_contents(content_t m1, content_t m2)
{
if(m1 == CONTENT_IGNORE || m2 == CONTENT_IGNORE)
return 0;
bool contents_differ = (m1 != m2);
// Contents don't differ for different forms of same liquid
if(content_liquid(m1) && content_liquid(m2)
&& make_liquid_flowing(m1) == make_liquid_flowing(m2))
contents_differ = false;
bool solidness_differs = (content_solidness(m1) != content_solidness(m2));
bool makes_face = contents_differ && solidness_differs;
if(makes_face == false)
return 0;
if(content_solidness(m1) > content_solidness(m2))
return 1;
else
return 2;
}
u8 face_contents(content_t m1, content_t m2, bool *equivalent);
/*
Packs directions like (1,0,0), (1,-1,0)

View File

@ -75,10 +75,45 @@ void signal_handler_init(void)
}
#else // _WIN32
#include <signal.h>
#include <windows.h>
BOOL WINAPI event_handler(DWORD sig)
{
switch(sig)
{
case CTRL_C_EVENT:
case CTRL_CLOSE_EVENT:
case CTRL_LOGOFF_EVENT:
case CTRL_SHUTDOWN_EVENT:
if(g_killed == false)
{
dstream<<DTIME<<"INFO: event_handler(): "
<<"Ctrl+C, Close Event, Logoff Event or Shutdown Event, shutting down."<<std::endl;
dstream<<DTIME<<"INFO: event_handler(): "
<<"Printing debug stacks"<<std::endl;
debug_stacks_print();
g_killed = true;
}
else
{
(void)signal(SIGINT, SIG_DFL);
}
break;
case CTRL_BREAK_EVENT:
break;
}
return TRUE;
}
void signal_handler_init(void)
{
// No-op
dstream<<"signal_handler_init()"<<std::endl;
SetConsoleCtrlHandler( (PHANDLER_ROUTINE)event_handler,TRUE);
}
#endif
@ -129,8 +164,8 @@ void initializePaths()
// Use "./bin/../data"
path_data = std::string(buf) + DIR_DELIM ".." DIR_DELIM "data";
// Use "./bin/../"
path_userdata = std::string(buf) + DIR_DELIM ".." DIR_DELIM;
// Use "./bin/.."
path_userdata = std::string(buf) + DIR_DELIM "..";
/*
Linux
@ -149,7 +184,7 @@ void initializePaths()
path_data = std::string(buf) + "/../data";
// Use "./bin/../"
path_userdata = std::string(buf) + "/../";
path_userdata = std::string(buf) + "/..";
/*
OS X
@ -160,7 +195,7 @@ void initializePaths()
dstream<<"WARNING: Relative path not properly supported on OS X and FreeBSD"
<<std::endl;
path_data = std::string("../data");
path_userdata = std::string("../");
path_userdata = std::string("..");
#endif

View File

@ -1777,14 +1777,13 @@ void Server::AsyncRunStep()
void Server::Receive()
{
DSTACK(__FUNCTION_NAME);
u32 data_maxsize = 10000;
Buffer<u8> data(data_maxsize);
SharedBuffer<u8> data;
u16 peer_id;
u32 datasize;
try{
{
JMutexAutoLock conlock(m_con_mutex);
datasize = m_con.Receive(peer_id, *data, data_maxsize);
datasize = m_con.Receive(peer_id, data);
}
// This has to be called so that the client list gets synced
@ -4808,8 +4807,7 @@ v3f findSpawnPos(ServerMap &map)
{
//return v3f(50,50,50)*BS;
v2s16 nodepos;
s16 groundheight = 0;
v3s16 nodepos;
#if 0
nodepos = v2s16(0,0);
@ -4822,13 +4820,11 @@ v3f findSpawnPos(ServerMap &map)
{
s32 range = 1 + i;
// We're going to try to throw the player to this position
nodepos = v2s16(-range + (myrand()%(range*2)),
v2s16 nodepos2d = v2s16(-range + (myrand()%(range*2)),
-range + (myrand()%(range*2)));
v2s16 sectorpos = getNodeSectorPos(nodepos);
// Get sector (NOTE: Don't get because it's slow)
//m_env.getMap().emergeSector(sectorpos);
//v2s16 sectorpos = getNodeSectorPos(nodepos2d);
// Get ground height at point (fallbacks to heightmap function)
groundheight = map.findGroundLevel(nodepos);
s16 groundheight = map.findGroundLevel(nodepos2d);
// Don't go underwater
if(groundheight < WATER_LEVEL)
{
@ -4841,22 +4837,33 @@ v3f findSpawnPos(ServerMap &map)
//infostream<<"-> Underwater"<<std::endl;
continue;
}
// Found a good place
//infostream<<"Searched through "<<i<<" places."<<std::endl;
break;
nodepos = v3s16(nodepos2d.X, groundheight-2, nodepos2d.Y);
bool is_good = false;
s32 air_count = 0;
for(s32 i=0; i<10; i++){
v3s16 blockpos = getNodeBlockPos(nodepos);
map.emergeBlock(blockpos, true);
MapNode n = map.getNodeNoEx(nodepos);
if(n.getContent() == CONTENT_AIR){
air_count++;
if(air_count >= 2){
is_good = true;
nodepos.Y -= 1;
break;
}
}
nodepos.Y++;
}
if(is_good){
// Found a good place
//infostream<<"Searched through "<<i<<" places."<<std::endl;
break;
}
}
#endif
// If no suitable place was not found, go above water at least.
if(groundheight < WATER_LEVEL)
groundheight = WATER_LEVEL;
return intToFloat(v3s16(
nodepos.X,
groundheight + 3,
nodepos.Y
), BS);
return intToFloat(nodepos, BS);
}
Player *Server::emergePlayer(const char *name, const char *password, u16 peer_id)

View File

@ -852,9 +852,9 @@ struct TestConnection
try
{
u16 peer_id;
u8 data[100];
SharedBuffer<u8> data;
infostream<<"** running client.Receive()"<<std::endl;
u32 size = client.Receive(peer_id, data, 100);
u32 size = client.Receive(peer_id, data);
infostream<<"** Client received: peer_id="<<peer_id
<<", size="<<size
<<std::endl;
@ -874,9 +874,9 @@ struct TestConnection
try
{
u16 peer_id;
u8 data[100];
SharedBuffer<u8> data;
infostream<<"** running server.Receive()"<<std::endl;
u32 size = server.Receive(peer_id, data, 100);
u32 size = server.Receive(peer_id, data);
infostream<<"** Server received: peer_id="<<peer_id
<<", size="<<size
<<std::endl;
@ -901,9 +901,9 @@ struct TestConnection
try
{
u16 peer_id;
u8 data[100];
SharedBuffer<u8> data;
infostream<<"** running client.Receive()"<<std::endl;
u32 size = client.Receive(peer_id, data, 100);
u32 size = client.Receive(peer_id, data);
infostream<<"** Client received: peer_id="<<peer_id
<<", size="<<size
<<std::endl;
@ -919,9 +919,9 @@ struct TestConnection
try
{
u16 peer_id;
u8 data[100];
SharedBuffer<u8> data;
infostream<<"** running server.Receive()"<<std::endl;
u32 size = server.Receive(peer_id, data, 100);
u32 size = server.Receive(peer_id, data);
infostream<<"** Server received: peer_id="<<peer_id
<<", size="<<size
<<std::endl;
@ -929,7 +929,10 @@ struct TestConnection
catch(con::NoIncomingDataException &e)
{
}
#if 1
/*
Simple send-receive test
*/
{
/*u8 data[] = "Hello World!";
u32 datasize = sizeof(data);*/
@ -941,22 +944,23 @@ struct TestConnection
sleep_ms(50);
u16 peer_id;
u8 recvdata[100];
SharedBuffer<u8> recvdata;
infostream<<"** running server.Receive()"<<std::endl;
u32 size = server.Receive(peer_id, recvdata, 100);
u32 size = server.Receive(peer_id, recvdata);
infostream<<"** Server received: peer_id="<<peer_id
<<", size="<<size
<<", data="<<*data
<<std::endl;
assert(memcmp(*data, recvdata, data.getSize()) == 0);
assert(memcmp(*data, *recvdata, data.getSize()) == 0);
}
#endif
u16 peer_id_client = 2;
#if 0
/*
Send consequent packets in different order
Not compatible with new Connection, thus commented out.
*/
{
/*
Send consequent packets in different order
*/
//u8 data1[] = "hello1";
//u8 data2[] = "hello2";
SharedBuffer<u8> data1 = SharedBufferFromString("hello1");
@ -983,29 +987,29 @@ struct TestConnection
infostream<<"*** Receiving the packets"<<std::endl;
u16 peer_id;
u8 recvdata[20];
SharedBuffer<u8> recvdata;
u32 size;
infostream<<"** running client.Receive()"<<std::endl;
peer_id = 132;
size = client.Receive(peer_id, recvdata, 20);
size = client.Receive(peer_id, recvdata);
infostream<<"** Client received: peer_id="<<peer_id
<<", size="<<size
<<", data="<<recvdata
<<", data="<<*recvdata
<<std::endl;
assert(size == data1.getSize());
assert(memcmp(*data1, recvdata, data1.getSize()) == 0);
assert(memcmp(*data1, *recvdata, data1.getSize()) == 0);
assert(peer_id == PEER_ID_SERVER);
infostream<<"** running client.Receive()"<<std::endl;
peer_id = 132;
size = client.Receive(peer_id, recvdata, 20);
size = client.Receive(peer_id, recvdata);
infostream<<"** Client received: peer_id="<<peer_id
<<", size="<<size
<<", data="<<recvdata
<<", data="<<*recvdata
<<std::endl;
assert(size == data2.getSize());
assert(memcmp(*data2, recvdata, data2.getSize()) == 0);
assert(memcmp(*data2, *recvdata, data2.getSize()) == 0);
assert(peer_id == PEER_ID_SERVER);
bool got_exception = false;
@ -1013,10 +1017,10 @@ struct TestConnection
{
infostream<<"** running client.Receive()"<<std::endl;
peer_id = 132;
size = client.Receive(peer_id, recvdata, 20);
size = client.Receive(peer_id, recvdata);
infostream<<"** Client received: peer_id="<<peer_id
<<", size="<<size
<<", data="<<recvdata
<<", data="<<*recvdata
<<std::endl;
}
catch(con::NoIncomingDataException &e)
@ -1027,6 +1031,47 @@ struct TestConnection
assert(got_exception);
}
#endif
#if 0
/*
Send large amounts of packets (infinite test)
Commented out because of infinity.
*/
{
infostream<<"Sending large amounts of packets (infinite test)"<<std::endl;
int sendcount = 0;
for(;;){
int datasize = myrand_range(0,5)==0?myrand_range(100,10000):myrand_range(0,100);
infostream<<"datasize="<<datasize<<std::endl;
SharedBuffer<u8> data1(datasize);
for(u16 i=0; i<datasize; i++)
data1[i] = i/4;
int sendtimes = myrand_range(1,10);
for(int i=0; i<sendtimes; i++){
server.Send(peer_id_client, 0, data1, true);
sendcount++;
}
infostream<<"sendcount="<<sendcount<<std::endl;
//int receivetimes = myrand_range(1,20);
int receivetimes = 20;
for(int i=0; i<receivetimes; i++){
SharedBuffer<u8> recvdata;
u16 peer_id = 132;
u16 size = 0;
bool received = false;
try{
size = client.Receive(peer_id, recvdata);
received = true;
}catch(con::NoIncomingDataException &e){
}
}
}
}
#endif
/*
Send a large packet
*/
{
const int datasize = 30000;
SharedBuffer<u8> data1(datasize);
@ -1047,7 +1092,7 @@ struct TestConnection
sleep_ms(3000);
u8 recvdata[datasize + 1000];
SharedBuffer<u8> recvdata;
infostream<<"** running client.Receive()"<<std::endl;
u16 peer_id = 132;
u16 size = 0;
@ -1057,7 +1102,7 @@ struct TestConnection
if(porting::getTimeMs() - timems0 > 5000)
break;
try{
size = client.Receive(peer_id, recvdata, datasize + 1000);
size = client.Receive(peer_id, recvdata);
received = true;
}catch(con::NoIncomingDataException &e){
}
@ -1071,13 +1116,13 @@ struct TestConnection
infostream<<"Received data (size="<<size<<"):";
for(int i=0; i<size && i<20; i++){
if(i%2==0) DEBUGPRINT(" ");
DEBUGPRINT("%.2X", ((int)((const char*)recvdata)[i])&0xff);
DEBUGPRINT("%.2X", ((int)(recvdata[i]))&0xff);
}
if(size>20)
infostream<<"...";
infostream<<std::endl;
assert(memcmp(*data1, recvdata, data1.getSize()) == 0);
assert(memcmp(*data1, *recvdata, data1.getSize()) == 0);
assert(peer_id == PEER_ID_SERVER);
}

View File

@ -236,21 +236,21 @@ bool isBlockInSight(v3s16 blockpos_b, v3f camera_pos, v3f camera_dir,
// If block is (nearly) touching the camera, don't
// bother validating further (that is, render it anyway)
if(d > block_max_radius)
{
// Cosine of the angle between the camera direction
// and the block direction (camera_dir is an unit vector)
f32 cosangle = dforward / d;
// Compensate for the size of the block
// (as the block has to be shown even if it's a bit off FOV)
// This is an estimate.
cosangle += block_max_radius / dforward;
if(d < block_max_radius)
return true;
// Cosine of the angle between the camera direction
// and the block direction (camera_dir is an unit vector)
f32 cosangle = dforward / d;
// Compensate for the size of the block
// (as the block has to be shown even if it's a bit off FOV)
// This is an estimate, plus an arbitary factor
cosangle += block_max_radius / d * 0.5;
// If block is not in the field of view, skip it
if(cosangle < cos(camera_fov / 2))
return false;
}
// If block is not in the field of view, skip it
if(cosangle < cos(camera_fov / 2))
return false;
return true;
}

View File

@ -222,13 +222,13 @@ inline u16 readU16(std::istream &is)
return readU16((u8*)buf);
}
inline void writeU32(std::ostream &os, u16 p)
inline void writeU32(std::ostream &os, u32 p)
{
char buf[4];
writeU16((u8*)buf, p);
os.write(buf, 4);
}
inline u16 readU32(std::istream &is)
inline u32 readU32(std::istream &is)
{
char buf[4];
is.read(buf, 4);
@ -343,26 +343,59 @@ template <typename T>
class Buffer
{
public:
Buffer()
{
m_size = 0;
data = NULL;
}
Buffer(unsigned int size)
{
m_size = size;
data = new T[size];
if(size != 0)
data = new T[size];
else
data = NULL;
}
Buffer(const Buffer &buffer)
{
m_size = buffer.m_size;
data = new T[buffer.m_size];
memcpy(data, buffer.data, buffer.m_size);
if(m_size != 0)
{
data = new T[buffer.m_size];
memcpy(data, buffer.data, buffer.m_size);
}
else
data = NULL;
}
Buffer(T *t, unsigned int size)
{
m_size = size;
data = new T[size];
memcpy(data, t, size);
if(size != 0)
{
data = new T[size];
memcpy(data, t, size);
}
else
data = NULL;
}
~Buffer()
{
delete[] data;
drop();
}
Buffer& operator=(const Buffer &buffer)
{
if(this == &buffer)
return *this;
drop();
m_size = buffer.m_size;
if(m_size != 0)
{
data = new T[buffer.m_size];
memcpy(data, buffer.data, buffer.m_size);
}
else
data = NULL;
return *this;
}
T & operator[](unsigned int i) const
{
@ -377,6 +410,11 @@ public:
return m_size;
}
private:
void drop()
{
if(data)
delete[] data;
}
T *data;
unsigned int m_size;
};
@ -471,6 +509,10 @@ public:
{
return m_size;
}
operator Buffer<T>() const
{
return Buffer<T>(data, m_size);
}
private:
void drop()
{