Merge remote-tracking branch 'origin/master' into STK-helper-ItemWeights

This commit is contained in:
hiker 2018-06-17 01:05:07 +10:00
commit 6bcd1b4c58
59 changed files with 676 additions and 439 deletions

253
INSTALL.md Normal file
View File

@ -0,0 +1,253 @@
## Building from source
In order to build SuperTuxKart from source, you'll need both the code and the assets (See <https://supertuxkart.net/Source_control> for more information):
```bash
git clone https://github.com/supertuxkart/stk-code stk-code
svn co https://svn.code.sf.net/p/supertuxkart/code/stk-assets stk-assets
```
## Building SuperTuxKart on Linux
### Dependencies
To build SuperTuxKart from source, you'll need to install the following packages:
* OpenGL (mesa)
* OpenAL (recommended: openal-soft-devel)
* Ogg (libogg-dev)
* Vorbis (libvorbis-dev)
* Freetype (libfreetype6-dev)
* libcurl (libcurl-devel)
* libbluetooth (bluez-devel)
* libpng (libpng-devel)
* zlib (zlib-devel)
* jpeg (libjpeg-turbo-devel)
Ubuntu command:
```bash
sudo apt-get install build-essential cmake libbluetooth-dev \
libcurl4-openssl-dev libenet-dev libfreetype6-dev libfribidi-dev \
libgl1-mesa-dev libglew-dev libjpeg-dev libogg-dev libopenal-dev libpng-dev \
libssl-dev libvorbis-dev libxrandr-dev libx11-dev pkg-config zlib1g-dev
```
Fedora command:
```bash
sudo dnf install @development-tools cmake bluez-libs-devel \
openssl-devel libcurl-devel freetype-devel fribidi-devel mesa-libGL-devel \
libjpeg-turbo-devel libogg-devel openal-soft-devel libpng-devel \
libvorbis-devel libXrandr-devel libGLEW pkgconf zlib-devel
```
### In-game recorder
To build the in-game recorder for STK, you have to install
libopenglrecorder from your distribution, or compile it yourself from [here](https://github.com/Benau/libopenglrecorder).
Compilation instruction is explained there. If you don't need this feature, pass `-DBUILD_RECORDER=off` to cmake.
### Compiling
To compile SuperTuxKart, run the following commands inside `stk-code` directory:
```bash
mkdir cmake_build
cd cmake_build
cmake ..
make -j4
```
STK can then be run from the build directory with `bin/supertuxkart`
#### Keeping your build up to date
To recompile the latest code without redownloading the entire source, first run the ```svn up``` command inside the 'stk-assets' directory, then run the following commands inside the 'stk-code' directory:
```bash
git pull
cd cmake_build
cmake ..
make -j4
```
##### Build Speed Optimization
"-j4" is an example, for a faster build, use "-jx" instead, where "x" is the amount of CPU threads you have, minus one. "-j$(nproc)" usually works.
### Further options
To create a debug version of STK, run:
```bash
cmake .. -DCMAKE_BUILD_TYPE=Debug
```
You can install your build system-wide:
```bash
sudo make install
```
The default install location is `/usr/local`, i.e. the data files will
be written to `/usr/local/share/games/supertuxkart`, the executable
will be copied to `/usr/local/bin`. To change the default installation
location, specify `CMAKE_INSTALL_PREFIX` when running cmake, e.g.:
`cmake .. -DCMAKE_INSTALL_PREFIX=/opt/stk`
## Building SuperTuxKart on Windows
To Build SuperTuxKart on Windows, follow these instructions:
1. Download and install Visual Studio from here: [Visual Studio - Download](https://www.visualstudio.com/downloads/). The free Visual Studio Community edition works fine.
2. Download the SuperTuxKart source package from either [SuperTuxKart download area - SourceForge.net](https://sourceforge.net/projects/supertuxkart/files/SuperTuxKart/) or [SuperTuxKart.net - Source Control](https://supertuxkart.net/Source_control), and unpack it.
*Note: If you downloaded the source package from here: [SuperTuxKart.net - Source Control](https://supertuxkart.net/Source_control), then both `stk-code` and `stk-assets` **must** be in the same directory, otherwise the build can result in failure*
3. Download the Windows dependencies package from either [SuperTuxKart download area: Dependencies - SourceForge.net](https://sourceforge.net/projects/supertuxkart/files/SuperTuxKart%20Dependencies/Windows/)
or [SuperTuxKart on GitHub - Dependencies](https://github.com/supertuxkart/dependencies), and unpack it; then, copy the `dependencies` directory from either the `windows` or the `windows_64bit` directories into the `stk-code` directory, rename it to `dependencies-64bit` if you want to compile a 64bit build.
4. Download CMake from here: [CMake - download page](https://cmake.org/download/), install it; once CMake is installed, double click on the CMake icon on your desktop, and point it towards your `stk-code` directory in the 'Where is the source code' field, and point it to a directory called `build` or `bld` inside the stk-code directory.
5. Press 'Configure'; CMake will ask you if it is OK to create the aforementioned directory, press `Yes`. CMake will then ask you about your version of Visual Studio.
Confirm your selection; *Please look at the table below to avoid confusion between version numbers and releases of Visual Studio*;
CMake will begin creating the required files for the build in the directory.
6. Navigate to your build directory and open the `SuperTuxKart.sln` file; Visual Studio will now load the solution.
7. In the 'Solution Explorer', right click on the `supertuxkart` project and select "Set as StartUp project"
8. Open the 'Build' menu and select 'Build Solution'; or, press the default keyboard shortcut: `CTRL + SHIFT + B` to build the solution.
*Note: To avoid confusion between releases and versions, refer to this table:*
Visual Studio Release | Version
----------------------|------------
Visual Studio 2017| 15
Visual Studio 2015| 14
Visual Studio 2013| 13
## Building SuperTuxKart on Windows (from PowerShell/Command line)
1. Download and install Visual Studio from here: [Visual Studio - Download](https://www.visualstudio.com/downloads/), the free Visual Studio Community edition works fine.
2. Download a source package from either [SuperTuxKart 0.9.2 download area - SourceForge.net](https://sourceforge.net/projects/supertuxkart/files/SuperTuxKart/0.9.2) or [SuperTuxKart.net - Source Control](https://supertuxkart.net/Source_control)
NOTE: the `stk-code` and `stk-assets` directories **must** be in the same directory
3. Download the Windows dependencies package from either [SuperTuxKart download area - SourceForge.net](https://sourceforge.net/projects/supertuxkart/files/SuperTuxKart%20Dependencies/Windows/)
or [SuperTuxKart on GitHub - Dependencies](https://github.com/supertuxkart/dependencies)
and unpack the archive; once unpacked, copy the `dependencies` directory from either the `windows` or the `windows_64bit` directories into the `stk-code` directory
4. Download CMake from here: [CMake - download page](https://cmake.org/download/); and install it. Navigate to the `stk-code` directory; and create an directory called "build":
```cmd
mkdir build
cd build
```
5. Once inside the build directory; run CMake to start the compilation process:
```cmd
cmake ..
```
6. Now that CMake finished configuring and creating the necessary files for the build, run the build command in the same directory:
```cmd
msbuild.exe SuperTuxKart.sln
```
SuperTuxKart can now be run as `bin\Debug\supertuxkart.exe` or `bin\Release\supertuxkart.exe`
## Building SuperTuxKart on macOS
### Getting Started
Install the developer tools, either from the OS X Install DVD or from Apple's website.
If you have never built anything before, you have create `/usr/local/include/` first:
```bash
sudo mkdir -p /usr/local/include/
```
Symlink the `include`-folder of OpenGL framework to `/usr/local/include/GL` (Unix programs have an easier time finding it this way):
```bash
sudo ln -s /System/Library/Frameworks/OpenGL.framework/Versions/A/Headers/ /usr/local/include/GL
```
On OS X 10.9.5, you might need the following workaround:
```bash
sudo ln -s `xcrun --show-sdk-path`/usr/include/ /usr/include
sudo ln -s `xcrun --show-sdk-path`/System/Library/Frameworks/OpenGL.framework/Headers/ /usr/local/include/OpenGL
```
The first link is required in order to find libcurl, the second to find opengl.
### CMake
CMake is used to build STK. At this time CMake will not make a binary that is ready for distribution.
You'll have to run these commands inside your stk-code directory.
### STK 0.9.4 or later (or latest git)
Install homebrew ( https://brew.sh/)
Install all of the dependencies using homebrew :
```bash
brew install libogg
brew install libvorbis
brew install openal-soft
brew install freetype
brew install curl
brew install openssl@1.1
brew install fribidi
brew install glew
```
Build STK
```bash
mkdir cmake_build
cd cmake_build
CMAKE_PREFIX_PATH=/usr/local/opt/freetype/:/usr/local/opt/curl/:/usr/local/opt/libogg/:/usr/local/opt/libogg/:/usr/local/opt/libvorbis/:/usr/local/opt/openssl\@1.1/:/usr/local/opt/glew/:/usr/local/opt/fribidi/ /usr/local/opt/cmake/bin/cmake .. -DFREETYPE_INCLUDE_DIRS=/usr/local/opt/freetype/include/freetype2/ -DUSE_SYSTEM_GLEW=1 -DOPENAL_INCLUDE_DIR=/usr/local/opt/openal-soft/include/ -DOPENAL_LIBRARY=/usr/local/opt/openal-soft/lib/libopenal.dylib
make
```
#### (Optional) packaging for distribution
By default, the executable that is produced is not ready for distribution. Install https://github.com/auriamg/macdylibbundler
```bash
dylibbundler -od -b -x ./bin/SuperTuxKart.app/Contents/MacOS/supertuxkart -d ./bin/SuperTuxKart.app/Contents/libs/ -p @executable_path/../libs/
```
then copy the datafiles into /SuperTuxKart.app/Contents/Resources/data
### STK 0.9.3 or earlier
Download pre-built dependencies from [here](https://sourceforge.net/projects/supertuxkart/files/SuperTuxKart%20Dependencies/OSX/) and put the frameworks in [hard disk root]/Library/Frameworks
Building with clang:
```bash
mkdir cmake_build
cd cmake_build
cmake ..
make
```
Building with GCC:
```bash
mkdir cmake_build
cd cmake_build
cmake .. -DCMAKE_CXX_COMPILER=/usr/bin/g++ -DCMAKE_C_COMPILER=/usr/bin/gcc
make
```
Building on 10.10 with 10.9 compatibility:
```bash
cmake .. -DCMAKE_OSX_SYSROOT=/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.9.sdk -DCMAKE_OSX_DEPLOYMENT_TARGET=10.9
```
#### Xcode
Place an additional copy of the dependencies into `Users/<YOUR_USERNAME>/Library/Frameworks`.
Then cd to your cloned stk-code directory and execute the following commands:
```bash
mkdir xcode_build && cd xcode_build
cmake .. -GXcode
```
Use Finder to navigate to your stk-code/xcode_build folder and open the newly generated Xcode project (`SuperTuxKart.xcodeproj`).
You can then build the project in Xcode using Product -> Build
Note: Xcode is much less well tested than makefiles, so there may be issues when trying to use Xcode.

244
README.md
View File

@ -30,246 +30,4 @@ The export utilities perform the needed transformation, so in Blender you just
## Building from source
In order to build SuperTuxKart from source, you'll need both the code and the assets (See <https://supertuxkart.net/Source_control> for more information):
```bash
git clone https://github.com/supertuxkart/stk-code stk-code
svn co https://svn.code.sf.net/p/supertuxkart/code/stk-assets stk-assets
```
## Building SuperTuxKart on Linux
### Dependencies
To build SuperTuxKart from source, you'll need to install the following packages:
* OpenGL (mesa)
* OpenAL (recommended: openal-soft-devel)
* Ogg (libogg-dev)
* Vorbis (libvorbis-dev)
* Freetype (libfreetype6-dev)
* libcurl (libcurl-devel)
* libbluetooth (bluez-devel)
* libpng (libpng-devel)
* zlib (zlib-devel)
* jpeg (libjpeg-turbo-devel)
Ubuntu command:
```bash
sudo apt-get install build-essential cmake libbluetooth-dev \
libcurl4-gnutls-dev libfreetype6-dev libfribidi-dev libgl1-mesa-dev \
libjpeg-dev libogg-dev libopenal-dev libpng-dev libvorbis-dev libxrandr-dev \
mesa-common-dev pkg-config zlib1g-dev
```
### In-game recorder
To build the in-game recorder for STK, you have to install
libopenglrecorder from your distribution, or compile it yourself from [here](https://github.com/Benau/libopenglrecorder).
Compilation instruction is explained there. If you don't need this feature, pass `-DBUILD_RECORDER=off` to cmake.
### Compiling
To compile SuperTuxKart, run the following commands inside `stk-code` directory:
```bash
mkdir cmake_build
cd cmake_build
cmake ..
make -j4
```
STK can then be run from the build directory with `bin/supertuxkart`
#### Keeping your build up to date
To recompile the latest code without redownloading the entire source, first run the ```svn up``` command inside the 'stk-assets' directory, then run the following commands inside the 'stk-code' directory:
```bash
git pull
cd cmake_build
cmake ..
make -j4
```
##### Build Speed Optimization
"-j4" is an example, for a faster build, use "-jx" instead, where "x" is the amount of CPU threads you have, minus one.
### Further options
To create a debug version of STK, run:
```bash
cmake .. -DCMAKE_BUILD_TYPE=Debug
```
You can install your build system-wide:
```bash
sudo make install
```
The default install location is `/usr/local`, i.e. the data files will
be written to `/usr/local/share/games/supertuxkart`, the executable
will be copied to `/usr/local/bin`. To change the default installation
location, specify `CMAKE_INSTALL_PREFIX` when running cmake, e.g.:
`cmake .. -DCMAKE_INSTALL_PREFIX=/opt/stk`
## Building SuperTuxKart on Windows
To Build SuperTuxKart on Windows, follow these instructions:
1. Download and install Visual Studio from here: [Visual Studio - Download](https://www.visualstudio.com/downloads/). The free Visual Studio Community edition works fine.
2. Download the SuperTuxKart source package from either [SuperTuxKart download area - SourceForge.net](https://sourceforge.net/projects/supertuxkart/files/SuperTuxKart/) or [SuperTuxKart.net - Source Control](https://supertuxkart.net/Source_control), and unpack it.
*Note: If you downloaded the source package from here: [SuperTuxKart.net - Source Control](https://supertuxkart.net/Source_control), then both `stk-code` and `stk-assets` **must** be in the same directory, otherwise the build can result in failure*
3. Download the Windows dependencies package from either [SuperTuxKart download area: Dependencies - SourceForge.net](https://sourceforge.net/projects/supertuxkart/files/SuperTuxKart%20Dependencies/Windows/)
or [SuperTuxKart on GitHub - Dependencies](https://github.com/supertuxkart/dependencies), and unpack it; then, copy the `dependencies` directory from either the `windows` or the `windows_64bit` directories into the `stk-code` directory, rename it to `dependencies-64bit` if you want to compile a 64bit build.
4. Download CMake from here: [CMake - download page](https://cmake.org/download/), install it; once CMake is installed, double click on the CMake icon on your desktop, and point it towards your `stk-code` directory in the 'Where is the source code' field, and point it to a directory called `build` or `bld` inside the stk-code directory.
5. Press 'Configure'; CMake will ask you if it is OK to create the aforementioned directory, press `Yes`. CMake will then ask you about your version of Visual Studio.
Confirm your selection; *Please look at the table below to avoid confusion between version numbers and releases of Visual Studio*;
CMake will begin creating the required files for the build in the directory.
6. Navigate to your build directory and open the `SuperTuxKart.sln` file; Visual Studio will now load the solution.
7. In the 'Solution Explorer', right click on the `supertuxkart` project and select "Set as StartUp project"
8. Open the 'Build' menu and select 'Build Solution'; or, press the default keyboard shortcut: `CTRL + SHIFT + B` to build the solution.
*Note: To avoid confusion between releases and versions, refer to this table:*
Visual Studio Release | Version
----------------------|------------
Visual Studio 2017| 15
Visual Studio 2015| 14
Visual Studio 2013| 13
## Building SuperTuxKart on Windows (from PowerShell/Command line)
1. Download and install Visual Studio from here: [Visual Studio - Download](https://www.visualstudio.com/downloads/), the free Visual Studio Community edition works fine.
2. Download a source package from either [SuperTuxKart 0.9.2 download area - SourceForge.net](https://sourceforge.net/projects/supertuxkart/files/SuperTuxKart/0.9.2) or [SuperTuxKart.net - Source Control](https://supertuxkart.net/Source_control)
NOTE: the `stk-code` and `stk-assets` directories **must** be in the same directory
3. Download the Windows dependencies package from either [SuperTuxKart download area - SourceForge.net](https://sourceforge.net/projects/supertuxkart/files/SuperTuxKart%20Dependencies/Windows/)
or [SuperTuxKart on GitHub - Dependencies](https://github.com/supertuxkart/dependencies)
and unpack the archive; once unpacked, copy the `dependencies` directory from either the `windows` or the `windows_64bit` directories into the `stk-code` directory
4. Download CMake from here: [CMake - download page](https://cmake.org/download/); and install it. Navigate to the `stk-code` directory; and create an directory called "build":
```cmd
mkdir build
cd build
```
5. Once inside the build directory; run CMake to start the compilation process:
```cmd
cmake ..
```
6. Now that CMake finished configuring and creating the necessary files for the build, run the build command in the same directory:
```cmd
msbuild.exe SuperTuxKart.sln
```
SuperTuxKart can now be run as `bin\Debug\supertuxkart.exe` or `bin\Release\supertuxkart.exe`
## Building SuperTuxKart on macOS
### Getting Started
Install the developer tools, either from the OS X Install DVD or from Apple's website.
If you have never built anything before, you have create `/usr/local/include/` first:
```bash
sudo mkdir -p /usr/local/include/
```
Symlink the `include`-folder of OpenGL framework to `/usr/local/include/GL` (Unix programs have an easier time finding it this way):
```bash
sudo ln -s /System/Library/Frameworks/OpenGL.framework/Versions/A/Headers/ /usr/local/include/GL
```
On OS X 10.9.5, you might need the following workaround:
```bash
sudo ln -s `xcrun --show-sdk-path`/usr/include/ /usr/include
sudo ln -s `xcrun --show-sdk-path`/System/Library/Frameworks/OpenGL.framework/Headers/ /usr/local/include/OpenGL
```
The first link is required in order to find libcurl, the second to find opengl.
### CMake
CMake is used to build STK. At this time CMake will not make a binary that is ready for distribution.
You'll have to run these commands inside your stk-code directory.
### STK 0.9.4 or later (or latest git)
Install homebrew ( https://brew.sh/)
Install all of the dependencies using homebrew :
```bash
brew install libogg
brew install libvorbis
brew install openal-soft
brew install freetype
brew install curl
brew install openssl@1.1
brew install fribidi
brew install glew
```
Build STK
```bash
mkdir cmake_build
cd cmake_build
CMAKE_PREFIX_PATH=/usr/local/opt/freetype/:/usr/local/opt/curl/:/usr/local/opt/libogg/:/usr/local/opt/libogg/:/usr/local/opt/libvorbis/:/usr/local/opt/openssl\@1.1/:/usr/local/opt/glew/:/usr/local/opt/fribidi/ /usr/local/opt/cmake/bin/cmake .. -DFREETYPE_INCLUDE_DIRS=/usr/local/opt/freetype/include/freetype2/ -DUSE_SYSTEM_GLEW=1 -DOPENAL_INCLUDE_DIR=/usr/local/opt/openal-soft/include/ -DOPENAL_LIBRARY=/usr/local/opt/openal-soft/lib/libopenal.dylib
make
```
#### (Optional) packaging for distribution
By default, the executable that is produced is not ready for distribution. Install https://github.com/auriamg/macdylibbundler
```bash
dylibbundler -od -b -x ./bin/SuperTuxKart.app/Contents/MacOS/supertuxkart -d ./bin/SuperTuxKart.app/Contents/libs/ -p @executable_path/../libs/
```
then copy the datafiles into /SuperTuxKart.app/Contents/Resources/data
### STK 0.9.3 or earlier
Download pre-built dependencies from [here](https://sourceforge.net/projects/supertuxkart/files/SuperTuxKart%20Dependencies/OSX/) and put the frameworks in [hard disk root]/Library/Frameworks
Building with clang:
```bash
mkdir cmake_build
cd cmake_build
cmake ..
make
```
Building with GCC:
```bash
mkdir cmake_build
cd cmake_build
cmake .. -DCMAKE_CXX_COMPILER=/usr/bin/g++ -DCMAKE_C_COMPILER=/usr/bin/gcc
make
```
Building on 10.10 with 10.9 compatibility:
```bash
cmake .. -DCMAKE_OSX_SYSROOT=/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.9.sdk -DCMAKE_OSX_DEPLOYMENT_TARGET=10.9
```
#### Xcode
Place an additional copy of the dependencies into `Users/<YOUR_USERNAME>/Library/Frameworks`.
Then cd to your cloned stk-code directory and execute the following commands:
```bash
mkdir xcode_build && cd xcode_build
cmake .. -GXcode
```
Use Finder to navigate to your stk-code/xcode_build folder and open the newly generated Xcode project (`SuperTuxKart.xcodeproj`).
You can then build the project in Xcode using Product -> Build
Note: Xcode is much less well tested than makefiles, so there may be issues when trying to use Xcode.
Building instructions can be found in [`INSTALL.md`](/INSTALL.md)

View File

@ -9,7 +9,7 @@
# FRIBIDI_LIBRARIES
# Fribidi library list
if(UNIX)
if(UNIX AND NOT APPLE)
include(FindPkgConfig)
pkg_check_modules(FRIBIDI fribidi)
else()

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 KiB

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 KiB

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.3 KiB

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.4 KiB

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 KiB

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.5 KiB

After

Width:  |  Height:  |  Size: 4.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.6 KiB

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 KiB

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.3 KiB

After

Width:  |  Height:  |  Size: 3.8 KiB

View File

@ -2753,26 +2753,26 @@ namespace video
void COGLES2CallBridge::setBlendFunc(GLenum source, GLenum destination)
{
if(BlendSource != source || BlendDestination != destination)
{
//if(BlendSource != source || BlendDestination != destination)
//{
glBlendFunc(source, destination);
BlendSource = source;
BlendDestination = destination;
}
//}
}
void COGLES2CallBridge::setBlend(bool enable)
{
if(Blend != enable)
{
//if(Blend != enable)
//{
if (enable)
glEnable(GL_BLEND);
else
glDisable(GL_BLEND);
Blend = enable;
}
//}
}
void COGLES2CallBridge::setCullFaceFunc(GLenum mode)

View File

@ -18,6 +18,8 @@
\page addons Addons
*/
#ifndef SERVER_ONLY
#include "addons/addons_manager.hpp"
#include "addons/news_manager.hpp"
@ -614,3 +616,4 @@ void AddonsManager::saveInstalled()
xml_installed.close();
} // saveInstalled
#endif

View File

@ -19,6 +19,8 @@
#ifndef HEADER_ADDONS_MANAGER_HPP
#define HEADER_ADDONS_MANAGER_HPP
#ifndef SERVER_ONLY
#include <string>
#include <map>
#include <vector>
@ -89,5 +91,6 @@ public:
}; // class AddonsManager
extern AddonsManager *addons_manager;
#endif
#endif
#endif

View File

@ -15,6 +15,8 @@
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#ifndef SERVER_ONLY
#include "addons/news_manager.hpp"
#include "config/user_config.hpp"
@ -490,3 +492,5 @@ bool NewsManager::conditionFulfilled(const std::string &cond)
} // conditionFulfilled
// ----------------------------------------------------------------------------
#endif

View File

@ -18,6 +18,8 @@
#ifndef HEADER_NEWS_MANAGER_HPP
#define HEADER_NEWS_MANAGER_HPP
#ifndef SERVER_ONLY
#include <string>
#include <vector>
@ -143,4 +145,4 @@ public:
extern NewsManager *news_manager;
#endif
#endif

View File

@ -31,6 +31,7 @@
StoryModeStatus::StoryModeStatus(const XMLNode *node)
{
m_points = 0;
m_points_before = 0;
m_next_unlock_points = 0;
m_first_time = true;
m_easy_challenges = 0;
@ -79,6 +80,7 @@ bool StoryModeStatus::isLocked(const std::string& feature)
//-----------------------------------------------------------------------------
void StoryModeStatus::computeActive()
{
int old_points = m_points;
m_points = 0;
m_next_unlock_points = 0;
m_easy_challenges = 0;
@ -182,6 +184,9 @@ void StoryModeStatus::computeActive()
// now we have the number of points.
if (old_points != m_points)
m_points_before = old_points;
unlockFeatureByList();
//Actually lock the tracks

View File

@ -62,6 +62,7 @@ private:
const ChallengeStatus *m_current_challenge;
int m_points;
int m_points_before; // used for unlocks
int m_next_unlock_points;
/** Set to false after the initial stuff (intro, select kart, etc.) */
@ -101,6 +102,9 @@ public:
/** Returns the number of points accumulated. */
int getPoints () const { return m_points; }
// ------------------------------------------------------------------------
/** Returns the number of points before the previous point increase */
int getPointsBefore () const { return m_points_before; }
// ------------------------------------------------------------------------
/** Returns the number of points needed by the next unlockable. 0 if none. */
int getNextUnlockPoints () const { return m_next_unlock_points; }
// ------------------------------------------------------------------------

View File

@ -230,6 +230,8 @@ public:
// ------------------------------------------------------------------------
unsigned int getPoints() const { return m_story_mode_status->getPoints(); }
// ------------------------------------------------------------------------
unsigned int getPointsBefore() const { return m_story_mode_status->getPointsBefore(); }
// ------------------------------------------------------------------------
unsigned int getNextUnlockPoints() const { return m_story_mode_status->getNextUnlockPoints(); }
// ------------------------------------------------------------------------
void setFirstTime(bool b) { m_story_mode_status->setFirstTime(b); }

View File

@ -995,6 +995,10 @@ namespace UserConfigParams
PARAM_DEFAULT( BoolUserConfigParam(false, "everything_unlocked",
"Enable all karts and tracks") );
PARAM_PREFIX StringUserConfigParam m_commandline
PARAM_DEFAULT( StringUserConfigParam("", "commandline",
"Allows to set commandline args in config file") );
// TODO? implement blacklist for new irrlicht device and GUI
PARAM_PREFIX std::vector<std::string> m_blacklist_res;

View File

@ -160,6 +160,9 @@ void IconButtonWidget::add()
m_element = btn;
m_id = m_element->getID();
if (!m_is_visible)
m_element->setVisible(false);
// ---- label if any
const stringw& message = getText();
if (message.size() > 0)
@ -222,6 +225,11 @@ void IconButtonWidget::add()
m_label->setVisible(false);
}
if (!m_is_visible)
{
m_label->setVisible(false);
}
setLabelFont();
m_label->setRightToLeft(translations->isRTLText(message));

View File

@ -60,10 +60,18 @@ void AssetsAndroid::init()
paths.push_back(getenv("SUPERTUXKART_DATADIR"));
if (global_android_app->activity->externalDataPath)
{
m_file_manager->checkAndCreateDirectoryP(
global_android_app->activity->externalDataPath);
paths.push_back(global_android_app->activity->externalDataPath);
}
if (global_android_app->activity->internalDataPath)
{
m_file_manager->checkAndCreateDirectoryP(
global_android_app->activity->internalDataPath);
paths.push_back(global_android_app->activity->internalDataPath);
}
if (getenv("EXTERNAL_STORAGE"))
paths.push_back(getenv("EXTERNAL_STORAGE"));

View File

@ -146,6 +146,7 @@ public:
} // ItemState(ItemType)
// ------------------------------------------------------------------------
virtual ~ItemState() {}
void setDisappearCounter();
void update(int ticks);
virtual void collected(const AbstractKart *kart);

View File

@ -543,6 +543,8 @@ void ItemManager::switchItems()
ItemState::ItemType new_type = m_switch_to[(*i)->getType()];
if (new_type == (*i)->getType())
continue;
if(m_switch_ticks<0)
(*i)->switchTo(new_type, m_item_mesh[(int)new_type], m_item_lowres_mesh[(int)new_type]);
else

View File

@ -30,10 +30,12 @@
#include <assert.h>
#include <map>
#include <memory>
#include <string>
#include <vector>
class Kart;
class STKPeer;
/**
* \ingroup items
@ -129,7 +131,8 @@ public:
bool randomItemsForArena(const AlignedArray<btTransform>& pos);
// ------------------------------------------------------------------------
/** Only used in the NetworkItemManager. */
virtual void setItemConfirmationTime(int host_id, int ticks)
virtual void setItemConfirmationTime(std::weak_ptr<STKPeer> peer,
int ticks)
{
assert(false);
}

View File

@ -24,7 +24,7 @@
#include "network/protocols/game_protocol.hpp"
#include "network/rewind_manager.hpp"
#include "network/stk_host.hpp"
#include "network/stk_peer.hpp"
//-----------------------------------------------------------------------------
/** Creates one instance of the item manager. */
@ -42,16 +42,19 @@ NetworkItemManager::NetworkItemManager()
: Rewinder(/*can be deleted*/false),
ItemManager()
{
m_last_confirmed_item_ticks.lock();
m_last_confirmed_item_ticks.getData().clear();
m_last_confirmed_item_ticks.clear();
if (NetworkConfig::get()->isServer())
{
m_last_confirmed_item_ticks.getData()
.resize(STKHost::get()->getPeerCount(), 0);
auto peers = STKHost::get()->getPeers();
for (auto& p : peers)
{
if (!p->isValidated())
continue;
m_last_confirmed_item_ticks[p] = 0;
}
}
m_last_confirmed_item_ticks.unlock();
} // NetworkItemManager
//-----------------------------------------------------------------------------
@ -141,23 +144,32 @@ Item* NetworkItemManager::dropNewItem(ItemState::ItemType type,
/** Called by the GameProtocol when a confirmation for an item event is
* received by a host. Once all hosts have confirmed an event, it can be
* deleted and won't be send to any clients again.
* \param host_id Host identification of the host confirming the latest
* event time received.
* \param peer Peer confirming the latest event time received.
* \param ticks Time at which the last event was received.
*/
void NetworkItemManager::setItemConfirmationTime(int host_id, int ticks)
void NetworkItemManager::setItemConfirmationTime(std::weak_ptr<STKPeer> peer,
int ticks)
{
assert(NetworkConfig::get()->isServer());
m_last_confirmed_item_ticks.lock();
if (ticks > m_last_confirmed_item_ticks.getData()[host_id])
m_last_confirmed_item_ticks.getData()[host_id] = ticks;
if (ticks > m_last_confirmed_item_ticks.at(peer))
m_last_confirmed_item_ticks.at(peer) = ticks;
// Now discard unneeded events, i.e. all events that have
// been confirmed by all clients:
int min_time = 999999;
for (auto i : m_last_confirmed_item_ticks.getData())
if (i < min_time) min_time = i;
m_last_confirmed_item_ticks.unlock();
// Now discard unneeded events and expired (disconnected) peer, i.e. all
// events that have been confirmed by all clients:
int min_time = std::numeric_limits<int32_t>::max();
for (auto it = m_last_confirmed_item_ticks.begin();
it != m_last_confirmed_item_ticks.end();)
{
if (it->first.expired())
{
it = m_last_confirmed_item_ticks.erase(it);
}
else
{
if (it->second < min_time) min_time = it->second;
it++;
}
}
// Find the last entry before the minimal confirmed time.
// Since the event list is sorted, all events up to this
@ -169,7 +181,6 @@ void NetworkItemManager::setItemConfirmationTime(int host_id, int ticks)
m_item_events.getData().erase(m_item_events.getData().begin(), p);
m_item_events.unlock();
// TODO: Get informed when a client drops out!!!
} // setItemConfirmationTime
//-----------------------------------------------------------------------------
@ -290,7 +301,6 @@ void NetworkItemManager::restoreState(BareNetworkString *buffer, int count)
if(iei.isItemCollection())
{
int index = iei.getIndex();
ItemState *item_state = m_confirmed_state[index];
// An item on the track was collected:
AbstractKart *kart = World::getWorld()->getKart(iei.getKartId());
m_confirmed_state[index]->collected(kart);
@ -322,7 +332,8 @@ void NetworkItemManager::restoreState(BareNetworkString *buffer, int count)
} // while count >0
// Inform the server which events have been received.
GameProtocol::lock()->sendItemEventConfirmation(World::getWorld()->getTimeTicks());
if (auto gp = GameProtocol::lock())
gp->sendItemEventConfirmation(World::getWorld()->getTimeTicks());
// Forward the confirmed item state till the world time:
int dt = World::getWorld()->getTimeTicks() - current_time;

View File

@ -25,6 +25,11 @@
#include "utils/cpp2011.hpp"
#include "utils/synchronised.hpp"
#include <map>
#include <memory>
class STKPeer;
/** \ingroup items
* The network item manager is responsible for handling all network related
* item manager tasks - synchronisation between clients and servers. It
@ -47,7 +52,8 @@ private:
int m_confirmed_state_time;
/** Stores on the server the latest confirmed tick from each client. */
Synchronised< std::vector<int> > m_last_confirmed_item_ticks;
std::map<std::weak_ptr<STKPeer>, int32_t,
std::owner_less<std::weak_ptr<STKPeer> > > m_last_confirmed_item_ticks;
/** List of all items events. */
Synchronised< std::vector<ItemEventInfo> > m_item_events;
@ -64,8 +70,9 @@ public:
void sendItemUpdate();
void saveInitialState();
virtual void reset();
virtual void setItemConfirmationTime(int host_id, int ticks) OVERRIDE;
virtual void reset() OVERRIDE;
virtual void setItemConfirmationTime(std::weak_ptr<STKPeer> peer,
int ticks) OVERRIDE;
virtual void collectedItem(Item *item, AbstractKart *kart) OVERRIDE;
virtual Item* dropNewItem(ItemState::ItemType type, const AbstractKart *kart,
const Vec3 *xyz=NULL) OVERRIDE;

View File

@ -1687,6 +1687,21 @@ void Kart::update(int ticks)
} // update
//-----------------------------------------------------------------------------
void Kart::handleRewoundTransform()
{
if (!m_controller->isLocalPlayerController())
{
if (RewindManager::get()->isRewinding())
m_rewound_transforms.push_back(getTrans());
else if (!m_rewound_transforms.empty())
{
setTrans(m_rewound_transforms.front());
m_rewound_transforms.pop_front();
}
}
} // handleRewoundTransform
//-----------------------------------------------------------------------------
/** Updates the local speed based on the current physical velocity. The value
* is smoothed exponentially to avoid camera stuttering (camera distance
@ -2765,7 +2780,8 @@ void Kart::loadData(RaceManager::KartType type, bool is_animated_model)
m_skidmarks = new SkidMarks(*this);
}
if (CVS->isGLSL() && !CVS->isShadowEnabled())
if (CVS->isGLSL() && !CVS->isShadowEnabled() && m_kart_properties
->getShadowMaterial()->getSamplerPath(0) != "unicolor_white")
{
m_shadow = new Shadow(m_kart_properties->getShadowMaterial(), *this);
}

View File

@ -32,6 +32,7 @@
#include "karts/abstract_kart.hpp"
#include "utils/no_copy.hpp"
#include <deque>
#include <SColor.h>
class AbstractKartAnimation;
@ -250,6 +251,8 @@ protected:
int m_ticks_last_crash;
RaceManager::KartType m_type;
std::deque<btTransform> m_rewound_transforms;
/** To prevent using nitro in too short bursts */
int m_min_nitro_ticks;
@ -547,6 +550,9 @@ public:
virtual void playSound(SFXBuffer* buffer) OVERRIDE;
// ------------------------------------------------------------------------
virtual bool isVisible() OVERRIDE;
// ------------------------------------------------------------------------
void handleRewoundTransform();
}; // Kart

View File

@ -60,15 +60,39 @@ void KartRewinder::reset()
void KartRewinder::saveTransform()
{
m_saved_transform = getTrans();
m_rewound_transforms.clear();
} // saveTransform
// ----------------------------------------------------------------------------
void KartRewinder::computeError()
{
// Local player kart doesn't need showing in the past
if (m_rewound_transforms.empty())
return;
std::deque<btTransform> copied = m_rewound_transforms;
// Find the closest position that matches previous rewound one
Vec3 saved_position = m_saved_transform.getOrigin();
while (!copied.empty())
{
Vec3 cur_position = copied.front().getOrigin();
if ((cur_position - saved_position).length() < 0.25f)
{
setTrans(copied.front());
copied.pop_front();
std::swap(m_rewound_transforms, copied);
return;
}
copied.pop_front();
}
// Use newly rewound one if no matching transformation
setTrans(m_rewound_transforms.front());
m_rewound_transforms.pop_front();
//btTransform error = getTrans() - m_saved_transform;
Vec3 pos_error = getTrans().getOrigin() - m_saved_transform.getOrigin();
btQuaternion rot_error(0, 0, 0, 1);
Kart::addError(pos_error, rot_error);
//Vec3 pos_error = getTrans().getOrigin() - m_saved_transform.getOrigin();
//btQuaternion rot_error(0, 0, 0, 1);
//Kart::addError(pos_error, rot_error);
} // computeError
// ----------------------------------------------------------------------------

View File

@ -106,7 +106,7 @@ void Moveable::updateGraphics(float dt, const Vec3& offset_xyz,
#endif
}
#ifndef SERVER_ONLY
Vec3 xyz=getXYZ()+offset_xyz - m_positional_error;
Vec3 xyz=getXYZ()+offset_xyz;
m_node->setPosition(xyz.toIrrVector());
btQuaternion r_all = getRotation()*rotation;
if(btFuzzyZero(r_all.getX()) && btFuzzyZero(r_all.getY()-0.70710677f) &&

View File

@ -1574,7 +1574,9 @@ void initRest()
// This only initialises the non-network part of the add-ons manager. The
// online section of the add-ons manager will be initialised from a
// separate thread running in network HTTP.
#ifndef SERVER_ONLY
addons_manager = new AddonsManager();
#endif
Online::ProfileManager::create();
// The request manager will start the login process in case of a saved
@ -1583,7 +1585,9 @@ void initRest()
// achievement managers to be created, which can only be created later).
PlayerManager::create();
Online::RequestManager::get()->startNetworkThread();
#ifndef SERVER_ONLY
NewsManager::get(); // this will create the news manager
#endif
music_manager = new MusicManager();
SFXManager::create();
@ -1664,8 +1668,10 @@ void askForInternetPermission()
Online::RequestManager::IPERM_ALLOWED;
UserConfigParams::m_internet_status =
Online::RequestManager::IPERM_ALLOWED;
#ifndef SERVER_ONLY
if (need_to_start_news_manager)
NewsManager::get()->init(false);
#endif
GUIEngine::ModalDialog::dismiss();
} // onConfirm
// --------------------------------------------------------
@ -1732,6 +1738,8 @@ int main(int argc, char *argv[] )
// not have) other managers initialised:
initUserConfig();
CommandLine::addArgsFromUserConfig();
handleCmdLinePreliminary();
initRest();
@ -1806,6 +1814,7 @@ int main(int argc, char *argv[] )
//handleCmdLine() needs InitTuxkart() so it can't be called first
if(!handleCmdLine()) exit(0);
#ifndef SERVER_ONLY
addons_manager->checkInstalledAddons();
// Load addons.xml to get info about add-ons even when not
@ -1827,6 +1836,7 @@ int main(int argc, char *argv[] )
}
}
}
#endif
if(UserConfigParams::m_unit_testing)
{
@ -1959,6 +1969,7 @@ int main(int argc, char *argv[] )
StateManager::get()->enterGameState();
}
#ifndef SERVER_ONLY
// If an important news message exists it is shown in a popup dialog.
const core::stringw important_message =
NewsManager::get()->getImportantMessage();
@ -1968,7 +1979,7 @@ int main(int argc, char *argv[] )
MessageDialog::MESSAGE_DIALOG_OK,
NULL, true);
} // if important_message
#endif
// Replay a race
// =============
@ -2119,11 +2130,13 @@ static void cleanSuperTuxKart()
// was deleted (in cleanUserConfig below), but before STK finishes and
// the OS takes all threads down.
#ifndef SERVER_ONLY
if(!NewsManager::get()->waitForReadyToDeleted(2.0f))
{
Log::info("Thread", "News manager not stopping, exiting anyway.");
}
NewsManager::deallocate();
#endif
if(!Online::RequestManager::get()->waitForReadyToDeleted(5.0f))
{
@ -2144,7 +2157,9 @@ static void cleanSuperTuxKart()
// The add-ons manager might still be called from a currenty running request
// in the request manager, so it can not be deleted earlier.
#ifndef SERVER_ONLY
if(addons_manager) delete addons_manager;
#endif
ServersManager::deallocate();
cleanUserConfig();

View File

@ -1056,6 +1056,16 @@ void World::update(int ticks)
Physics::getInstance()->update(ticks);
if (NetworkConfig::get()->isNetworking() &&
NetworkConfig::get()->isClient())
{
for (int i = 0 ; i < kart_amount; i++)
{
if (!m_karts[i]->isEliminated())
static_cast<Kart*>(m_karts[i])->handleRewoundTransform();
}
}
PROFILER_PUSH_CPU_MARKER("World::update (projectiles)", 0xa0, 0x7F, 0x00);
projectile_manager->update(ticks);
PROFILER_POP_CPU_MARKER();

View File

@ -322,6 +322,11 @@ void ClientLobby::update(int ticks)
case PLAYING:
break;
case RACE_FINISHED:
if (!RaceEventManager::getInstance()->protocolStopped() ||
!GameProtocol::emptyInstance())
return;
if (!m_received_server_result)
m_received_server_result = true;
break;
case DONE:
m_state.store(EXITING);
@ -762,16 +767,9 @@ void ClientLobby::raceFinished(Event* event)
// stop race protocols
RaceEventManager::getInstance()->stop();
RaceEventManager::getInstance()->getProtocol()->requestTerminate();
GameProtocol::lock()->requestTerminate();
while (!RaceEventManager::getInstance()->protocolStopped())
StkTime::sleep(1);
while (!GameProtocol::emptyInstance())
StkTime::sleep(1);
m_received_server_result = true;
m_state.store(RACE_FINISHED);
} // raceFinished
//-----------------------------------------------------------------------------

View File

@ -101,9 +101,6 @@ bool GameProtocol::notifyEventAsynchronous(Event* event)
NetworkString &data = event->data();
uint8_t message_type = data.getUInt8();
if (message_type != GP_CONTROLLER_ACTION &&
message_type != GP_STATE)
printf("");
switch (message_type)
{
case GP_CONTROLLER_ACTION: handleControllerAction(event); break;
@ -298,10 +295,9 @@ void GameProtocol::sendItemEventConfirmation(int ticks)
void GameProtocol::handleItemEventConfirmation(Event *event)
{
assert(NetworkConfig::get()->isServer());
int host_id = event->getPeer()->getHostId();
int ticks = event->data().getTime();
NetworkItemManager::get()->setItemConfirmationTime(host_id, ticks);
int ticks = event->data().getTime();
NetworkItemManager::get()->setItemConfirmationTime(event->getPeerSP(),
ticks);
} // handleItemEventConfirmation
// ----------------------------------------------------------------------------

View File

@ -99,6 +99,9 @@ ServerLobby::ServerLobby() : LobbyProtocol(NULL)
"STK addons server, don't bother host one if you don't have the "
"corresponding permission, they will be rejected if so.");
}
m_result_ns = getNetworkString();
m_result_ns->setSynchronous(true);
m_waiting_for_reset = false;
} // ServerLobby
//-----------------------------------------------------------------------------
@ -110,6 +113,7 @@ ServerLobby::~ServerLobby()
{
unregisterServer(true/*now*/);
}
delete m_result_ns;
} // ~ServerLobby
//-----------------------------------------------------------------------------
@ -142,6 +146,8 @@ void ServerLobby::setup()
m_peers_votes.clear();
m_server_delay = 0.0;
m_timeout.store(std::numeric_limits<float>::max());
m_waiting_for_reset = false;
Log::info("ServerLobby", "Reset server to initial state.");
} // setup
@ -426,6 +432,21 @@ void ServerLobby::asynchronousUpdate()
void ServerLobby::update(int ticks)
{
// Reset server to initial state if no more connected players
if (m_waiting_for_reset)
{
if ((RaceEventManager::getInstance() &&
!RaceEventManager::getInstance()->protocolStopped()) ||
!GameProtocol::emptyInstance())
return;
RaceResultGUI::getInstance()->backToLobby();
std::lock_guard<std::mutex> lock(m_connection_mutex);
m_game_setup->stopGrandPrix();
m_state = NetworkConfig::get()->isLAN() ?
ACCEPTING_CLIENTS : REGISTER_SELF_ADDRESS;
setup();
}
if ((m_state.load() > ACCEPTING_CLIENTS ||
m_game_setup->isGrandPrixStarted()) &&
STKHost::get()->getPeerCount() == 0 &&
@ -434,13 +455,12 @@ void ServerLobby::update(int ticks)
if (RaceEventManager::getInstance() &&
RaceEventManager::getInstance()->isRunning())
{
stopCurrentRace();
RaceEventManager::getInstance()->stop();
RaceEventManager::getInstance()->getProtocol()->requestTerminate();
GameProtocol::lock()->requestTerminate();
}
std::lock_guard<std::mutex> lock(m_connection_mutex);
m_game_setup->stopGrandPrix();
m_state = NetworkConfig::get()->isLAN() ?
ACCEPTING_CLIENTS : REGISTER_SELF_ADDRESS;
setup();
m_waiting_for_reset = true;
return;
}
// Reset for ranked server if in kart / track selection has only 1 player
@ -502,6 +522,22 @@ void ServerLobby::update(int ticks)
checkRaceFinished();
}
break;
case WAIT_FOR_RACE_STOPPED:
if (!RaceEventManager::getInstance()->protocolStopped() ||
!GameProtocol::emptyInstance())
return;
// This will go back to lobby in server (and exit the current race)
RaceResultGUI::getInstance()->backToLobby();
// Reset for next state usage
resetPeersReady();
// Set the delay before the server forces all clients to exit the race
// result screen and go back to the lobby
m_timeout.store((float)StkTime::getRealTime() + 15.0f);
m_state = RESULT_DISPLAY;
sendMessageToPeers(m_result_ns, /*reliable*/ true);
Log::info("ServerLobby", "End of game message sent");
break;
case RESULT_DISPLAY:
if (checkPeersReady() ||
StkTime::getRealTime() > m_timeout.load())
@ -811,28 +847,32 @@ void ServerLobby::checkRaceFinished()
if (!RaceEventManager::getInstance()->isRaceOver()) return;
Log::info("ServerLobby", "The game is considered finish.");
// notify the network world that it is stopped
RaceEventManager::getInstance()->stop();
// Reset for next state usage
resetPeersReady();
NetworkString* total = getNetworkString();
total->setSynchronous(true);
total->addUInt8(LE_RACE_FINISHED);
// stop race protocols before going back to lobby (end race)
RaceEventManager::getInstance()->getProtocol()->requestTerminate();
GameProtocol::lock()->requestTerminate();
// Save race result before delete the world
m_result_ns->clear();
m_result_ns->addUInt8(LE_RACE_FINISHED);
if (m_game_setup->isGrandPrix())
{
// fastest lap
int fastest_lap =
static_cast<LinearWorld*>(World::getWorld())->getFastestLapTicks();
total->addUInt32(fastest_lap);
m_result_ns->addUInt32(fastest_lap);
// all gp tracks
total->addUInt8((uint8_t)m_game_setup->getTotalGrandPrixTracks())
m_result_ns->addUInt8((uint8_t)m_game_setup->getTotalGrandPrixTracks())
.addUInt8((uint8_t)m_game_setup->getAllTracks().size());
for (const std::string& gp_track : m_game_setup->getAllTracks())
total->encodeString(gp_track);
m_result_ns->encodeString(gp_track);
// each kart score and total time
auto& players = m_game_setup->getPlayers();
total->addUInt8((uint8_t)players.size());
m_result_ns->addUInt8((uint8_t)players.size());
for (unsigned i = 0; i < players.size(); i++)
{
int last_score = race_manager->getKartScore(i);
@ -846,7 +886,7 @@ void ServerLobby::checkRaceFinished()
player->setScore(cur_score);
player->setOverallTime(overall_time);
}
total->addUInt32(last_score).addUInt32(cur_score)
m_result_ns->addUInt32(last_score).addUInt32(cur_score)
.addFloat(overall_time);
}
}
@ -854,23 +894,14 @@ void ServerLobby::checkRaceFinished()
{
int fastest_lap =
static_cast<LinearWorld*>(World::getWorld())->getFastestLapTicks();
total->addUInt32(fastest_lap);
m_result_ns->addUInt32(fastest_lap);
}
if (NetworkConfig::get()->isRankedServer())
{
computeNewRankings();
submitRankingsToAddons();
}
stopCurrentRace();
// Set the delay before the server forces all clients to exit the race
// result screen and go back to the lobby
m_timeout.store((float)StkTime::getRealTime() + 15.0f);
m_state = RESULT_DISPLAY;
sendMessageToPeers(total, /*reliable*/ true);
delete total;
Log::info("ServerLobby", "End of game message sent");
m_state.store(WAIT_FOR_RACE_STOPPED);
} // checkRaceFinished
//-----------------------------------------------------------------------------
@ -940,13 +971,13 @@ void ServerLobby::computeNewRankings()
{
result = 0.0;
ranking_importance = mode_factor *
MAX_SCALING_TIME * MAX_POINTS_PER_SECOND * player_factors;
scalingValueForTime(MAX_SCALING_TIME) * player_factors;
}
else if (!players[j])
{
result = 1.0;
ranking_importance = mode_factor *
MAX_SCALING_TIME * MAX_POINTS_PER_SECOND * player_factors;
scalingValueForTime(MAX_SCALING_TIME) * player_factors;
}
else
{
@ -964,10 +995,11 @@ void ServerLobby::computeNewRankings()
(player1_time - player2_time) / (player2_time / 20.0);
result = std::max(0.0, 0.5 - result);
}
double max_time = std::min(std::max(player1_time, player2_time),
MAX_SCALING_TIME);
ranking_importance = mode_factor *
std::min(
std::max(player1_time, player2_time), MAX_SCALING_TIME) *
MAX_POINTS_PER_SECOND * player_factors;
scalingValueForTime(max_time) * player_factors;
}
// Compute the ranking change
scores_change[i] +=
@ -1040,6 +1072,15 @@ double ServerLobby::getModeSpread()
return 1.4;
} // getModeSpread
//-----------------------------------------------------------------------------
/** Compute the scaling value of a given time
* Short races are more random, so we don't use strict proportionality
*/
double ServerLobby::scalingValueForTime(double time)
{
return time * sqrt(time / 120.0) * MAX_POINTS_PER_SECOND;
} // scalingValueForTime
//-----------------------------------------------------------------------------
/** Manages the distribution of the base points.
* Gives half of the points progressively
@ -1052,35 +1093,12 @@ double ServerLobby::distributeBasePoints(uint32_t online_id)
unsigned num_races = m_num_ranked_races.at(online_id);
if (num_races < 45)
{
return
(BASE_RANKING_POINTS / 2000.0 * std::max((45u - num_races), 4u) *
2.0);
return BASE_RANKING_POINTS / 2000.0 * std::max((45u - num_races), 4u);
}
else
return 0.0;
} // distributeBasePoints
//-----------------------------------------------------------------------------
/** Stop any race currently in server, should only be called in main thread.
*/
void ServerLobby::stopCurrentRace()
{
// notify the network world that it is stopped
RaceEventManager::getInstance()->stop();
// stop race protocols before going back to lobby (end race)
RaceEventManager::getInstance()->getProtocol()->requestTerminate();
GameProtocol::lock()->requestTerminate();
while (!RaceEventManager::getInstance()->protocolStopped())
StkTime::sleep(1);
while (!GameProtocol::emptyInstance())
StkTime::sleep(1);
// This will go back to lobby in server (and exit the current race)
RaceResultGUI::getInstance()->backToLobby();
} // stopCurrentRace
//-----------------------------------------------------------------------------
/** Called when a client disconnects.
* \param event The disconnect event.

View File

@ -16,6 +16,7 @@
#include <tuple>
class BareNetworkString;
class NetworkString;
class NetworkPlayerProfile;
class STKPeer;
@ -34,6 +35,7 @@ public:
WAIT_FOR_RACE_STARTED, // Wait for all clients to have started the race
DELAY_SERVER, // Additional server delay
RACING, // racing
WAIT_FOR_RACE_STOPPED, // Wait server for stopping all race protocols
RESULT_DISPLAY, // Show result screen
ERROR_LEAVE, // shutting down server
EXITING
@ -104,7 +106,7 @@ private:
/* Ranking related variables */
// If updating the base points, update the base points distribution in DB
const double BASE_RANKING_POINTS = 4000.0;
const double MAX_SCALING_TIME = 600.0;
const double MAX_SCALING_TIME = 500.0;
const double MAX_POINTS_PER_SECOND = 0.125;
/** Online id to profile map, handling disconnection in ranked server */
@ -119,6 +121,10 @@ private:
/** Number of ranked races done for each current players */
std::map<uint32_t, unsigned> m_num_ranked_races;
bool m_waiting_for_reset;
NetworkString* m_result_ns;
// connection management
void clientDisconnected(Event* event);
void connectionRequested(Event* event);
@ -183,8 +189,6 @@ private:
uint32_t online_id,
const irr::core::stringw& online_name);
std::tuple<std::string, uint8_t, bool, bool> handleVote();
void stopCurrentRace();
void getRankingForPlayer(std::shared_ptr<NetworkPlayerProfile> p);
void submitRankingsToAddons();
void computeNewRankings();
@ -193,6 +197,8 @@ private:
double distributeBasePoints(uint32_t online_id);
double getModeFactor();
double getModeSpread();
double scalingValueForTime(double time);
void checkRaceFinished();
public:
ServerLobby();
@ -207,7 +213,6 @@ public:
void signalRaceStartToClients();
void startSelection(const Event *event=NULL);
void checkIncomingConnectionRequests();
void checkRaceFinished();
void finishedLoadingWorld() OVERRIDE;
ServerState getCurrentState() const { return m_state.load(); }
void updateBanList();

View File

@ -162,17 +162,20 @@ void RewindManager::addNetworkState(BareNetworkString *buffer, int ticks)
void RewindManager::saveState(bool local_save)
{
PROFILER_PUSH_CPU_MARKER("RewindManager - save state", 0x20, 0x7F, 0x20);
GameProtocol::lock()->startNewState(local_save);
auto gp = GameProtocol::lock();
if (!gp)
return;
gp->startNewState(local_save);
AllRewinder::const_iterator rewinder;
for (rewinder = m_all_rewinder.begin(); rewinder != m_all_rewinder.end(); ++rewinder)
{
// TODO: check if it's worth passing in a sufficiently large buffer from
// GameProtocol - this would save the copy operation.
BareNetworkString *buffer = (*rewinder)->saveState();
if (buffer && buffer->size() >= 0)
if (buffer)
{
m_overall_state_size += buffer->size();
GameProtocol::lock()->addState(buffer);
gp->addState(buffer);
} // size >= 0
delete buffer; // buffer can be freed
}
@ -186,10 +189,14 @@ void RewindManager::saveState(bool local_save)
*/
void RewindManager::saveLocalState()
{
auto gp = GameProtocol::lock();
if (!gp)
return;
int ticks = World::getWorld()->getTimeTicks();
saveState(/*local_state*/true);
NetworkString *state = GameProtocol::lock()->getState();
NetworkString *state = gp->getState();
// Copy the data to a new string, making the buffer in
// GameProtocol availble for again.
@ -208,7 +215,6 @@ void RewindManager::saveLocalState()
void RewindManager::restoreState(BareNetworkString *data)
{
data->reset();
int index = 0;
for (auto rewinder = m_all_rewinder.begin();
rewinder != m_all_rewinder.end(); ++rewinder)
@ -230,7 +236,6 @@ void RewindManager::update(int ticks_not_used)
m_all_rewinder.size() == 0 ||
m_is_rewinding) return;
float time = World::getWorld()->getTime();
int ticks = World::getWorld()->getTimeTicks();
m_not_rewound_ticks.store(ticks, std::memory_order_relaxed);
@ -245,7 +250,8 @@ void RewindManager::update(int ticks_not_used)
// Save state
saveState(/**allow_local_save*/false);
PROFILER_PUSH_CPU_MARKER("RewindManager - send state", 0x20, 0x7F, 0x40);
GameProtocol::lock()->sendState();
if (auto gp = GameProtocol::lock())
gp->sendState();
PROFILER_POP_CPU_MARKER();
m_last_saved_state = ticks;
} // update

View File

@ -210,7 +210,6 @@ void RewindQueue::mergeNetworkData(int world_ticks, bool *needs_rewind,
// Only a client ever rewinds. So the rewind time should be the latest
// received state before current world time (if any)
*rewind_ticks = -9999;
bool adjust_next = false;
// FIXME: making m_network_events sorted would prevent the need to
// go through the whole list of events
@ -261,7 +260,8 @@ void RewindQueue::mergeNetworkData(int world_ticks, bool *needs_rewind,
// any server message should be in the client's past - but it can
// happen during debugging) we need to rewind to getTicks (in order
// to get the latest state).
if (NetworkConfig::get()->isClient() && (*i)->getTicks() <= world_ticks)
if (NetworkConfig::get()->isClient() && (*i)->getTicks() <= world_ticks
&& (*i)->isState())
{
// We need rewind if we receive an event in the past. This will
// then trigger a rewind later. Note that we only rewind to the

View File

@ -255,16 +255,18 @@ bool ProfileManager::inPersistent(const uint32_t id)
*/
OnlineProfile* ProfileManager::addPersistent(OnlineProfile * profile)
{
if (inPersistent(profile->getID()))
uint32_t profile_id = profile->getID();
if (inPersistent(profile_id))
{
m_profiles_persistent[profile->getID()]->merge(profile);
m_profiles_persistent[profile_id]->merge(profile);
}
else
{
m_profiles_persistent[profile->getID()] = profile;
m_profiles_persistent[profile_id] = profile;
}
return m_profiles_persistent[profile->getID()];
return m_profiles_persistent[profile_id];
} // addPersistent
// ------------------------------------------------------------------------

12
src/physics/btKart.cpp Normal file → Executable file
View File

@ -353,17 +353,17 @@ void btKart::getVisualContactPoint(float visual_rotation,
m_visual_wheels_touch_ground = true;
short int old_group = 0;
if (m_chassisBody->getBroadphaseHandle())
{
old_group = m_chassisBody->getBroadphaseHandle()
->m_collisionFilterGroup;
m_chassisBody->getBroadphaseHandle()->m_collisionFilterGroup = 0;
}
for (int index = 2; index <= 3; index++)
{
// Map index 0-1 to wheel 2-3 (which are the rear wheels)
btWheelInfo &wheel = m_wheelInfo[index];
updateWheelTransformsWS(wheel, false);
if (m_chassisBody->getBroadphaseHandle())
{
old_group = m_chassisBody->getBroadphaseHandle()
->m_collisionFilterGroup;
m_chassisBody->getBroadphaseHandle()->m_collisionFilterGroup = 0;
}
btScalar max_susp_len = wheel.getSuspensionRestLength()
+ wheel.m_maxSuspensionTravel;

View File

@ -234,7 +234,7 @@ void AddonsScreen::tearDown()
*/
void AddonsScreen::loadList()
{
#ifndef SERVER_ONLY
// Get the filter by words.
GUIEngine::TextBoxWidget* w_filter_name =
getWidget<GUIEngine::TextBoxWidget>("filter_name");
@ -416,6 +416,7 @@ void AddonsScreen::loadList()
else
getWidget<GUIEngine::RibbonWidget>("category")->select("tab_update",
PLAYER_ID_GAME_MASTER);
#endif
} // loadList
// ----------------------------------------------------------------------------
@ -452,6 +453,7 @@ void AddonsScreen::onColumnClicked(int column_id)
void AddonsScreen::eventCallback(GUIEngine::Widget* widget,
const std::string& name, const int playerID)
{
#ifndef SERVER_ONLY
if (name == "back")
{
StateManager::get()->escapePressed();
@ -509,7 +511,7 @@ void AddonsScreen::eventCallback(GUIEngine::Widget* widget,
{
loadList();
}
#endif
} // eventCallback
// ----------------------------------------------------------------------------
@ -534,6 +536,7 @@ void AddonsScreen::setLastSelected()
void AddonsScreen::onUpdate(float dt)
{
#ifndef SERVER_ONLY
if (m_reloading)
{
if(UserConfigParams::m_internet_status!=RequestManager::IPERM_ALLOWED)
@ -579,5 +582,5 @@ void AddonsScreen::onUpdate(float dt)
m_show_tips = false;
}
}
#endif
} // onUpdate

View File

@ -46,7 +46,6 @@ class AddonsScreen : public GUIEngine::Screen,
friend class GUIEngine::ScreenSingleton<AddonsScreen>;
private:
AddonsScreen();
AddonsManager *m_addons;
AddonsLoading *m_load;
void loadInformations();
/** Icon for installed addon, which can be updated. */

View File

@ -45,8 +45,10 @@ using namespace irr::gui;
*/
AddonsLoading::AddonsLoading(const std::string &id)
: ModalDialog(0.8f, 0.8f),
m_addon(*(addons_manager->getAddon(id)) )
: ModalDialog(0.8f, 0.8f)
#ifndef SERVER_ONLY
, m_addon(*(addons_manager->getAddon(id)) )
#endif
{
m_icon_shown = false;
@ -82,6 +84,7 @@ AddonsLoading::~AddonsLoading()
void AddonsLoading::beforeAddingWidgets()
{
#ifndef SERVER_ONLY
/* Init the icon here to be able to load a single image*/
m_icon = getWidget<IconButtonWidget> ("icon" );
m_progress = getWidget<ProgressBarWidget>("progress");
@ -180,6 +183,7 @@ void AddonsLoading::beforeAddingWidgets()
unit = _LTR("%s KB", 1);
core::stringw size = _("Size: %s", unit.c_str());
getWidget<LabelWidget>("size")->setText(size, false);
#endif
} // AddonsLoading
// ----------------------------------------------------------------------------
@ -205,6 +209,7 @@ bool AddonsLoading::onEscapePressed()
GUIEngine::EventPropagation AddonsLoading::processEvent(const std::string& event_source)
{
#ifndef SERVER_ONLY
GUIEngine::RibbonWidget* actions_ribbon =
getWidget<GUIEngine::RibbonWidget>("actions");
@ -252,12 +257,14 @@ GUIEngine::EventPropagation AddonsLoading::processEvent(const std::string& event
voteClicked();
return GUIEngine::EVENT_BLOCK;
}
#endif
return GUIEngine::EVENT_LET;
} // processEvent
// ----------------------------------------------------------------------------
void AddonsLoading::voteClicked()
{
#ifndef SERVER_ONLY
if (PlayerManager::isCurrentLoggedIn())
{
// We need to keep a copy of the addon id, since dismiss() will
@ -266,11 +273,13 @@ void AddonsLoading::voteClicked()
dismiss();
new VoteDialog(addon_id);
}
#endif
} // voteClicked
// ----------------------------------------------------------------------------
void AddonsLoading::onUpdate(float delta)
{
#ifndef SERVER_ONLY
if(m_progress->isVisible())
{
float progress = m_download_request->getProgress();
@ -308,6 +317,7 @@ void AddonsLoading::onUpdate(float delta)
}
m_icon_shown = true;
}
#endif
} // onUpdate
// ----------------------------------------------------------------------------
@ -316,13 +326,14 @@ void AddonsLoading::onUpdate(float delta)
**/
void AddonsLoading::startDownload()
{
#ifndef SERVER_ONLY
std::string save = "tmp/"
+ StringUtils::getBasename(m_addon.getZipFileName());
m_download_request = new Online::HTTPRequest(save, /*manage mem*/false,
/*priority*/5);
m_download_request->setURL(m_addon.getZipFileName());
m_download_request->queue();
#endif
} // startDownload
// ----------------------------------------------------------------------------
@ -353,6 +364,7 @@ void AddonsLoading::stopDownload()
*/
void AddonsLoading::doInstall()
{
#ifndef SERVER_ONLY
delete m_download_request;
m_download_request = NULL;
@ -383,12 +395,14 @@ void AddonsLoading::doInstall()
}
track_manager->loadTrackList();
#endif
} // doInstall
// ----------------------------------------------------------------------------
void AddonsLoading::doUninstall()
{
#ifndef SERVER_ONLY
delete m_download_request;
m_download_request = NULL;
bool error = !addons_manager->uninstall(m_addon);
@ -418,4 +432,5 @@ void AddonsLoading::doUninstall()
AddonsScreen::getInstance()->loadList();
dismiss();
}
#endif
} // doUninstall

View File

@ -41,7 +41,9 @@ private:
GUIEngine::IconButtonWidget *m_icon;
/** The addon to load. */
#ifndef SERVER_ONLY
Addon m_addon;
#endif
void startDownload();
void stopDownload();
void doInstall();

View File

@ -93,6 +93,7 @@ bool VoteDialog::onEscapePressed()
*/
void VoteDialog::sendVote()
{
#ifndef SERVER_ONLY
/** A vote request. The callback will update the addon manager with the
* new average. The VoteDialog polls this request till it is finished
* to inform the user about the new average.
@ -125,7 +126,7 @@ void VoteDialog::sendVote()
m_rating_widget->setActive(false);
m_cancel_widget->setActive(false);
#endif
} // sendVote
// -----------------------------------------------------------------------------

View File

@ -165,10 +165,6 @@ FeatureUnlockedCutScene::FeatureUnlockedCutScene()
: CutsceneScreen("feature_unlocked.stkgui")
{
m_key_angle = 0;
#ifdef USE_IRRLICHT_BUG_WORKAROUND
m_avoid_irrlicht_bug = NULL;
#endif
} // FeatureUnlockedCutScene
// ----------------------------------------------------------------------------
@ -181,12 +177,6 @@ void FeatureUnlockedCutScene::loadedFromFile()
void FeatureUnlockedCutScene::onCutsceneEnd()
{
#ifdef USE_IRRLICHT_BUG_WORKAROUND
if (m_avoid_irrlicht_bug)
irr_driver->removeNode(m_avoid_irrlicht_bug);
m_avoid_irrlicht_bug = NULL;
#endif
m_unlocked_stuff.clearAndDeleteAll();
#ifndef SERVER_ONLY
if (CVS->isGLSL())
@ -205,8 +195,10 @@ void FeatureUnlockedCutScene::onCutsceneEnd()
void FeatureUnlockedCutScene::findWhatWasUnlocked(RaceManager::Difficulty difficulty,std::vector<const ChallengeData*>& unlocked)
{
PlayerProfile *player = PlayerManager::getCurrentPlayer();
int points_before = player->getPoints();
int points_now = points_before + CHALLENGE_POINTS[difficulty];
// The number of points is updated before this function is called
int points_before = player->getPointsBefore();
int points_now = player->getPoints();
std::vector<std::string> tracks;
std::vector<std::string> gps;
@ -362,18 +354,6 @@ void FeatureUnlockedCutScene::init()
#ifdef DEBUG
m_unlocked_stuff[n].m_root_gift_node->setName("unlocked kart");
#endif
#ifdef USE_IRRLICHT_BUG_WORKAROUND
// If a mesh with this material is added, irrlicht will
// display the 'continue' text (otherwise the text is
// not visible). This is a terrible work around, but allows
// stk to be released without waiting for the next
// irrlicht version.
video::SMaterial m;
m.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
scene::IMesh* mesh =
irr_driver->createTexturedQuadMesh(&m, 0, 0);
m_avoid_irrlicht_bug = irr_driver->addMesh(mesh);
#endif
}
#ifndef SERVER_ONLY
@ -475,6 +455,7 @@ void FeatureUnlockedCutScene::onUpdate(float dt)
m_global_time += dt;
const int unlockedStuffCount = m_unlocked_stuff.size();
// When the chest has opened but the items are not yet at their final position
if (m_global_time > GIFT_EXIT_FROM && m_global_time < GIFT_EXIT_TO)
{
float progress_factor = (m_global_time - GIFT_EXIT_FROM) / (GIFT_EXIT_TO - GIFT_EXIT_FROM);
@ -489,30 +470,21 @@ void FeatureUnlockedCutScene::onUpdate(float dt)
// when there are more than 1 unlocked items, make sure they each
// have their own path when they move
if (unlockedStuffCount > 1)
{
if (n == 1) pos.X -= 1.0f*dt*float( int((n + 1)/2) );
else if (n > 1) pos.X += 1.0f*dt*(n - 0.3f);
// and that they won't end offscreen in usual situations
//else pos.X += 6.2f*dt*float( int((n + 1)/2) );
//Log::info("FeatureUnlockedCutScene", "Object %d moving by %f", n,
// (n % 2 == 0 ? -4.0f : 4.0f)*float( n/2 + 1 ));
}
else
{
//pos.X -= 2.0f*dt;
}
//if (m_global_time > GIFT_EXIT_FROM + 2.0f) pos.Z -= 2.0f*dt;
// Put the trophy in center
float pos_value = (n == 0) ? unlockedStuffCount/2 :
(n == unlockedStuffCount/2) ? 0 : n;
float offset = (float) pos_value - ((float) unlockedStuffCount)/2.0f + 0.5f;
offset *= (unlockedStuffCount <= 3) ? 1.4f :
(unlockedStuffCount <= 5) ? 1.2f : 1.0f;
pos.X += offset*dt;
pos.Z = smoothed_progress_factor * -4.0f;
m_unlocked_stuff[n].m_root_gift_node->setPosition(pos);
}
}
else if (m_global_time < GIFT_EXIT_FROM)
{
}
for (int n=0; n<unlockedStuffCount; n++)
{

View File

@ -116,10 +116,6 @@ class FeatureUnlockedCutScene : public GUIEngine::CutsceneScreen, public GUIEngi
/** Angle of the key (from 0 to 1, simply traces progression) */
float m_key_angle;
#ifdef USE_IRRLICHT_BUG_WORKAROUND
scene::IMeshSceneNode *m_avoid_irrlicht_bug;
#endif
void continueButtonPressed();
public:

View File

@ -140,6 +140,7 @@ void MainMenuScreen::init()
// the key bindings for the first player the default again.
input_manager->getDeviceManager()->clearLatestUsedDevice();
#ifndef SERVER_ONLY
if (addons_manager->isLoading())
{
IconButtonWidget* w = getWidget<IconButtonWidget>("addons");
@ -152,6 +153,7 @@ void MainMenuScreen::init()
const core::stringw &news_text = NewsManager::get()->getNextNewsMessage();
w->setText(news_text, true);
w->update(0.01f);
#endif
RibbonWidget* r = getWidget<RibbonWidget>("menu_bottomrow");
// FIXME: why do I need to do this manually
@ -174,6 +176,7 @@ void MainMenuScreen::init()
void MainMenuScreen::onUpdate(float delta)
{
#ifndef SERVER_ONLY
PlayerProfile *player = PlayerManager::getCurrentPlayer();
if(PlayerManager::getCurrentOnlineState() == PlayerProfile::OS_GUEST ||
PlayerManager::getCurrentOnlineState() == PlayerProfile::OS_SIGNED_IN)
@ -222,6 +225,7 @@ void MainMenuScreen::onUpdate(float delta)
const core::stringw &news_text = NewsManager::get()->getNextNewsMessage();
w->setText(news_text, true);
}
#endif
} // onUpdate
// ----------------------------------------------------------------------------
@ -229,6 +233,7 @@ void MainMenuScreen::onUpdate(float delta)
void MainMenuScreen::eventCallback(Widget* widget, const std::string& name,
const int playerID)
{
#ifndef SERVER_ONLY
if(name=="user-id")
{
UserScreen::getInstance()->push();
@ -534,6 +539,7 @@ void MainMenuScreen::eventCallback(Widget* widget, const std::string& name,
{
OnlineProfileAchievements::getInstance()->push();
}
#endif
} // eventCallback
// ----------------------------------------------------------------------------
@ -546,6 +552,7 @@ void MainMenuScreen::tearDown()
void MainMenuScreen::onDisabledItemClicked(const std::string& item)
{
#ifndef SERVER_ONLY
if (item == "addons")
{
if (UserConfigParams::m_internet_status != RequestManager::IPERM_ALLOWED)
@ -565,4 +572,5 @@ void MainMenuScreen::onDisabledItemClicked(const std::string& item)
new MessageDialog( _("Please wait while the add-ons are loading"));
}
}
#endif
} // onDisabledItemClicked

View File

@ -239,6 +239,7 @@ void OptionsScreenUI::init()
void OptionsScreenUI::eventCallback(Widget* widget, const std::string& name, const int playerID)
{
#ifndef SERVER_ONLY
if (name == "options_choice")
{
std::string selection = ((RibbonWidget*)widget)->getSelectionIDString(PLAYER_ID_GAME_MASTER);
@ -387,7 +388,7 @@ void OptionsScreenUI::eventCallback(Widget* widget, const std::string& name, con
OptionsScreenUI::getInstance()->push();
}
#endif
} // eventCallback
// -----------------------------------------------------------------------------

View File

@ -107,6 +107,15 @@ void RegisterScreen::init()
makeEntryFieldsVisible();
local_username->setFocusForPlayer(PLAYER_ID_GAME_MASTER);
// The behaviour of the screen is slightly different at startup, i.e.
// when it is the first screen: cancel will exit the game, and in
// this case no 'back' error should be shown.
bool has_player_profile = (PlayerManager::get()->getNumPlayers() > 0);
getWidget<IconButtonWidget>("back")->setVisible(has_player_profile);
getWidget<IconButtonWidget>("cancel")->setLabel(has_player_profile
? _("Cancel")
: _("Exit game"));
} // init
// -----------------------------------------------------------------------------
@ -237,6 +246,13 @@ void RegisterScreen::doRegister()
stringw local_name = getWidget<TextBoxWidget>("local_username")
->getText().trim();
if (local_name.empty())
{
m_info_widget->setErrorColor();
m_info_widget->setText(_("User name cannot be empty."), false);
return;
}
handleLocalName(local_name);
// If no online account is requested, don't register

View File

@ -17,6 +17,7 @@
#include "states_screens/user_screen.hpp"
#include "addons/news_manager.hpp"
#include "audio/sfx_manager.hpp"
#include "challenges/unlock_manager.hpp"
#include "config/player_manager.hpp"
@ -26,6 +27,7 @@
#include "guiengine/widgets/label_widget.hpp"
#include "guiengine/widgets/list_widget.hpp"
#include "guiengine/widgets/text_box_widget.hpp"
#include "online/request_manager.hpp"
#include "states_screens/dialogs/message_dialog.hpp"
#include "states_screens/dialogs/kart_color_slider_dialog.hpp"
#include "states_screens/dialogs/recovery_dialog.hpp"
@ -326,18 +328,49 @@ void BaseUserScreen::eventCallback(Widget* widget,
}
else if (name == "online")
{
// If online access is not allowed, do not accept an online account
// but advice the user where to enable this option.
// If online access is not allowed,
// give the player the choice to enable this option.
if (m_online_cb->getState())
{
if (UserConfigParams::m_internet_status ==
Online::RequestManager::IPERM_NOT_ALLOWED)
{
m_info_widget->setText(
_("Internet access is disabled, please enable it in the options"),
true);
irr::core::stringw message =
_("Internet access is disabled. Do you want to enable it ?");
class ConfirmInternet : public MessageDialog::IConfirmDialogListener
{
BaseUserScreen *m_parent_screen;
private:
GUIEngine::CheckBoxWidget *m_cb;
public:
virtual void onConfirm()
{
UserConfigParams::m_internet_status =
Online::RequestManager::IPERM_ALLOWED;
#ifndef SERVER_ONLY
NewsManager::get()->init(false);
#endif
m_parent_screen->makeEntryFieldsVisible();
ModalDialog::dismiss();
} // onConfirm
virtual void onCancel()
{
m_cb->setState(false);
m_parent_screen->makeEntryFieldsVisible();
ModalDialog::dismiss();
} // onCancel
// ------------------------------------------------------------
ConfirmInternet(BaseUserScreen *parent, GUIEngine::CheckBoxWidget *online_cb)
{
m_parent_screen = parent;
m_cb = online_cb;
}
}; // ConfirmInternet
SFXManager::get()->quickSound( "anvil" );
m_online_cb->setState(false);
new MessageDialog(message, MessageDialog::MESSAGE_DIALOG_CONFIRM,
new ConfirmInternet(this, m_online_cb), true);
}
}
makeEntryFieldsVisible();

View File

@ -32,12 +32,28 @@ std::string CommandLine::m_exec_name="";
void CommandLine::init(unsigned int argc, char *argv[])
{
if (argc > 0)
{
m_exec_name = argv[0];
}
for(unsigned int i=1; i<argc; i++)
for (unsigned int i = 1; i < argc; i++)
{
m_argv.push_back(argv[i]);
}
} // CommandLine
// ----------------------------------------------------------------------------
void CommandLine::addArgsFromUserConfig()
{
std::vector<std::string> config_args;
config_args = StringUtils::split(UserConfigParams::m_commandline, ' ');
for (std::string config_arg : config_args)
{
m_argv.push_back(config_arg);
}
}
// ----------------------------------------------------------------------------
bool CommandLine::has(const std::string &option)
{

View File

@ -79,6 +79,7 @@ private:
public:
static void init(unsigned int argc, char *argv[]);
static void addArgsFromUserConfig();
static void reportInvalidParameters();
static bool has(const std::string &option);
// ------------------------------------------------------------------------