Merge branch 'master' of git://github.com/celeron55/minetest
Conflicts: src/game.cpp
This commit is contained in:
commit
21fa08bba3
@ -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}")
|
||||
|
||||
|
49
README.txt
49
README.txt
@ -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
|
||||
-----------------------
|
||||
|
||||
|
254
doc/README.txt
254
doc/README.txt
@ -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.
|
||||
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -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
|
||||
|
@ -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.
|
||||
|
41
src/game.cpp
41
src/game.cpp
@ -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(
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
31
src/main.cpp
31
src/main.cpp
@ -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));
|
||||
|
||||
|
280
src/map.cpp
280
src/map.cpp
@ -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",
|
||||
|
@ -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] =
|
||||
|
@ -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)
|
||||
{
|
||||
/*
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
||||
|
@ -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)
|
||||
|
103
src/test.cpp
103
src/test.cpp
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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()
|
||||
{
|
||||
|
Loading…
x
Reference in New Issue
Block a user