Merge remote-tracking branch 'origin/master' into galtgendo/sdl2

This commit is contained in:
Tim Felgentreff 2020-04-13 10:59:04 +02:00
commit af307f9f17
236 changed files with 24193 additions and 2687 deletions

2
.gitignore vendored
View file

@ -26,3 +26,5 @@ obj-*
./stratagus.suo
./tolua.cpp
./tolua.cpp.rule
build
.vscode

View file

@ -1,8 +1,4 @@
language: cpp
# sudo: required
# compiler:
# - gcc
# - clang
os:
- linux
- osx
@ -20,11 +16,32 @@ before_script:
- "if [ $TRAVIS_OS_NAME == osx ]; then brew install lua51 sdl; \
git clone https://github.com/LuaDist/toluapp.git; \
cd toluapp; mkdir build;
cd build; cmake ..; make && sudo make install; \
cd build; cmake ..; make; \
export CMAKEARGS=\"-DTOLUA++_INCLUDE_DIR=$(pwd)/../include/ -DTOLUA++_LIBRARY=$(pwd)/libtoluapp.dylib -DTOLUA++_APP=$(pwd)/toluapp -DWITH_X11=OFF\";
cd ..;
cd ..;
fi"
- mkdir build
- cd build
- cmake ..
- cmake $CMAKEARGS ..
script: make
after_success:
- "if [ $TRAVIS_REPO_SLUG == Wargus/stratagus -a \
$TRAVIS_BRANCH == master -a \
$TRAVIS_OS_NAME == osx -a \
$TRAVIS_PULL_REQUEST == 'false' ]; then \
git clone https://${GH_TOKEN}@github.com/Wargus/stratagus.wiki.git;
mkdir -p stratagus.wiki/$TRAVIS_OS_NAME;
cp $TRAVIS_BUILD_DIR/build/stratagus stratagus.wiki/$TRAVIS_OS_NAME/;
rm -rf macdylibbundler; git clone https://github.com/auriamg/macdylibbundler;
cd macdylibbundler; make; cd ..;
macdylibbundler/dylibbundler -cd -of -b -x stratagus.wiki/$TRAVIS_OS_NAME/stratagus -d stratagus.wiki/libs/;
cd stratagus.wiki/;
git config --global user.email \"travis-ci@travis.org\";
git config --global user.name \"Travis CI\";
git add $TRAVIS_OS_NAME/stratagus;
git add libs;
git commit --amend -C HEAD;
git push -fq origin master;
cd ..;
fi"

View file

@ -34,7 +34,7 @@ set(STRATAGUS_MAJOR_VERSION 2)
# Stratagus minor version (maximum 99)
set(STRATAGUS_MINOR_VERSION 4)
# Stratagus patch level (maximum 99)
set(STRATAGUS_PATCH_LEVEL 0)
set(STRATAGUS_PATCH_LEVEL 2)
# Stratagus patch level 2
set(STRATAGUS_PATCH_LEVEL2 0)
#########################
@ -65,6 +65,7 @@ set(action_SRCS
src/action/action_built.cpp
src/action/action_defend.cpp
src/action/action_die.cpp
src/action/action_explore.cpp
src/action/action_follow.cpp
src/action/action_move.cpp
src/action/action_patrol.cpp
@ -675,7 +676,7 @@ endif()
# Options for compiling
if(WIN32)
option(ENABLE_STDIO_REDIRECT "Redirect Stratagus console output to files on Windows" OFF)
option(ENABLE_STDIO_REDIRECT "Redirect Stratagus console output to files on Windows" ON)
option(ENABLE_NSIS "Create Stratagus Window NSIS Installer" OFF)
endif()
@ -759,6 +760,10 @@ if(WITH_MNG AND MNG_FOUND)
add_definitions(-DUSE_MNG)
include_directories(${MNG_INCLUDE_DIR})
set(stratagus_LIBS ${stratagus_LIBS} ${MNG_LIBRARY})
if (MSVC)
include_directories(${JPEG_INCLUDE_DIR})
set(stratagus_LIBS ${stratagus_LIBS} ${JPEG_LIBRARY})
endif()
endif()
if(WITH_OGGVORBIS AND OGGVORBIS_FOUND)
@ -841,10 +846,14 @@ if(BEOS)
set(stratagus_SRCS ${stratagus_SRCS} ${beos_SRCS})
endif()
if(HAIKU)
set(stratagus_LIBS ${stratagus_LIBS} -lnetwork)
endif()
# Stratagus needs to have char by default signed
# No idea how to tell this to other compilers
if(CMAKE_COMPILER_IS_GNUCXX)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsigned-char")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsigned-char -std=gnu++0x -Werror")
endif()
if(CMAKE_COMPILER_IS_GNUC)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsigned-char")
@ -972,6 +981,8 @@ elseif(BSD)
message("Platform: BSD")
elseif(BEOS)
message("Platform: BEOS")
elseif(HAIKU)
message("Platform: Haiku")
elseif(LINUX)
message("Platform: Linux")
else()
@ -1078,7 +1089,11 @@ add_custom_command(OUTPUT tolua.cpp
VERBATIM
)
add_executable(stratagus WIN32 ${stratagus_SRCS} ${stratagus_HDRS})
if (ENABLE_STDIO_REDIRECT)
add_executable(stratagus WIN32 ${stratagus_SRCS} ${stratagus_HDRS})
else ()
add_executable(stratagus ${stratagus_SRCS} ${stratagus_HDRS})
endif ()
target_link_libraries(stratagus ${stratagus_LIBS})
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
@ -1149,7 +1164,9 @@ endif()
set(gameheaders_HDRS
gameheaders/stratagus-game-installer.nsi
gameheaders/stratagus-gameutils.h
gameheaders/stratagus-game-launcher.h
gameheaders/stratagus-tinyfiledialogs.h
)
source_group(gameheaders FILES ${gameheaders_HDRS})
@ -1212,6 +1229,14 @@ if(WIN32 AND ENABLE_NSIS AND MAKENSIS_FOUND)
file(COPY ${GLIB_DLL} DESTINATION ${CMAKE_CURRENT_BINARY_DIR})
file(COPY ${GTHREAD_DLL} DESTINATION ${CMAKE_CURRENT_BINARY_DIR})
endif()
# also ship lua51.dll
find_file(LUA_DLL lua51.dll HINTS ${CMAKE_PREFIX_PATH} PATH_SUFFIXES bin lib)
file(COPY ${LUA_DLL} DESTINATION ${CMAKE_CURRENT_BINARY_DIR})
set(MAKENSIS_FLAGS ${MAKENSIS_FLAGS} -DLUADLL=lua51.dll)
# ship SDL.dll
find_file(SDL_DLL SDL.dll HINTS ${CMAKE_PREFIX_PATH} PATH_SUFFIXES bin lib)
file(COPY ${SDL_DLL} DESTINATION ${CMAKE_CURRENT_BINARY_DIR})
set(MAKENSIS_FLAGS ${MAKENSIS_FLAGS} -DSDL=SDL.dll)
add_custom_command(OUTPUT Stratagus-${STRATAGUS_VERSION}${MAKENSIS_SUFFIX}
COMMAND ${MAKENSIS} ARGS ${MAKENSIS_FLAGS} -DVERSION=${STRATAGUS_VERSION} -DVIVERSION=${STRATAGUS_VERSION_FULL} ${CMAKE_CURRENT_SOURCE_DIR}/src/win32/stratagus.nsi
DEPENDS src/win32/stratagus.nsi stratagus COPYING
@ -1227,7 +1252,7 @@ install(TARGETS stratagus DESTINATION ${GAMEDIR})
install(TARGETS png2stratagus DESTINATION ${BINDIR})
if(SQLITE_FOUND)
install(TARGETS metaserver DESTINATION ${SBINDIR})
install(TARGETS metaserver DESTINATION ${BINDIR} RENAME stratagus-metaserver)
endif()
if(ENABLE_DOC AND DOXYGEN_FOUND)
@ -1255,3 +1280,14 @@ endif()
########### clean files ###############
set_directory_properties(PROPERTIES ADDITIONAL_MAKE_CLEAN_FILES "${CLEAN_FILES}")
# uninstall target
if(NOT TARGET uninstall)
configure_file(
"${CMAKE_CURRENT_SOURCE_DIR}/cmake_uninstall.cmake.in"
"${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake"
IMMEDIATE @ONLY)
add_custom_target(uninstall
COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake)
endif()

47
COPYING
View file

@ -1,12 +1,12 @@
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Copyright (C) 1989, 1991 Free Software Foundation, Inc., <http://fsf.org/>
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
@ -15,7 +15,7 @@ software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Library General Public License instead.) You can apply it to
the GNU Lesser General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
@ -55,8 +55,8 @@ patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
@ -110,7 +110,7 @@ above, provided that you also meet all of these conditions:
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
@ -168,7 +168,7 @@ access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
@ -225,7 +225,7 @@ impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
@ -255,7 +255,7 @@ make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
@ -277,9 +277,9 @@ YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
@ -290,8 +290,8 @@ to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
{description}
Copyright (C) {year} {fullname}
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
@ -303,17 +303,16 @@ the "copyright" line and a pointer to where the full notice is found.
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
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.
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) year name of author
Gnomovision version 69, Copyright (C) year name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
@ -330,11 +329,11 @@ necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
<signature of Ty Coon>, 1 April 1989
{signature of Ty Coon}, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Library General
library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License.

View file

@ -1,17 +1,4 @@
Here is small HOWTO release new version of Stratagus
You need some linux machine (ideally ubuntu) with:
git, debhelper, devscripts, cmake, make, nsis, upx, gnupg
For windows installers you need:
cmake toolchain file (see example)
windows gcc cross compiler: g++-mingw-w64
windows stratagus dependencies (from https://launchpad.net/~mingw-packages/+archive/ppa):
libmikmod-mingw-w64-cross, libogg-mingw-w64-cross, libpng-mingw-w64-cross, libpthread-mingw-w64-cross, libsdl1.2-mingw-w64-cross,
libtheora-mingw-w64-cross, libvorbis-mingw-w64-cross, lua5.1-mingw-w64-cross, tolua++-mingw-w64-cross, zlib-mingw-w64-cross
Download source code:
git clone https://github.com/Wargus/stratagus && cd stratagus
Here is small HOWTO release new version of Stratagus (and also Wargus/War1gus/Stargus/...)
Increase version in file:
CMakeLists.txt
@ -20,46 +7,31 @@ Update changelog in file:
doc/changelog.html
Increase version and update changelog for debian:
dch -i
dch -vNEWVERSION
dch -r
Commit changes to git and create tag:
Update copyright information for Debian:
debian/copyright
Update Copyright information in NSI installer:
src/win32/stratagus.nsi
Tag the new release in https://github.com/Wargus/win32-stratagus-dependencies
and wait for it to run through on the Appveyor CI. This will automatically
cause a release with the tag name to be created, and the windows dependencies
will be uploaded there.
Tag the new release here and wait for it to run through the CIs. Appveyor and
Travis will upload new versions for Windows and OSX, and Launchpad will
automatically build new debian packages:
git commit -a -m "Release version <version>"
git tag <version>
git push --tags origin master
Create orig tarball + sign:
git clean -idx
tar czvf ../stratagus_<version>.orig.tar.gz
gpg --armor --sign --detach-sig ../stratagus_*.orig.tar.gz
For Wargus/War1gus/Stargus we have a release.rb script. Run it without any
arguments, and it will tell you how to call it to start the release process
for this particular project.
Create ubuntu release packages:
(happens automatically on commit in launchpad)
Tag the new release in Wargus/War1gus/Stargus/... these repositories should be
set up to also use the appropriate release source from the Stratagus releases.
Create win32 installer + sign:
rm -rf build && mkdir build && cd build
cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_TOOLCHAIN_FILE=/path/to/win32/toolchain/file -DENABLE_STATIC=ON -DENABLE_NSIS=ON -DENABLE_UPX=ON -DENABLE_STRIP=ON ..
make && mv Stratagus-*.exe ../../ && cd ..
gpg --armor --sign --detach-sig ../Stratagus-*.exe
Create win64 installer + sign:
rm -rf build && mkdir build && cd build
cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_TOOLCHAIN_FILE=/path/to/win64/toolchain/file -DENABLE_STATIC=ON -DENABLE_NSIS=ON -DENABLE_STRIP=ON ..
make && mv Stratagus-*-x86_64.exe ../../ && cd ..
gpg --armor --sign --detach-sig ../Stratagus-*-x86_64.exe
Create new release on github, upload windows installers with signatures:
via web interface on https://github.com/Wargus/stratagus/releases
Upload ubuntu dsc packages to stratagus PPA:
dput ppa:stratagus/ppa ../stratagus_*ubuntu*_source.changes
Example of cmake win32 toolchain file for windows:
SET(CMAKE_SYSTEM_NAME Windows)
SET(CMAKE_C_COMPILER i686-w64-mingw32-gcc)
SET(CMAKE_CXX_COMPILER i686-w64-mingw32-g++)
SET(CMAKE_RC_COMPILER i686-w64-mingw32-windres)
SET(CMAKE_FIND_ROOT_PATH /usr/i686-w64-mingw32)
SET(CMAKE_PREFIX_PATH /usr/i686-w64-mingw32)
SET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
SET(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
SET(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)

View file

@ -1,4 +1,4 @@
________________________________README_________________________________
_______________________________________________________________________
_________ __ __
/ _____// |_____________ _/ |______ ____ __ __ ______
\_____ \\ __\_ __ \__ \\ __\__ \ / ___\| | \/ ___/
@ -9,14 +9,37 @@
T H E W A R B E G I N S
Stratagus - A free fantasy real time strategy game engine
[![Join the chat at https://gitter.im/Wargus](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/Wargus?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
Windows: <a href="https://ci.appveyor.com/project/timfel/stratagus"><img width="100" src="https://ci.appveyor.com/api/projects/status/github/Wargus/stratagus?branch=master&svg=true"></a>
Linux & OSX: [![Build Status](https://travis-ci.org/Wargus/stratagus.svg?branch=master)](https://travis-ci.org/Wargus/stratagus)
Nightly builds are available:
For Mac OS X, Stratagus comes bundled in the app bundles for Wargus, Stargus, and War1gus:
- Wargus: https://github.com/Wargus/stratagus/wiki/osx/Wargus.app.tar.gz
- War1gus: https://github.com/Wargus/stratagus/wiki/osx/War1gus.app.tar.gz
- Stargus: https://github.com/Wargus/stratagus/wiki/osx/Stargus.app.tar.gz
On Ubuntu/Debian, you probably want the deb packages:
- https://launchpad.net/~stratagus/+archive/ubuntu/ppa
- Note that the game packages you probably want are `wargus`, `war1gus`, and `stargus`
For Windows, you likely want the game installers:
- Wargus: https://github.com/Wargus/wargus/releases
- War1gus: https://github.com/Wargus/war1gus/releases
- Stargus: https://github.com/Wargus/stargus/releases
If you do indeed need the Stratagus engine itself, nightly builds are available:
- Windows Installer: https://github.com/Wargus/stratagus/releases/tag/master-builds
- Ubuntu/Debian Packages: https://launchpad.net/~stratagus/+archive/ubuntu/ppa
Read 'doc/index.html' for general information and license information.
Read 'doc/install.html' for Stratagus installation instructions.
Read 'doc/changelog.html' for the Stratagus changelog.
The Mac and Windows builds are done on Appveyor and Travis. The Ubuntu packages
are built on Launchpad:
- https://code.launchpad.net/~stratagus/+recipe/stratagus-github
- https://code.launchpad.net/~stratagus/+recipe/war1gus-github
- https://code.launchpad.net/~stratagus/+recipe/stargus-github
- https://code.launchpad.net/~stratagus/+recipe/wargus-github

View file

@ -1,24 +1,39 @@
os: Visual Studio 2015
shallow_clone: true
configuration:
- Release
before_build:
- mkdir build
- cd build
- appveyor DownloadFile https://github.com/Wargus/stratagus/releases/download/2015-30-11/dependencies.zip
- appveyor DownloadFile https://github.com/Wargus/win32-stratagus-dependencies/releases/download/master-builds/dependencies.zip
- 7z x dependencies.zip
- choco install nsis -pre
- cmake -G "Visual Studio 14 2015" -DCMAKE_PREFIX_PATH="%cd%\\dependencies" -DENABLE_NSIS=ON ..
- appveyor DownloadFile https://github.com/jimpark/unsis/releases/download/2.50.0/nsis-2.50.0-Unicode-setup.exe
- nsis-2.50.0-Unicode-setup.exe /S /D=C:\Program Files (x86)\NSIS
- cmake -G "Visual Studio 14 2015" -T v140_xp -DCMAKE_PREFIX_PATH="%cd%\\dependencies" -DENABLE_NSIS=ON -DENABLE_STDIO_REDIRECT=ON ..
- cd ..
after_build:
- 7z a compiled-binaries.zip %cd%\build\stratagus.exe %cd%\build\dependencies\bin\*.dll
artifacts:
- path: build\Stratagus-*.exe
- path: compiled-binaries.zip
deploy:
release: master-builds
description: 'Automatic builds from the master branch'
provider: GitHub
auth_token:
secure: NMy2KE3EpZTjverxNzEAoBnlV+7VLGvwy3e1WEIrliFy3R1oxuT+AgGUDcRwv9y/
artifact: /.*exe/
draft: false
prerelease: true
on:
branch: master
- provider: GitHub
release: master-builds
description: 'Automatic builds from the master branch'
auth_token:
secure: NMy2KE3EpZTjverxNzEAoBnlV+7VLGvwy3e1WEIrliFy3R1oxuT+AgGUDcRwv9y/
artifact: /.*(exe|zip)/
draft: false
prerelease: true
on:
branch: master
- provider: GitHub
release: $(APPVEYOR_REPO_TAG_NAME)
description: 'Release'
auth_token:
secure: NMy2KE3EpZTjverxNzEAoBnlV+7VLGvwy3e1WEIrliFy3R1oxuT+AgGUDcRwv9y/
artifact: /.*(exe|zip)/
draft: false
prerelease: false
on:
appveyor_repo_tag: true

View file

@ -10,19 +10,33 @@
# Redistribution and use is allowed according to the terms of the BSD license.
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
if(MNG_INCLUDE_DIR AND MNG_LIBRARY)
if(MNG_INCLUDE_DIR AND MNG_LIBRARY AND ((NOT MSVC) OR (JPEG_INCLUDE_DIR AND JPEG_LIBRARY)))
set(MNG_FOUND true)
else()
find_path(MNG_INCLUDE_DIR libmng.h)
find_library(MNG_LIBRARY NAMES mng)
if(MSVC)
find_path(JPEG_INCLUDE_DIR jpeglib.h)
find_library(JPEG_LIBRARY NAMES jpeg)
endif()
if(MNG_INCLUDE_DIR AND MNG_LIBRARY)
if(MNG_INCLUDE_DIR AND MNG_LIBRARY AND ((NOT MSVC) OR (JPEG_INCLUDE_DIR AND JPEG_LIBRARY)))
set(MNG_FOUND true)
message(STATUS "Found MNG: ${MNG_LIBRARY}")
if (MSVC)
message(STATUS "Found JPEG: ${JPEG_LIBRARY}")
endif()
else()
set(MNG_FOUND false)
if(MSVC AND (NOT (JPEG_INCLUDE_DIR AND JPEG_LIBRARY)))
message(STATUS "Could not find JPEG")
endif()
message(STATUS "Could not find MNG")
endif()
mark_as_advanced(MNG_INCLUDE_DIR MNG_LIBRARY)
if(MSVC)
mark_as_advanced(MNG_INCLUDE_DIR MNG_LIBRARY JPEG_INCLUDE_DIR JPEG_LIBRARY)
else()
mark_as_advanced(MNG_INCLUDE_DIR MNG_LIBRARY)
endif()
endif()

View file

@ -18,6 +18,7 @@
if ( SQLITE_INCLUDE_DIR AND SQLITE_LIBRARIES )
# in cache already
SET(Sqlite_FIND_QUIETLY TRUE)
SET(SQLITE_FOUND)
endif ( SQLITE_INCLUDE_DIR AND SQLITE_LIBRARIES )
# use pkg-config to get the directories and then use these values

21
cmake_uninstall.cmake.in Normal file
View file

@ -0,0 +1,21 @@
if(NOT EXISTS "@CMAKE_BINARY_DIR@/install_manifest.txt")
message(FATAL_ERROR "Cannot find install manifest: @CMAKE_BINARY_DIR@/install_manifest.txt")
endif(NOT EXISTS "@CMAKE_BINARY_DIR@/install_manifest.txt")
file(READ "@CMAKE_BINARY_DIR@/install_manifest.txt" files)
string(REGEX REPLACE "\n" ";" files "${files}")
foreach(file ${files})
message(STATUS "Uninstalling $ENV{DESTDIR}${file}")
if(IS_SYMLINK "$ENV{DESTDIR}${file}" OR EXISTS "$ENV{DESTDIR}${file}")
exec_program(
"@CMAKE_COMMAND@" ARGS "-E remove \"$ENV{DESTDIR}${file}\""
OUTPUT_VARIABLE rm_out
RETURN_VALUE rm_retval
)
if(NOT "${rm_retval}" STREQUAL 0)
message(FATAL_ERROR "Problem when removing $ENV{DESTDIR}${file}")
endif(NOT "${rm_retval}" STREQUAL 0)
else(IS_SYMLINK "$ENV{DESTDIR}${file}" OR EXISTS "$ENV{DESTDIR}${file}")
message(STATUS "File $ENV{DESTDIR}${file} does not exist.")
endif(IS_SYMLINK "$ENV{DESTDIR}${file}" OR EXISTS "$ENV{DESTDIR}${file}")
endforeach(file)

37
debian/changelog vendored
View file

@ -1,3 +1,40 @@
stratagus (2.4.2) xenial; urgency=medium
* Force load progress to screen only every 500ms. On modern machines,
loading was so fast that almost all time was spent in screen redraw
rather than loading.
* Add support for game launchers to have optional contrib files that are
just ignored if they are not present
* Reliability: Fall back to software and windowed rendering before
giving up on startup. This fixes the trouble some people have when
they enable OpenGL or an unsupported fullscreen resolution and now the
game won't start. Otherwise, they have to know where the
preferences.lua file is stored and either delete or edit it.
* Commandline: -Z now takes a WIDTHxHEIGHT argument, too, to define the
base resolution to scale up from.
* Bugfix: Warping mouse coordinates in zoomed mode was not scaled correctly.
* Metaserver: Implement simple UDP hole punching to allow connections through some NATs
* Metaserver: Add CREATEGAME command
* Metaserver: Allow access for non-registered users
* Bugfix: Remove checksumming of lua files for now due to issues
* Installation: Include tinyfiledialogs and make extraction of game
data more consistent for games that want it by offering the
functionality on first launch based on header defines in the game
launchers.
* Bugfix: Regenerating forest tiles should no longer set the wrong tile index
* Graphics: Allow each game to ship its own shaders by searching in the game data path
* Keybindings: Use Alt+/ and Alt+\ do change shaders globally
-- Tim Felgentreff <timfelgentreff@gmail.com> Sun, 11 Jun 2017 12:10:55 +0200
stratagus (2.4.1-0) unstable; urgency=low
* Add support for icon frames in engine
* Add support for selecting and giving orders to multiple buildings
* Add checksumming for loaded lua files, to avoid incompatible multiplayer clients
* Update shader support to use pre-compiled shaders from libretro
-- Tim Felgentreff <timfelgentreff@gmail.com> Wed, 2 Dec 2015 12:41:01 +0100
stratagus (2.4.0-1) unstable; urgency=low
* Introduced OpenGL shaders for pixel scaling

6
debian/control vendored
View file

@ -4,8 +4,8 @@ Priority: optional
Maintainer: cybermind <iddqd_mail@mail.ru>
Build-Depends: debhelper (>= 7), cmake (>= 2.6), doxygen,
imagemagick, sharutils, liblua5.1-dev | liblua5.1-0-dev, libtolua++5.1-dev,
zlib1g-dev, libbz2-dev, libpng12-dev (>= 1.2.5), libmng-dev,
libmikmod2-dev, libogg-dev, libvorbis-dev, libtheora-dev,
zlib1g-dev, libbz2-dev, libpng12-dev (>= 1.2.5) | libpng-dev (>= 1.2.5),
libmng-dev, libmikmod2-dev, libogg-dev, libvorbis-dev, libtheora-dev,
libsdl1.2-dev (>> 1.2.2), libx11-dev, libsqlite3-dev,
libgles1-sgx-img-dev | libglu1-mesa-dev | libglu-dev | libgles1-mesa-dev,
libsdl-gles1.2-dev | libglu1-mesa-dev | libglu-dev, libfluidsynth-dev
@ -16,7 +16,7 @@ Vcs-Git: https://github.com/Wargus/stratagus.git
Package: stratagus
Architecture: any
Suggests: wargus, war1gus, stargus, stratagus-data
Recommends: wargus, war1gus, stargus, stratagus-data
Depends: ${misc:Depends}, ${shlibs:Depends}
Description: Strategy Gaming Engine
Stratagus is a free cross-platform real-time strategy gaming engine.

4
debian/copyright vendored
View file

@ -6,15 +6,17 @@ Copyright:
© 2004 David Martínez Moreno <ender@debian.org>
© 2010-2012 Pali Rohár <pali.rohar@gmail.com>
© 2015 cybermind <iddqd_mail@mail.ru>
© 2016-2018 Tim Felgentreff <timfelgentreff@gmail.com>
License: GPL-2+
Files: *
© 1998-2015 by The Stratagus Project, including:
© 1998-2017 by The Stratagus Project, including:
Jimmy Salmon <jsalmon3@users.sourceforge.net>
Russel Smith <mr-russ@users.sourceforge.net>
Nehal Mistry <nehalmistry@users.sourceforge.net>
Pali Rohár <pali.rohar@gmail.com>
cybermind <iddqd_mail@mail.ru>
Tim Felgentreff <timfelgentreff@gmail.com>
License: GPL-2+
License: GPL-2+

2
debian/rules vendored
View file

@ -45,7 +45,7 @@ override_dh_auto_build:
override_dh_install:
dh_install
dh_auto_install --builddirectory=obj-$(DEB_BUILD_GNU_TYPE)-dbg --destdir=debian/stratagus-dbg
rm -f debian/stratagus-dbg/usr/bin/png2stratagus debian/stratagus-dbg/usr/sbin/metaserver
rm -f debian/stratagus-dbg/usr/bin/png2stratagus
convert src/win32/stratagus.ico debian/stratagus/usr/share/pixmaps/stratagus.png
override_dh_shlibdeps:

View file

@ -15,8 +15,8 @@
----
---- 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., 59 Temple Place - Suite 330, Boston, MA
---- 02111-1307, USA.
---- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
---- 02110-1301, USA.
-->
<title>ChangeLog: Stratagus Version 2.3</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
@ -40,6 +40,73 @@
<ul>
<p/>
<p/><li>2.4.3 Released<p/></li>
<ul>
<li>
Allow specifying colors, percentages, and border for the LifeBar.
</li>
</ul>
</li><p/><li>2.4.2 Released<p/></li>
<ul>
<li>
Force load progress to screen only every 500ms. On modern machines, loading
was so fast that almost all time was spent in screen redraw rather than loading.
</li>
<li>
Add support for game launchers to have optional contrib files that are just ignored if they are not present
</li>
<li>
Add "make uninstall" target
</li>
<li>
Reliability: Fall back to software and windowed rendering before
giving up on startup. This fixes the trouble some people have when
they enable OpenGL or an unsupported fullscreen resolution and now the
game won't start. Otherwise, they have to know where the
preferences.lua file is stored and either delete or edit it.
</li>
<li>
Commandline: -Z now takes a WIDTHxHEIGHT argument, too, to define the
base resolution to scale up from.
</li>
<li>
Bugfix: Warping mouse coordinates in zoomed mode was not scaled correctly.
</li>
<li>
Metaserver: Implement simple UDP hole punching to allow connections through some NATs
</li>
<li>
Metaserver: Add CREATEGAME command
</li>
<li>
Metaserver: Allow access for non-registered users
</li>
<li>
Bugfix: Remove checksumming of lua files for now due to issues
</li>
<li>
Installation: Include tinyfiledialogs and make extraction of game
data more consistent for games that want it by offering the
functionality on first launch based on header defines in the game
launchers.
</li>
<li>
Bugfix: Regenerating forest tiles should no longer set the wrong tile index
</li>
<li>
Graphics: Allow each game to ship its own shaders by searching in the game data path
</li>
<li>
Keybindings: Use Alt+/ and Alt+\ do change shaders globally
</li>
</ul>
<p/><li>2.4.1 Released<p/></li>
<ul>
<li>Add support for icon frames in engine</li>
<li>Add support for selecting and giving orders to multiple buildings</li>
<li>Add checksumming for loaded lua files, to avoid incompatible multiplayer clients</li>
<li>Update shader support to use pre-compiled shaders from libretro</li>
</ul>
<p/><li>2.4.0 Released<p/></li>
<ul>
<li>Introduced OpenGL shaders for pixel scaling</li>

View file

@ -16,8 +16,8 @@
----
---- 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., 59 Temple Place - Suite 330, Boston, MA
---- 02111-1307, USA.
---- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
---- 02110-1301, USA.
-->
<title>Development for Stratagus</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">

View file

@ -15,8 +15,8 @@
----
---- 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., 59 Temple Place - Suite 330, Boston, MA
---- 02111-1307, USA.
---- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
---- 02110-1301, USA.
-->
<title>FAQ for Stratagus</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">

View file

@ -15,8 +15,8 @@
----
---- 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., 59 Temple Place - Suite 330, Boston, MA
---- 02111-1307, USA.
---- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
---- 02110-1301, USA.
-->
<title>Stratagus Palette Documentation</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">

View file

@ -15,8 +15,8 @@
----
---- 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., 59 Temple Place - Suite 330, Boston, MA
---- 02111-1307, USA.
---- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
---- 02110-1301, USA.
-->
<title>Stratagus tileset graphic format</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">

View file

@ -15,8 +15,8 @@
----
---- 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., 59 Temple Place - Suite 330, Boston, MA
---- 02111-1307, USA.
---- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
---- 02110-1301, USA.
-->
<title>Stratagus</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
@ -57,7 +57,7 @@
<ul>
<li>Wargus - Warcraft II - <a href="https://launchpad.net/wargus">https://launchpad.net/wargus</a>
<li>Doom Wars - <a href="http://stratagus.com/games/doom-wars">http://stratagus.com/games/doom-wars</a>
<li>Wyrmsun - <a href="ttps://github.com/andrettin/wyrmsun">ttps://github.com/andrettin/wyrmsun</a><br>
<li>Wyrmsun - <a href="https://github.com/andrettin/wyrmsun">https://github.com/andrettin/wyrmsun</a><br>
(uses modified engine version : <a href="https://github.com/Andrettin/Wyrmgus">https://github.com/Andrettin/Wyrmgus</a>)</li>
<li>War1gus - Warcraft I - <a href="https://launchpad.net/war1gus">https://launchpad.net/war1gus</a>
<li>Stargus - Starcraft I - <a href="https://launchpad.net/stargus">https://launchpad.net/stargus</a>

View file

@ -15,8 +15,8 @@
----
---- 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., 59 Temple Place - Suite 330, Boston, MA
---- 02111-1307, USA.
---- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
---- 02110-1301, USA.
-->
<title>Stratagus Installation</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">

View file

@ -15,8 +15,8 @@
----
---- 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., 59 Temple Place - Suite 330, Boston, MA
---- 02111-1307, USA.
---- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
---- 02110-1301, USA.
-->
<title>Stratagus Media Documentation</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">

View file

@ -14,8 +14,8 @@
----
---- 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., 59 Temple Place - Suite 330, Boston, MA
---- 02111-1307, USA.
---- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
---- 02110-1301, USA.
-->
<title>Stratagus Configuration Language Description: Artificial Intelligence(AI)</title>
<meta name="Author" content="johns98@gmx.net">

View file

@ -14,8 +14,8 @@
----
---- 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., 59 Temple Place - Suite 330, Boston, MA
---- 02111-1307, USA.
---- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
---- 02110-1301, USA.
-->
<title>Stratagus Configuration Language Description: Config</title>
<meta name="Author" content="johns98@gmx.net">

View file

@ -14,8 +14,8 @@
----
---- 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., 59 Temple Place - Suite 330, Boston, MA
---- 02111-1307, USA.
---- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
---- 02110-1301, USA.
-->
<title>Stratagus Configuration Language Description: Icon</title>
<meta name="Author" content="johns98@gmx.net">

View file

@ -14,8 +14,8 @@
----
---- 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., 59 Temple Place - Suite 330, Boston, MA
---- 02111-1307, USA.
---- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
---- 02110-1301, USA.
-->
<title>Stratagus Configuration Language Description: Index</title>
<meta name="Author" content="johns98@gmx.net">

View file

@ -14,8 +14,8 @@
----
---- 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., 59 Temple Place - Suite 330, Boston, MA
---- 02111-1307, USA.
---- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
---- 02110-1301, USA.
-->
<title>Stratagus Configuration Language Description: Magic</title>
<meta name="Author" content="cleonard@go.ro">

View file

@ -14,8 +14,8 @@
----
---- 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., 59 Temple Place - Suite 330, Boston, MA
---- 02111-1307, USA.
---- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
---- 02110-1301, USA.
-->
<title>Stratagus Configuration Language Description: PUD conversion</title>
</head>

View file

@ -14,8 +14,8 @@
----
---- 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., 59 Temple Place - Suite 330, Boston, MA
---- 02111-1307, USA.
---- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
---- 02110-1301, USA.
-->
<title>Stratagus Configuration Language Description: PUD conversion</title>
</head>

View file

@ -14,8 +14,8 @@
----
---- 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., 59 Temple Place - Suite 330, Boston, MA
---- 02111-1307, USA.
---- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
---- 02110-1301, USA.
-->
<title>Stratagus Configuration Language Description: Icon</title>
<meta name="Author" content="johns98@gmx.net">

View file

@ -14,8 +14,8 @@
----
---- 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., 59 Temple Place - Suite 330, Boston, MA
---- 02111-1307, USA.
---- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
---- 02110-1301, USA.
-->
<title>Stratagus Configuration Language Description: Save Game Files</title>
<meta name="Author" content="johns98@gmx.net">

View file

@ -14,8 +14,8 @@
----
---- 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., 59 Temple Place - Suite 330, Boston, MA
---- 02111-1307, USA.
---- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
---- 02110-1301, USA.
-->
<title>Stratagus Configuration Language Description: Icon</title>
<meta name="Author" content="johns98@gmx.net">

View file

@ -14,8 +14,8 @@
----
---- 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., 59 Temple Place - Suite 330, Boston, MA
---- 02111-1307, USA.
---- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
---- 02110-1301, USA.
-->
<title>Stratagus Configuration Language Description: Tileset</title>
<meta name="Author" content="johns98@gmx.net">

View file

@ -14,8 +14,8 @@
----
---- 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., 59 Temple Place - Suite 330, Boston, MA
---- 02111-1307, USA.
---- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
---- 02110-1301, USA.
-->
<title>Stratagus Configuration Language Description: Triggers</title>
<meta name="Keyword" content="ccl,tileset">

View file

@ -14,8 +14,8 @@
----
---- 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., 59 Temple Place - Suite 330, Boston, MA
---- 02111-1307, USA.
---- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
---- 02110-1301, USA.
-->
<title>Stratagus Configuration Language Description: User Interface (UI)</title>
<meta name="Author" content="johns98@gmx.net">
@ -54,6 +54,7 @@
<a href="#DefineUI">DefineUI</a>
<a href="#DefineViewports">DefineViewports</a>
<a href="#SetGameCursor">SetGameCursor</a>
<a href="#Icon Frame">Icon Frame</a>
<hr>
<h2>Intro - Introduction to UI functions and variables</h2>
@ -231,7 +232,11 @@ Selected, Clicked, Disabled, or the Default setting. Possible tags:
<dd>Display the text at this position (overrides the main position).
</dd>
<dt>Border = { Color = color, Size = size}</dt>
<dd>Draw a border with the specified color and size.
<dd>Draw a border with the specified color and size, with the border flashing
</dd>
</dl>
<dt>Border = { SolidColor = color, Size = size}</dt>
<dd>Draw a border with the specified color and size, without any flashing of the border
</dd>
</dl>
</dd>
@ -913,6 +918,15 @@ Define panel content when an unit is selected.
<dd>Height of the bar.</dd>
<dt>Width = value</dt>
<dd>width of the bar.</dd>
<dt>Border = boolean</dt>
<dd>if true then add a border to the bar. Default is true.</dd>
<dt>Colors = list</dt>
<dd>A list of {percentage, color-name} pairs. The default is equivalent
to {{75, "dark-green"}, {50, "yellow"}, {25, "orange"}, {0,
"red"}}. The last element must start with "0". The meaning of the
number is the percentage above which the associated color takes
effect.
</dd>
</dl></dd>
<dt>"CompleteBar", {flag = value, ...}</dt>
<dd>Draw a bar which represent the variable.
@ -1261,6 +1275,16 @@ Set the game cursor.
SetGameCursor("cursor-point")
</pre>
<a name="Icon Frame"></a>
<h3>Icon Frame</h3>
Set a custom frame to be drawn around icons. Note that "IconsShift" has to be true.
<h4>Example</h4>
<pre>
Preference.IconsShift = true
Preference.IconFrameG = CGraphic:New("ui/" .. race .. "/icon_border.png", 62, 48)
Preference.PressedIconFrameG = CGraphic:New("ui/" .. race .. "/icon_border.png", 62, 48)
</pre>
<hr>
(C) Copyright 2002-2015 by The <a href="https://launchpad.net/stratagus">Stratagus</a> Project under the <a href="../gpl.html">GNU General Public License</a>.<br>
All trademarks and copyrights on this page are owned by their respective owners.<br>

View file

@ -14,8 +14,8 @@
----
---- 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., 59 Temple Place - Suite 330, Boston, MA
---- 02111-1307, USA.
---- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
---- 02110-1301, USA.
-->
<title>Stratagus Configuration Language Description: UnitType</title>
<meta name="Author" content="johns98@gmx.net">

View file

@ -9,7 +9,7 @@
T H E W A R B E G I N S
Stratagus - A free fantasy real time strategy game engine
stratagus-game-launcher.h - Stratagus Game Launcher
stratagus-game-launcher.h - Stratagus Game Launcher
Copyright (C) 2010-2011 Pali Rohár <pali.rohar@gmail.com>
This program is free software: you can redistribute it and/or modify
@ -24,7 +24,6 @@
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
@ -41,8 +40,14 @@
*
* ::GAME_CD
*
* ::GAME_CD_FILE_PATTERNS
*
* ::GAME
*
* ::EXTRACTOR_TOOL
*
* ::EXTRACTOR_ARGS
*
* On Non Windows system you need to specify also paths:
*
* ::DATA_PATH
@ -61,6 +66,9 @@
* #define GAME_NAME "My Game Name"
* #define GAME_CD "Original Game CD Name"
* #define GAME "my_game"
* #define GAME_CD_FILE_PATTERNS "*.WAR", "*.war"
* #define EXTRACTOR_TOOL "gametool"
* #define EXTRACTOR_ARGS "-v"
*
* #ifndef WIN32
* #define DATA_PATH "/usr/share/games/stratagus/my_game"
@ -83,11 +91,28 @@
* Full name of data CD
**/
/**
* \def GAME_CD_FILE_PATTERNS
* Comma-separated file patterns for the extraction wizard to help users select
* the right folder.
**/
/**
* \def GAME
* Short name of game (lower ascii chars without space)
**/
/**
* \def EXTRACTOR_TOOL
* The name of the game data extractor tool. This code will append the
* arguments, src, and destionation directories.
**/
/**
* \def EXTRACTOR_ARGS
* The default arguments of the game data extractor tool.
**/
/**
* \def DATA_PATH
* Path to game data directory
@ -103,14 +128,6 @@
* Path to stratagus executable binary
**/
/**
* \def TITLE_PNG
* OPTIONAL: Path to title screen (for testing if data was extracted)
**/
#ifndef TITLE_PNG
#define TITLE_PNG "%s\\graphics\\ui\\title.png"
#endif
/* Fake definitions for Doxygen */
#ifdef DOXYGEN
#define GAME_NAME
@ -121,56 +138,37 @@
#define STRATAGUS_BIN
#endif
#if ! defined (GAME_NAME) || ! defined (GAME_CD) || ! defined (GAME)
#if ! defined (GAME_NAME) || ! defined (GAME_CD) || ! defined (GAME) || ! defined(EXTRACTOR_TOOL)
#error You need to define all Game macros, see stratagus-game-launcher.h
#endif
#if ( defined (_MSC_VER) || defined (_WIN32) || defined (_WIN64) ) && ! defined (WIN32)
#define WIN32
#ifndef GAME_SHOULD_EXTRACT_AGAIN
#define GAME_SHOULD_EXTRACT_AGAIN false
#endif
/**
* \def TITLE_PNG
* OPTIONAL: Path to title screen (for testing if data was extracted)
**/
#ifndef TITLE_PNG
#ifdef WIN32
#define TITLE_PNG "%s\\graphics\\ui\\title.png"
#else
#define TITLE_PNG "%s/graphics/ui/title.png"
#endif
#endif
#ifndef WIN32
#if ! defined (DATA_PATH) || ! defined (SCRIPTS_PATH) || ! defined (STRATAGUS_BIN)
#error You need to define paths, see stratagus-game-launcher.h
#endif
#endif
#ifdef WIN32
#define WINVER 0x0501
#include <windows.h>
#include <wincon.h>
#include <process.h>
#include <errno.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#if defined(_MSC_VER) || defined(__MINGW32__)
#include <direct.h>
#define inline __inline
#define chdir _chdir
#define getcwd _getcwd
#define spawnvp _spawnvp
#define stat _stat
#pragma GCC diagnostic ignored "-Wwrite-strings"
#endif
#ifdef _MSC_VER
#pragma comment(linker, "/SUBSYSTEM:WINDOWS /ENTRY:mainCRTStartup")
#endif
#ifndef WIN32
#include <unistd.h>
#include <X11/Xlib.h>
#ifndef NOGTK
#include <gtk/gtk.h>
#endif
#endif
#ifdef _WIN64
#define REGKEY "Software\\Wow6432Node\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\Stratagus (64 bit)"
#elif defined (WIN32)
@ -179,66 +177,284 @@
#define TITLE GAME_NAME
#define STRATAGUS_NOT_FOUND "Stratagus is not installed.\nYou need Stratagus to run " GAME_NAME "!\nFirst install Stratagus from https://launchpad.net/stratagus"
#define DATA_NOT_EXTRACTED GAME_NAME " data was not extracted yet.\nYou need extract data from original " GAME_CD " first!"
#define NO_X_DISPLAY "Cannot open X Display"
#define CONSOLE_MODE_NOT_ROOT "You must be root to run " GAME_NAME " in console framebuffer mode"
#define DATA_NOT_EXTRACTED GAME_NAME " data was not extracted, is corrupted, or outdated.\nYou need to extract it from original " GAME_CD "."
#define BUFF_SIZE 1024
#include "stratagus-gameutils.h"
static void SetUserDataPath(char* data_path) {
#if defined(WIN32)
strcpy(data_path, getenv("APPDATA"));
#else
strcpy(data_path, getenv("HOME"));
#endif
int datalen = strlen(data_path);
#if defined(WIN32)
strcat(data_path, "\\Stratagus\\");
#elif defined(USE_MAC)
strcat(data_path, "/Library/Stratagus/");
#else
strcat(data_path, "/.stratagus/");
#endif
strcat(data_path, "data." GAME_NAME);
}
int check_version(char* tool_path, char* data_path) {
char buf[4096] = {'\0'};
sprintf(buf, "%s/extracted" , data_path);
FILE *f = fopen(buf, "r");
char dataversion[20] = {'\0'};
char toolversion[20] = {'\0'};
if (f) {
fgets(dataversion, 20, f);
fclose(f);
} else {
#ifdef CHECK_EXTRACTED_VERSION
return 0; // No file means we have a problem
#else
return 1; // No file means we don't care
#endif
}
#ifndef WIN32
int ConsoleMode = 0;
sprintf(buf, "%s -V", tool_path);
FILE *pipe = popen(buf, "r");
if (f) {
fgets(toolversion, 20, pipe);
pclose(pipe);
}
#else
sprintf(buf, "%s -V", tool_path); // tool_path is already quoted
HANDLE g_hChildStd_OUT_Rd = NULL;
HANDLE g_hChildStd_OUT_Wr = NULL;
SECURITY_ATTRIBUTES saAttr;
saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
saAttr.bInheritHandle = TRUE;
saAttr.lpSecurityDescriptor = NULL;
if (!CreatePipe(&g_hChildStd_OUT_Rd, &g_hChildStd_OUT_Wr, &saAttr, 0))
return 1;
if (!SetHandleInformation(g_hChildStd_OUT_Rd, HANDLE_FLAG_INHERIT, 0))
return 1;
PROCESS_INFORMATION piProcInfo;
STARTUPINFO siStartInfo;
ZeroMemory(&piProcInfo, sizeof(PROCESS_INFORMATION));
ZeroMemory(&siStartInfo, sizeof(STARTUPINFO));
siStartInfo.cb = sizeof(STARTUPINFO);
siStartInfo.hStdError = g_hChildStd_OUT_Wr;
siStartInfo.hStdOutput = g_hChildStd_OUT_Wr;
siStartInfo.dwFlags |= STARTF_USESTDHANDLES;
if (!CreateProcess(NULL, buf, NULL, NULL, TRUE, 0, NULL, NULL, &siStartInfo, &piProcInfo))
return 1;
CloseHandle(piProcInfo.hProcess);
CloseHandle(piProcInfo.hThread);
ReadFile(g_hChildStd_OUT_Rd, toolversion, 20, NULL, NULL);
#endif
// strip whitespace
for (size_t i=0, j=0; toolversion[j]=toolversion[i]; j+=!isspace(toolversion[i++]));
for (size_t i=0, j=0; dataversion[j]=dataversion[i]; j+=!isspace(dataversion[i++]));
if (strcmp(dataversion, toolversion) == 0) {
return 1;
}
return 0;
}
static void error(char * title, char * text) {
static void ExtractData(char* extractor_tool, char* destination, char* scripts_path, int force=0) {
if (force == 0) {
tinyfd_messageBox("Missing data",
DATA_NOT_EXTRACTED " Please select the " GAME_CD, "ok", "question", 1);
} else if (force == 1) {
tinyfd_messageBox("", "Please select the " GAME_CD, "ok", "question", 1);
} else if (force == 2) {
// pass
}
#ifdef USE_MAC
int patterncount = 0;
char* filepatterns[] = { NULL };
// file types as names not working at least on macOS sierra
#else
char* filepatterns[] = { GAME_CD_FILE_PATTERNS, NULL };
int patterncount = 0;
while (filepatterns[patterncount++] != NULL);
#endif
const char* datafile = tinyfd_openFileDialog(GAME_CD " location", "",
patterncount - 1, filepatterns, NULL, 0);
if (datafile == NULL) {
exit(-1);
}
char srcfolder[1024] = {'\0'};
strcpy(srcfolder, datafile);
char* sourcepath = strdup(scripts_path);
#ifdef WIN32
MessageBox(NULL, text, title, MB_OK | MB_ICONERROR);
#else
#ifdef NOGTK
{
#else
if ( ! ConsoleMode ) {
GtkWidget * window = NULL;
GtkWidget * dialog = NULL;
dialog = gtk_message_dialog_new(GTK_WINDOW(window), GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, "%s", text);
gtk_window_set_title(GTK_WINDOW(dialog), title);
gtk_window_set_skip_pager_hint(GTK_WINDOW(dialog), 0);
gtk_window_set_skip_taskbar_hint(GTK_WINDOW(dialog), 0);
gtk_label_set_selectable(GTK_LABEL(GTK_MESSAGE_DIALOG(dialog)->label), 0);
gtk_dialog_run(GTK_DIALOG(dialog));
gtk_widget_destroy(dialog);
} else {
#endif
fprintf(stderr, "%s -- Error: %s\n", title, text);
if (sourcepath[0] == '"') {
// if scripts_path is quoted, remove the quotes, i.e.,
// copy all but the first until all but the last char.
// sourcepath is already large enough because it used to contain the
// entire scripts_path
strncpy(sourcepath, scripts_path + 1, strlen(scripts_path) - 2);
sourcepath[strlen(scripts_path) - 2] = '\0';
}
#endif
exit(1);
mkdir_p(destination);
parentdir(srcfolder);
struct stat st;
if (stat(sourcepath, &st) != 0) {
// deployment time path not found, try compile time path
strcpy(sourcepath, SRC_PATH());
parentdir(sourcepath);
}
#ifndef WIN32
if (stat(sourcepath, &st) != 0) {
// deployment time path might be same as extractor
strcpy(sourcepath, extractor_tool);
parentdir(sourcepath);
}
#endif
if (stat(sourcepath, &st) != 0) {
// scripts not found, abort!
tinyfd_messageBox("Error", "There was an error copying the data, could not discover contributed directory path.", "ok", "error", 1);
return;
}
if (force != 2) {
char contrib_src_path[BUFF_SIZE];
char contrib_dest_path[BUFF_SIZE];
int i = 0;
int optional = 0;
char* contrib_directories[] = CONTRIB_DIRECTORIES;
while (contrib_directories[i] != NULL && contrib_directories[i + 1] != NULL) {
if (!strcmp(contrib_directories[i], ":optional:")) {
i += 1;
optional = 1;
} else {
if (contrib_directories[i][0] != '/') {
// absolute Unix paths are not appended to the source path
strcpy(contrib_src_path, sourcepath);
strcat(contrib_src_path, SLASH);
strcat(contrib_src_path, contrib_directories[i]);
} else {
strcpy(contrib_src_path, contrib_directories[i]);
}
if (stat(contrib_src_path, &st) != 0) {
// contrib dir not found, abort!
if (!optional) {
tinyfd_messageBox(contrib_directories[i], "There was an error copying the data, could not discover contributed directory path.", "ok", "error", 1);
return;
}
} else {
strcpy(contrib_dest_path, destination);
strcat(contrib_dest_path, SLASH);
strcat(contrib_dest_path, contrib_directories[i + 1]);
copy_dir(contrib_src_path, contrib_dest_path);
}
i += 2;
}
}
}
char cmdbuf[4096] = {'\0'};
#ifdef USE_MAC
strcat(cmdbuf, "osascript -e \"tell application \\\"Terminal\\\"\n"
" set w to do script \\\"");
#elif defined(WIN32)
strcat(cmdbuf, "/C \"");
#else
if (!isatty(1)) {
strcat(cmdbuf, "xterm -e bash -c ");
strcat(cmdbuf, " \"");
}
#endif
strcat(cmdbuf, extractor_tool);
strcat(cmdbuf, " " QUOTE);
strcat(cmdbuf, srcfolder);
strcat(cmdbuf, QUOTE " " QUOTE);
strcat(cmdbuf, destination);
strcat(cmdbuf, QUOTE);
#ifdef USE_MAC
strcat(cmdbuf, "; exit\\\"\n"
" repeat\n"
" delay 1\n"
" if not busy of w then exit repeat\n"
" end repeat\n"
"end tell\"");
#elif defined(WIN32)
strcat(cmdbuf, "\"");
#else
if (!isatty(1)) {
strcat(cmdbuf, "; echo 'Press RETURN to continue...'; read\"");
}
#endif
#ifdef WIN32
DWORD exitcode = 0;
SHELLEXECUTEINFO ShExecInfo = { 0 };
char* toolpath = strdup(extractor_tool);
if (PathRemoveFileSpec(toolpath)) {
// remove the leading quote
if (toolpath[0] == '"') memmove(toolpath, toolpath + 1, strlen(toolpath) + 1);
} else {
// nothing was removed, use current dir
toolpath = NULL;
}
ShExecInfo.cbSize = sizeof(SHELLEXECUTEINFO);
ShExecInfo.fMask = SEE_MASK_NOCLOSEPROCESS;
ShExecInfo.hwnd = NULL;
ShExecInfo.lpVerb = NULL;
ShExecInfo.lpFile = "cmd";
ShExecInfo.lpParameters = cmdbuf;
ShExecInfo.lpDirectory = toolpath;
ShExecInfo.nShow = SW_SHOW;
ShExecInfo.hInstApp = NULL;
ShellExecuteEx(&ShExecInfo);
WaitForSingleObject(ShExecInfo.hProcess, INFINITE);
GetExitCodeProcess(ShExecInfo.hProcess, &exitcode);
#else
int exitcode = 0;
exitcode = system(cmdbuf);
#endif
if (exitcode != 0) {
char* extractortext = (char*)calloc(sizeof(char), strlen(cmdbuf) + 1024);
sprintf(extractortext, "The following command was used to extract the data\n%s", cmdbuf);
tinyfd_messageBox("Extraction failed!", extractortext, "ok", "error", 1);
unlink(destination);
} else if (GAME_SHOULD_EXTRACT_AGAIN) {
ExtractData(extractor_tool, destination, scripts_path, 2);
}
}
int main(int argc, char * argv[]) {
#ifndef WIN32
if ( ! XOpenDisplay(NULL) ) {
ConsoleMode = 1;
}
if ( ConsoleMode ) {
if ( getuid() != 0 ) {
error(TITLE, CONSOLE_MODE_NOT_ROOT);
}
} else {
#ifndef NOGTK
gtk_init(&argc, &argv);
#endif
}
#endif
struct stat st;
int argccpy = argc;
char data_path[BUFF_SIZE];
char scripts_path[BUFF_SIZE];
char stratagus_bin[BUFF_SIZE];
char title_path[BUFF_SIZE];
char extractor_path[BUFF_SIZE];
strcat(extractor_path, EXTRACTOR_TOOL);
if (!detectPresence(extractor_path)) {
// The extractor is in the same dir as we are
if (strchr(argv[0], SLASH[0])) {
strcpy(extractor_path, argv[0]);
parentdir(extractor_path);
strcat(extractor_path, SLASH EXTRACTOR_TOOL);
#ifdef WIN32
if (!strstr(extractor_path, ".exe")) {
strcat(extractor_path, ".exe");
}
#endif
// Once we have the path, we quote it by moving the memory one byte to the
// right, and surrounding it with the quote character and finishing null
// bytes. Then we add the arguments.
extractor_path[strlen(extractor_path) + 1] = '\0';
memmove(extractor_path + 1, extractor_path, strlen(extractor_path));
extractor_path[0] = QUOTE[0];
extractor_path[strlen(extractor_path) + 1] = '\0';
extractor_path[strlen(extractor_path)] = QUOTE[0];
}
}
strcat(extractor_path, " " EXTRACTOR_ARGS);
#ifdef WIN32
char executable_path[BUFF_SIZE];
@ -264,41 +480,102 @@ int main(int argc, char * argv[]) {
if (data_path_length != 0 && data_path[data_path_length - 1] == '\\') {
data_path[data_path_length - 1] = '\0';
}
sprintf(scripts_path, "\"%s\"", data_path);
char stratagus_path[BUFF_SIZE];
DWORD stratagus_path_size = sizeof(stratagus_path);
memset(stratagus_path, 0, stratagus_path_size);
HKEY key;
if ( RegOpenKeyEx(HKEY_LOCAL_MACHINE, REGKEY, 0, KEY_QUERY_VALUE, &key) == ERROR_SUCCESS ) {
if ( RegQueryValueEx(key, "InstallLocation", NULL, NULL, (LPBYTE) stratagus_path, &stratagus_path_size) == ERROR_SUCCESS ) {
if ( stratagus_path_size == 0 || strlen(stratagus_path) == 0 ) {
error(TITLE, STRATAGUS_NOT_FOUND);
// Try to use stratagus.exe from data (install) directory first
sprintf(stratagus_bin, "%s\\stratagus.exe", data_path);
if (stat(stratagus_bin, &st) != 0) {
// If no local stratagus.exe is present, look for a globally installed version
DWORD stratagus_path_size = sizeof(stratagus_path);
memset(stratagus_path, 0, stratagus_path_size);
HKEY key;
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, REGKEY, 0, KEY_QUERY_VALUE, &key) == ERROR_SUCCESS) {
if (RegQueryValueEx(key, "InstallLocation", NULL, NULL, (LPBYTE)stratagus_path, &stratagus_path_size) == ERROR_SUCCESS) {
if (stratagus_path_size == 0 || strlen(stratagus_path) == 0) {
error(TITLE, STRATAGUS_NOT_FOUND);
}
}
RegCloseKey(key);
}
RegCloseKey(key);
}
if ( chdir(stratagus_path) != 0 ) {
error(TITLE, STRATAGUS_NOT_FOUND);
if (chdir(stratagus_path) != 0) {
error(TITLE, STRATAGUS_NOT_FOUND);
}
sprintf(stratagus_bin, "%s\\stratagus.exe", stratagus_path);
}
sprintf(scripts_path, "\"%s\"", data_path);
sprintf(stratagus_bin, "%s\\stratagus.exe", stratagus_path);
#ifdef DATA_PATH
// usually this isn't defined for windows builds. if it is, use it
strcpy(data_path, DATA_PATH);
#endif
#else
strcpy(data_path, DATA_PATH);
strcpy(scripts_path, SCRIPTS_PATH);
strcpy(stratagus_bin, STRATAGUS_BIN);
#endif
if (argc > 1) {
if (!strcmp(argv[1], "--extract")) {
// Force extraction and exit
SetUserDataPath(data_path);
ExtractData(extractor_path, data_path, scripts_path, 1);
return 0;
}
if (!strcmp(argv[1], "--extract-no-gui")) {
// Force extraction without ui and exit
tinyfd_forceConsole = 1;
SetUserDataPath(data_path);
ExtractData(extractor_path, data_path, scripts_path, 1);
return 0;
}
}
if ( stat(stratagus_bin, &st) != 0 ) {
error(TITLE, STRATAGUS_NOT_FOUND);
}
if ( stat(data_path, &st) != 0 ) {
error(TITLE, DATA_NOT_EXTRACTED);
#ifdef WIN32
_fullpath(stratagus_bin, argv[0], BUFF_SIZE);
PathRemoveFileSpec(stratagus_bin);
strcat(extractor_path, "\\stratagus.exe");
if (stat(stratagus_bin, &st) != 0) {
error(TITLE, STRATAGUS_NOT_FOUND);
}
#else
if (!detectPresence(stratagus_bin)) {
realpath(argv[0], stratagus_bin);
parentdir(stratagus_bin);
if (strlen(stratagus_bin) > 0) {
strcat(stratagus_bin, "/stratagus");
} else {
strcat(stratagus_bin, "./stratagus");
}
if ( stat(stratagus_bin, &st) != 0 ) {
error(TITLE, STRATAGUS_NOT_FOUND);
}
}
#endif
}
sprintf(title_path, TITLE_PNG, data_path);
if ( stat(title_path, &st) != 0 ) {
SetUserDataPath(data_path);
sprintf(title_path, TITLE_PNG, data_path);
if ( stat(title_path, &st) != 0 ) {
ExtractData(extractor_path, data_path, scripts_path);
}
if ( stat(title_path, &st) != 0 ) {
error(TITLE, DATA_NOT_EXTRACTED);
}
}
if (!check_version(extractor_path, data_path)) {
ExtractData(extractor_path, data_path, scripts_path);
}
#ifdef WIN32
int data_path_len = strlen(data_path);
_chdir(data_path);
for (int i = data_path_len - 1; i >= 0; --i) {
data_path[i + 1] = data_path[i];
@ -308,17 +585,6 @@ int main(int argc, char * argv[]) {
data_path[data_path_len + 2] = 0;
#endif
if ( stat(title_path, &st) != 0 ) {
error(TITLE, DATA_NOT_EXTRACTED);
}
#ifndef WIN32
if ( strcmp(data_path, scripts_path) != 0 ) {
if ( chdir(data_path) != 0 ) {
error(TITLE, DATA_NOT_EXTRACTED);
}
}
#endif
#ifdef _MSC_VER
char** stratagus_argv;
stratagus_argv = (char**) malloc((argc + 3) * sizeof (*stratagus_argv));
@ -339,7 +605,7 @@ int main(int argc, char * argv[]) {
#endif
stratagus_argv[1] = "-d";
stratagus_argv[2] = scripts_path;
stratagus_argv[2] = data_path;
for (int i = 3; i < argc + 2; ++i ) {
stratagus_argv[i] = argv[i - 2];
@ -347,20 +613,38 @@ int main(int argc, char * argv[]) {
stratagus_argv[argc + 2] = NULL;
#ifdef WIN32
AttachConsole(ATTACH_PARENT_PROCESS);
errno = 0;
int ret = spawnvp(_P_WAIT, stratagus_bin, stratagus_argv);
#ifdef _MSC_VER
free (stratagus_argv);
#endif
if ( errno == 0 ) {
return ret;
}
#else
execvp(stratagus_bin, stratagus_argv);
int ret = 0;
int childpid = fork();
if (childpid == 0) {
execvp(stratagus_bin, stratagus_argv);
if (strcmp(stratagus_bin, "stratagus") == 0) {
realpath(argv[0], stratagus_bin);
parentdir(stratagus_bin);
strcat(stratagus_bin, "/stratagus");
}
execvp(stratagus_bin, stratagus_argv);
exit(ENOENT);
} else if (childpid > 0) {
waitpid(childpid, &ret, 0);
} else {
ret = ENOENT;
}
#endif
error(TITLE, STRATAGUS_NOT_FOUND);
return 1;
if (ret == ENOENT) {
error(TITLE, STRATAGUS_NOT_FOUND);
} else if (ret != 0) {
char message[8096] = {'\0'};
snprintf(message, 8096,
"Stratagus failed to load game data. "
"If you just launched the game without any arguments, this may indicate a bug with the extraction process. "
"Please report this on https://github.com/Wargus/stratagus/issues/new, "
"and please give details, including: operating system, installation path, username, kind of source CD. "
"A possible solution is to remove the hidden folder %s).", data_path);
error(TITLE, message);
unlink(title_path);
unlink(data_path);
}
exit(ret);
}

View file

@ -0,0 +1,191 @@
/*
_________ __ __
/ _____// |_____________ _/ |______ ____ __ __ ______
\_____ \\ __\_ __ \__ \\ __\__ \ / ___\| | \/ ___/
/ \| | | | \// __ \| | / __ \_/ /_/ > | /\___ |
/_______ /|__| |__| (____ /__| (____ /\___ /|____//____ >
\/ \/ \//_____/ \/
______________________ ______________________
T H E W A R B E G I N S
Stratagus - A free fantasy real time strategy game engine
stratagus-game-launcher.h - Stratagus Game Launcher
Copyright (C) 2015-2016 The Stratagus Developers
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, see <http://www.gnu.org/licenses/>.
*/
void error(const char* title, const char* text);
void mkdir_p(const char* path);
void copy_dir(const char* source_folder, const char* target_folder);
#if __APPLE__
#define USE_MAC
#endif
#if ( defined (_MSC_VER) || defined (_WIN32) || defined (_WIN64) ) && ! defined (WIN32)
#define WIN32 1
#endif
#ifdef WIN32
#include <Shlwapi.h>
#pragma comment(lib, "comdlg32.lib")
#pragma comment(lib, "ole32.lib")
#pragma comment(lib, "Shlwapi.lib")
#include <direct.h>
//#define inline __inline
#define chdir _chdir
#define getcwd _getcwd
#define spawnvp _spawnvp
#define stat _stat
#define strdup _strdup
#define mkdir(f, m) _mkdir(f)
// PathRemoveFileSpec on a drive (e.g. when extracting from CD) will leave the trailing \... remove that
#define parentdir(x) PathRemoveFileSpec(x); if (x[strlen(x) - 1] == '\\') x[strlen(x) - 1] = '\0'
#define execvp _execvp
#define unlink(x) _unlink(x)
#else
#if defined(USE_MAC)
#define parentdir(x) strcpy(x, dirname(x))
#else
#define parentdir(x) dirname(x)
#endif
#endif
#ifdef WIN32
#ifndef WINVER
#define WINVER 0x0501
#endif
#include <windows.h>
#include <wincon.h>
#include <process.h>
#define QUOTE "\""
#else
#include <ftw.h>
#include <unistd.h>
#include <libgen.h>
#include <sys/wait.h>
#define QUOTE "'"
#endif
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include "stratagus-tinyfiledialogs.h"
#define BUFF_SIZE 4096
char dst_root[BUFF_SIZE];
char src_root[BUFF_SIZE];
void error(const char* title, const char* text) {
tinyfd_messageBox(title, text, "ok", "error", 1);
exit(-1);
}
void mkdir_p(const char* path) {
int error = 0;
printf("mkdir %s\n", path);
if (mkdir(path, 0777)) {
error = errno;
if (error == ENOENT) {
char *sep = strrchr((char*)path, '/');
if (sep == NULL) {
sep = strrchr((char*)path, SLASH[0]);
}
if (sep != NULL) {
*sep = '\0';
if (strlen(path) > 0) {
// will be null if the we reach the first /
mkdir_p(path);
}
*sep = '/';
}
} else if (error != EEXIST) {
if (mkdir(path, 0777)) {
printf("Error while trying to create '%s'\n", path);
}
}
}
}
#ifdef WIN32
#include <wchar.h>
#include <string>
void copy_dir(const char* source_folder, const char* target_folder)
{
wchar_t *wsource_folder = new wchar_t[strlen(source_folder) + 1];
size_t convertedChars = 0;
mbstowcs_s(&convertedChars, wsource_folder, strlen(source_folder) + 1, source_folder, _TRUNCATE);
wchar_t *wtarget_folder = new wchar_t[strlen(target_folder) + 1];
mbstowcs_s(&convertedChars, wtarget_folder, strlen(target_folder) + 1, target_folder, _TRUNCATE);
WCHAR sf[MAX_PATH + 1];
WCHAR tf[MAX_PATH + 1];
wcscpy_s(sf, MAX_PATH, wsource_folder);
char* ptarget = strdup(target_folder);
parentdir(ptarget);
mkdir_p(ptarget);
wcscpy_s(tf, MAX_PATH, wtarget_folder);
sf[lstrlenW(sf) + 1] = 0;
tf[lstrlenW(tf) + 1] = 0;
SHFILEOPSTRUCTW s = { 0 };
s.wFunc = FO_COPY;
s.pTo = tf;
s.pFrom = sf;
s.fFlags = FOF_SILENT | FOF_NOCONFIRMMKDIR | FOF_NOCONFIRMATION | FOF_NOERRORUI | FOF_NO_UI;
SHFileOperationW(&s);
}
#else
int copy_file(const char* src_path, const struct stat* sb, int typeflag) {
char dst_path[BUFF_SIZE];
printf("%s to %s\n", src_path, dst_root);
strcpy(dst_path, dst_root);
strcat(dst_path, src_path + strlen(src_root));
switch(typeflag) {
case FTW_D:
mkdir_p(dst_path);
break;
case FTW_F:
mkdir_p(parentdir(strdup(dst_path)));
FILE* in = fopen(src_path, "rb");
FILE* out = fopen(dst_path, "wb");
char buf[4096];
int c = 0;
if (!in) {
error("Extraction error", "Could not open source folder for reading.");
}
if (!out) {
error("Extraction error", "Could not open data folder for writing.");
}
while (c = fread(buf, sizeof(char), 4096, in)) {
fwrite(buf, sizeof(char), c, out);
}
fclose(in);
fclose(out);
break;
}
return 0;
}
void copy_dir(const char* src_path, const char* dst_path) {
printf("Copying %s to %s\n", src_path, dst_path);
mkdir_p(parentdir(strdup(dst_path)));
strcpy(dst_root, dst_path);
strcpy(src_root, src_path);
ftw(src_path, copy_file, 20);
}
#endif

File diff suppressed because it is too large Load diff

View file

@ -329,6 +329,7 @@ static void ParseCreateGame(Session *session, char *buf)
CreateGame(session, description, map, players, ip, port, password);
DebugPrint("%s created a game\n" _C_ session->UserData.Name);
DBAddGame(session->Game->ID, description, map, players_int);
Send(session, "CREATEGAME_OK\n");
}
@ -399,13 +400,15 @@ static void ParseJoinGame(Session *session, char *buf)
char *id;
char *password;
int ret;
unsigned long udphost;
int udpport;
if (Parse1or2Args(buf, &id, &password)) {
Send(session, "ERR_BADPARAMETER\n");
return;
}
ret = JoinGame(session, atoi(id), password);
ret = JoinGame(session, atoi(id), password, &udphost, &udpport);
if (ret == -1) {
Send(session, "ERR_ALREADYINGAME\n");
return;
@ -422,10 +425,16 @@ static void ParseJoinGame(Session *session, char *buf)
} else if (ret == -4) {
Send(session, "ERR_GAMEFULL\n");
return;
} else if (ret == -5) {
Send(session, "ERR_SERVERNOTREADY\n");
return;
}
DebugPrint("%s joined game %d\n" _C_ session->UserData.Name _C_ atoi(id));
Send(session, "JOINGAME_OK\n");
char* reply = (char*)calloc(sizeof(char), strlen("JOINGAME_OK 255.255.255.255 66535\n") + 1);
sprintf(reply, "JOINGAME_OK %d.%d.%d.%d %d\n", NIPQUAD(ntohl(UDPHost)), udpport);
DebugPrint("%s joined game %d with %s\n" _C_ session->UserData.Name _C_ atoi(id) _C_ reply);
Send(session, reply);
free(reply);
}
/**
@ -467,6 +476,30 @@ static void ParseEndGame(Session *session, char *buf)
Send(session, "ENDGAME_OK\n");
}
/**
** Parse STATS
*/
static void ParseStats(Session *session, char *buf)
{
char *result;
int start_time = 0;
char resultbuf[20] = {'\0'};
while (*buf == ' ') ++buf;
if (*buf) {
Parse1Arg(buf, &result);
start_time = atoi(result);
}
DebugPrint("%s requested stats\n" _C_ session->UserData.Name);
char* reply = (char*)calloc(sizeof(char), strlen("GAMES SINCE 12345678901234567890: 12345678901234567890\n") + 1);
DBStats(resultbuf, start_time);
sprintf(reply, "GAMES SINCE %d: %s\n", start_time, resultbuf);
Send(session, reply);
Send(session, "STATS_OK\n");
}
/**
** Parse MSG
*/
@ -490,19 +523,19 @@ static void ParseBuffer(Session *session)
buf = session->Buffer;
if (!strncmp(buf, "PING", 4)) {
ParsePing(session);
} else if (!session->UserData.LoggedIn) {
if (!strncmp(buf, "USER ", 5)) {
ParseUser(session, buf + 5);
} else if (!strncmp(buf, "REGISTER ", 9)) {
ParseRegister(session, buf + 9);
} else {
fprintf(stderr, "Unknown command: %s\n", session->Buffer);
Send(session, "ERR_BADCOMMAND\n");
}
} else {
if (!strncmp(buf, "USER ", 5) || !strncmp(buf, "REGISTER ", 9)) {
Send(session, "ERR_ALREADYLOGGEDIN\n");
} else if (!strncmp(buf, "CREATEGAME ", 11)) {
if (!session->UserData.LoggedIn) {
if (!strncmp(buf, "USER ", 5)) {
ParseUser(session, buf + 5);
} else if (!strncmp(buf, "REGISTER ", 9)) {
ParseRegister(session, buf + 9);
}
} else {
if (!strncmp(buf, "USER ", 5) || !strncmp(buf, "REGISTER ", 9)) {
Send(session, "ERR_ALREADYLOGGEDIN\n");
}
}
if (!strncmp(buf, "CREATEGAME ", 11)) {
ParseCreateGame(session, buf + 11);
} else if (!strcmp(buf, "CANCELGAME") || !strncmp(buf, "CANCELGAME ", 11)) {
ParseCancelGame(session, buf + 10);
@ -516,6 +549,8 @@ static void ParseBuffer(Session *session)
ParsePartGame(session, buf + 8);
} else if (!strncmp(buf, "ENDGAME ", 8)) {
ParseEndGame(session, buf + 8);
} else if (!strncmp(buf, "STATS ", 6)) {
ParseStats(session, buf + 6);
} else if (!strncmp(buf, "MSG ", 4)) {
ParseMsg(session, buf + 4);
} else {
@ -556,6 +591,26 @@ int UpdateParser(void)
}
}
if (strlen(UDPBuffer)) {
// If this is a server, we'll note its external data. When clients join,
// they'll receive this as part of the TCP response that they
// successfully joined. This is a simplification of the full UDP hole
// punching algorithm, which unneccessarily might go through the NAT
// even for clients inside the same NAT. This will also not work if in
// that case the NAT does not support hairpin translation. But we'll see
// how common that is...
char ip[128] = {'\0'};
char port[128] = {'\0'};
sscanf(UDPBuffer, "%s %s", (char*)&ip, (char*)&port);
DebugPrint("Filling in UDP info for %s:%s\n" _C_ ip _C_ port);
if (FillinUDPInfo(UDPHost, UDPPort, ip, port)) {
fprintf(stderr, "Error filling in UDP info for %s:%s with %d.%d.%d.%d:%d",
ip, port, NIPQUAD(ntohl(UDPHost)), UDPPort);
}
UDPBuffer[0] = '\0';
}
return 0;
}

View file

@ -59,10 +59,11 @@ static sqlite3 *DB;
#define SQLCreateGamesTable \
"CREATE TABLE games (" \
"date INTEGER," \
"id INTEGER PRIMARY KEY," \
"date INTEGER," \
"gamename TEXT," \
"map_id INTEGER" \
"mapname TEXT," \
"slots INTEGER" \
");"
#define SQLCreateGameDataTable \
@ -112,8 +113,10 @@ static sqlite3 *DB;
static int DBMaxIDCallback(void *password, int argc, char **argv, char **colname)
{
Assert(argc == 1);
if (argv[0])
GameID = atoi(argv[0]);
if (argv[0]) {
GameID = atoi(argv[0]) + 1;
}
fprintf(stderr, "Current max game id is %d\n", GameID);
return 0;
}
@ -141,15 +144,13 @@ int DBInit(void)
return -1;
}
if (!doinit) {
return 0;
}
errmsg = NULL;
if (sqlite3_exec(DB, SQLCreateTables, NULL, NULL, &errmsg) != SQLITE_OK) {
fprintf(stderr, "SQL error: %s\n", errmsg);
sqlite3_free(errmsg);
return -1;
if (doinit) {
errmsg = NULL;
if (sqlite3_exec(DB, SQLCreateTables, NULL, NULL, &errmsg) != SQLITE_OK) {
fprintf(stderr, "SQL error: %s\n", errmsg);
sqlite3_free(errmsg);
return -1;
}
}
errmsg = NULL;
@ -259,3 +260,44 @@ int DBUpdateLoginDate(char *username)
}
return 0;
}
int DBAddGame(int id, char *description, char *mapname, int numplayers)
{
char buf[1024];
int t;
char *errmsg;
t = (int)time(0);
sprintf(buf, "INSERT INTO games VALUES(%d, %d, '%s', '%s', %d);",
id, t, description, mapname, numplayers);
if (sqlite3_exec(DB, buf, NULL, NULL, &errmsg) != SQLITE_OK) {
fprintf(stderr, "SQL error: %s\n", errmsg);
sqlite3_free(errmsg);
return -1;
}
return 0;
}
static int DBStatsCallback(void *resultbuf, int argc, char **argv, char **colname)
{
Assert(argc == 1);
strcpy((char *)resultbuf, argv[0]);
return 0;
}
int DBStats(char* resultbuf, int start_time)
{
char buf[1024];
int t;
char *errmsg;
t = (int)time(0);
sprintf(buf, "SELECT COUNT(id) FROM games WHERE date > %d;", start_time);
if (sqlite3_exec(DB, buf, DBStatsCallback, resultbuf, &errmsg) != SQLITE_OK) {
fprintf(stderr, "SQL error: %s\n", errmsg);
sqlite3_free(errmsg);
return -1;
}
return 0;
}

View file

@ -41,6 +41,8 @@ extern void DBQuit(void);
extern int DBFindUser(char *username, char *password);
extern int DBAddUser(char *username, char *password);
extern int DBUpdateLoginDate(char *username);
extern int DBAddGame(int id, char *description, char *mapname, int numplayers);
extern int DBStats(char *results, int resultlen);
//@}

View file

@ -64,6 +64,8 @@ void CreateGame(Session *session, char *description, char *map,
strcpy(game->IP, ip);
strcpy(game->Port, port);
game->UDPHost = 0;
game->UDPPort = 0;
strcpy(game->Description, description);
strcpy(game->Map, map);
game->MaxSlots = atoi(players);
@ -89,6 +91,9 @@ void CreateGame(Session *session, char *description, char *map,
game->Prev = NULL;
Games = game;
if (session->Game) {
PartGame(session);
}
session->Game = game;
}
@ -120,6 +125,7 @@ int CancelGame(Session *session)
game->Sessions[i]->Game = NULL;
}
session->Game = NULL;
delete game;
return 0;
}
@ -140,12 +146,12 @@ int StartGame(Session *session)
/**
** Join a game
*/
int JoinGame(Session *session, int id, char *password)
int JoinGame(Session *session, int id, char *password, unsigned long *host, int *port)
{
GameData *game;
if (session->Game) {
return -1; // Already in a game
PartGame(session);
}
game = Games;
@ -167,6 +173,12 @@ int JoinGame(Session *session, int id, char *password)
if (!game->OpenSlots) {
return -4; // Game full
}
if (!(game->UDPHost && game->UDPPort)) {
return -5; // Server not ready
}
*host = game->UDPHost;
*port = game->UDPPort;
game->Sessions[game->NumSessions++] = session;
session->Game = game;
@ -213,8 +225,9 @@ int PartGame(Session *session)
static int MatchGameType(Session *session, GameData *game)
{
return (!*game->GameName || !strcmp(session->UserData.GameName, game->GameName)) &&
(!*game->Version || !strcmp(session->UserData.Version, game->Version));
return (!session->UserData.LoggedIn) ||
((!*game->GameName ||!strcmp(session->UserData.GameName, game->GameName)) &&
(!*game->Version || !strcmp(session->UserData.Version, game->Version)));
}
/**
@ -236,3 +249,17 @@ void ListGames(Session *session)
game = game->Next;
}
}
int FillinUDPInfo(unsigned long udphost, int udpport, char* ip, char* port) {
GameData *game;
for (game = Games; game; game = Games->Next) {
if (!strcmp(game->IP, ip) && !strcmp(game->Port, port)) {
if (!game->UDPHost && !game->UDPPort) {
game->UDPHost = udphost;
game->UDPPort = udpport;
return 0;
}
}
}
return -1;
}

View file

@ -65,6 +65,9 @@ public:
int ID;
int Started;
unsigned long UDPHost;
int UDPPort;
GameData *Next;
GameData *Prev;
};
@ -79,9 +82,10 @@ extern void CreateGame(Session *session, char *description, char *map,
char *players, char *ip, char *port, char *password);
extern int CancelGame(Session *session);
extern int StartGame(Session *session);
extern int JoinGame(Session *session, int id, char *password);
extern int JoinGame(Session *session, int id, char *password, unsigned long *host, int *port);
extern int PartGame(Session *session);
extern void ListGames(Session *session);
extern int FillinUDPInfo(unsigned long udphost, int udpport, char* ip, char* port);
//@}

View file

@ -223,7 +223,7 @@ int main(int argc, char **argv)
//
// Parse the command line.
//
while ((i = getopt(argc, argv, "aP:pm:i:d:")) != -1) {
while ((i = getopt(argc, argv, "aP:pm:i:d:h")) != -1) {
switch (i) {
case 'a':
EnableAssert = true;
@ -250,6 +250,16 @@ int main(int argc, char **argv)
printf("Missing argument for %c\n", optopt);
exit(0);
break;
case 'h':
printf("Arguments:\n"
"-a\tEnable asserts\n"
"-P\tSet port\n"
"-p\tEnable debug print\n"
"-m\tMax connections\n"
"-i\tIdle timeout\n"
"-d\tPolling delay\n");
exit(0);
break;
case '?':
printf("Unrecognized option: -%c\n", optopt);
break;

View file

@ -42,6 +42,7 @@
#endif
#include "stratagus.h"
#include "games.h"
#include "netdriver.h"
#include "net_lowlevel.h"
@ -92,9 +93,13 @@
----------------------------------------------------------------------------*/
static Socket MasterSocket;
static Socket HolePunchSocket;
SessionPool *Pool;
ServerStruct Server;
char UDPBuffer[16 /* GameData->IP */ + 6 /* GameData->Port */ + 1] = {'\0'};
unsigned long UDPHost = 0;
int UDPPort = 0;
/*----------------------------------------------------------------------------
-- Functions
@ -120,6 +125,7 @@ void Send(Session *session, const char *msg)
*/
int ServerInit(int port)
{
int code = 0;
Pool = NULL;
if (NetInit() == -1) {
@ -127,35 +133,42 @@ int ServerInit(int port)
}
if ((MasterSocket = NetOpenTCP(NULL, port)) == (Socket)-1) {
fprintf(stderr, "NetOpenTCP failed\n");
return -2;
fprintf(stderr, "NetOpenTCP failed\n");
return -2;
}
if ((HolePunchSocket = NetOpenUDP(INADDR_ANY, port)) == (Socket)-1) {
fprintf(stderr, "NetOpenUDP failed\n");
return -2;
}
if (NetSetNonBlocking(MasterSocket) == -1) {
fprintf(stderr, "NetSetNonBlocking failed\n");
NetCloseTCP(MasterSocket);
NetExit();
return -3;
fprintf(stderr, "NetSetNonBlocking TCP failed\n");
code = -3;
goto error;
}
if (NetSetNonBlocking(HolePunchSocket) == -1) {
fprintf(stderr, "NetSetNonBlocking UDP failed\n");
code = -3;
goto error;
}
if (NetListenTCP(MasterSocket) == -1) {
fprintf(stderr, "NetListenTCP failed\n");
NetCloseTCP(MasterSocket);
NetExit();
return -4;
fprintf(stderr, "NetListenTCP failed\n");
code = -4;
goto error;
}
if (!(Pool = new SessionPool)) {
fprintf(stderr, "Out of memory\n");
NetCloseTCP(MasterSocket);
NetExit();
return -5;
code = -5;
goto error;
}
if (!(Pool->Sockets = new SocketSet)) {
NetCloseTCP(MasterSocket);
NetExit();
return -6;
code = -6;
goto error;
}
Pool->First = NULL;
@ -163,6 +176,12 @@ int ServerInit(int port)
Pool->Count = 0;
return 0;
error:
NetCloseTCP(MasterSocket);
NetCloseUDP(HolePunchSocket);
NetExit();
return code;
}
/**
@ -210,6 +229,7 @@ static int KillSession(Session *session)
NetCloseTCP(session->Sock);
Pool->Sockets->DelSocket(session->Sock);
UNLINK(Pool->First, session, Pool->Last, Pool->Count);
PartGame(session);
delete session;
return 0;
}
@ -248,6 +268,10 @@ static void AcceptConnections()
LINK(Pool->First, new_session, Pool->Last, Pool->Count);
Pool->Sockets->AddSocket(new_socket);
}
if (NetSocketReady(HolePunchSocket, 0)) {
NetRecvUDP(HolePunchSocket, UDPBuffer, sizeof(UDPBuffer), &UDPHost, &UDPPort);
DebugPrint("New UDP %s (%d %d)\n" _C_ UDPBuffer _C_ UDPHost _C_ UDPPort);
}
}
/**

View file

@ -133,8 +133,11 @@ public:
SocketSet *Sockets;
};
/// external reference to session tracking.
/// external reference to session tracking.
extern SessionPool *Pool;
extern char UDPBuffer[16 /* GameData->IP */ + 6 /* GameData->Port */ + 1];
extern unsigned long UDPHost;
extern int UDPPort;
/*----------------------------------------------------------------------------
-- Functions

View file

@ -103,6 +103,8 @@ void AnimateActionAttack(CUnit &unit, COrder &order)
order->SetGoal(&target);
order->Range = attacker.Stats->Variables[ATTACKRANGE_INDEX].Max;
order->MinRange = attacker.Type->MinAttackRange;
if (attacker.Type->BoolFlag[SKIRMISHER_INDEX].value)
order->SkirmishRange = order->Range;
return order;
}
@ -121,6 +123,9 @@ void AnimateActionAttack(CUnit &unit, COrder &order)
} else {
order->goalPos = dest;
}
if (attacker.Type->BoolFlag[SKIRMISHER_INDEX].value)
order->SkirmishRange = attacker.Stats->Variables[ATTACKRANGE_INDEX].Max;
return order;
}
@ -131,6 +136,8 @@ void AnimateActionAttack(CUnit &unit, COrder &order)
order->goalPos = dest;
order->Range = attacker.Stats->Variables[ATTACKRANGE_INDEX].Max;
order->MinRange = attacker.Type->MinAttackRange;
if (attacker.Type->BoolFlag[SKIRMISHER_INDEX].value)
order->SkirmishRange = order->Range;
return order;
}
@ -172,6 +179,8 @@ void AnimateActionAttack(CUnit &unit, COrder &order)
} else if (!strcmp(value, "range")) {
++j;
this->Range = LuaToNumber(l, -1, j + 1);
if (unit.Type->BoolFlag[SKIRMISHER_INDEX].value)
this->SkirmishRange = this->Range;
} else if (!strcmp(value, "tile")) {
++j;
lua_rawgeti(l, -1, j + 1);
@ -226,12 +235,15 @@ void AnimateActionAttack(CUnit &unit, COrder &order)
input.SetGoal(this->goalPos, tileSize);
}
input.SetMinRange(this->MinRange);
int distance = this->Range;
if (GameSettings.Inside) {
CheckObstaclesBetweenTiles(input.GetUnitPos(), this->HasGoal() ? this->GetGoal()->tilePos : this->goalPos, MapFieldRocks | MapFieldForest, &distance);
}
input.SetMaxRange(distance);
if (!this->SkirmishRange || Distance(input.GetUnitPos(), input.GetGoalPos()) < this->SkirmishRange)
input.SetMinRange(this->MinRange);
else
input.SetMinRange(std::max<int>(this->SkirmishRange, this->MinRange));
}
/* virtual */ void COrder_Attack::OnAnimationAttack(CUnit &unit)
@ -605,6 +617,11 @@ void COrder_Attack::AttackTarget(CUnit &unit)
unit.Waiting = 0;
}
if (this->State != ATTACK_TARGET && unit.CanStoreOrder(this) && AutoCast(unit)) {
this->Finished = true;
return;
}
switch (this->State) {
case 0: { // First entry
// did Order change ?

View file

@ -296,5 +296,18 @@ static void EnterTransporter(CUnit &unit, COrder_Board &order)
}
}
/**
** Get goal position
*/
/* virtual */ const Vec2i COrder_Board::GetGoalPos() const
{
const Vec2i invalidPos(-1, -1);
if (goalPos != invalidPos) {
return goalPos;
}
if (this->HasGoal()) {
return this->GetGoal()->tilePos;
}
return invalidPos;
}
//@}

View file

@ -469,4 +469,19 @@ bool COrder_Build::BuildFromOutside(CUnit &unit) const
}
}
/**
** Get goal position
*/
/* virtual */ const Vec2i COrder_Build::GetGoalPos() const
{
const Vec2i invalidPos(-1, -1);
if (goalPos != invalidPos) {
return goalPos;
}
if (this->HasGoal()) {
return this->GetGoal()->tilePos;
}
return invalidPos;
}
//@}

View file

@ -37,6 +37,7 @@
#include "commands.h"
#include "construct.h"
#include "iolib.h"
#include "luacallback.h"
#include "map.h"
#include "player.h"
#include "script.h"
@ -208,6 +209,12 @@ static void Finish(COrder_Built &order, CUnit &unit)
AiWorkComplete(worker, unit);
}
if (unit.Type->OnReady) {
unit.Type->OnReady->pushPreamble();
unit.Type->OnReady->pushInteger(UnitNumber(unit));
unit.Type->OnReady->run();
}
// FIXME: Vladi: this is just a hack to test wall fixing,
// FIXME: also not sure if the right place...
// FIXME: Johns: hardcoded unit-type wall / more races!
@ -228,7 +235,7 @@ static void Finish(COrder_Built &order, CUnit &unit)
CorrectWallDirections(unit);
CorrectWallNeighBours(unit);
} else {
unit.Direction = (MyRand() >> 8) & 0xFF; // random heading
unit.Direction = (SyncRand() >> 8) & 0xFF; // random heading
}
UnitUpdateHeading(unit);
}
@ -267,6 +274,11 @@ static void Finish(COrder_Built &order, CUnit &unit)
const int maxProgress = type.Stats[unit.Player->Index].Costs[TimeCost] * 600;
// Check if we should make some random noise
if (unit.Frame == 0 && unit.Player == ThisPlayer && GameCycle % 150 == 0 && SyncRand(3) == 0) {
PlayUnitSound(unit, VoiceBuilding, true);
}
// Check if building ready. Note we can both build and repair.
if (!unit.Anim.Unbreakable && this->ProgressCounter >= maxProgress) {
Finish(*this, unit);

View file

@ -213,3 +213,18 @@ enum {
}
}
}
/**
** Get goal position
*/
/* virtual */ const Vec2i COrder_Defend::GetGoalPos() const
{
const Vec2i invalidPos(-1, -1);
if (goalPos != invalidPos) {
return goalPos;
}
if (this->HasGoal()) {
return this->GetGoal()->tilePos;
}
return invalidPos;
}

View file

@ -0,0 +1,219 @@
// _________ __ __
// / _____// |_____________ _/ |______ ____ __ __ ______
// \_____ \\ __\_ __ \__ \\ __\__ \ / ___\| | \/ ___/
// / \| | | | \// __ \| | / __ \_/ /_/ > | /\___ |
// /_______ /|__| |__| (____ /__| (____ /\___ /|____//____ >
// \/ \/ \//_____/ \/
// ______________________ ______________________
// T H E W A R B E G I N S
// Stratagus - A free fantasy real time strategy game engine
//
/**@name action_explore.cpp - The explore action. */
//
// (c) Copyright 1998-2019 by Lutz Sammer, Jimmy Salmon and Talas
//
// 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; only version 2 of the License.
//
// 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., 59 Temple Place - Suite 330, Boston, MA
// 02111-1307, USA.
//
//@{
/*----------------------------------------------------------------------------
-- Includes
----------------------------------------------------------------------------*/
#include "stratagus.h"
#include "action/action_explore.h"
#include "animation.h"
#include "iolib.h"
#include "map.h"
#include "pathfinder.h"
#include "script.h"
#include "tile.h"
#include "ui.h"
#include "unit.h"
#include "unittype.h"
#include "video.h"
/*----------------------------------------------------------------------------
-- Functions
----------------------------------------------------------------------------*/
static void GetExplorationTarget(const CUnit &unit, Vec2i &dest)
{
int triesLeft = Map.NoFogOfWar ? 0 : 3;
CMapField *field;
const CPlayer &player = *unit.Player;
dest.x = SyncRand(Map.Info.MapWidth - 1) + 1;
dest.y = SyncRand(Map.Info.MapHeight - 1) + 1;
while (triesLeft > 0) {
field = Map.Field(dest);
if (field && !field->playerInfo.IsExplored(player))
return; // unexplored, go here!
dest.x = SyncRand(Map.Info.MapWidth - 1) + 1;
dest.y = SyncRand(Map.Info.MapHeight - 1) + 1;
--triesLeft;
}
}
/* static */ COrder *COrder::NewActionExplore(const CUnit &unit)
{
Vec2i dest;
GetExplorationTarget(unit, dest);
Assert(Map.Info.IsPointOnMap(dest));
COrder_Explore *order = new COrder_Explore();
order->goalPos = dest;
return order;
}
/* virtual */ void COrder_Explore::Save(CFile &file, const CUnit &unit) const
{
file.printf("{\"action-explore\",");
if (this->Finished) {
file.printf(" \"finished\", ");
}
file.printf(" \"tile\", {%d, %d},", this->goalPos.x, this->goalPos.y);
file.printf(" \"range\", %d,", this->Range);
if (this->WaitingCycle != 0) {
file.printf(" \"waiting-cycle\", %d,", this->WaitingCycle);
}
file.printf("}");
}
/* virtual */ bool COrder_Explore::ParseSpecificData(lua_State *l, int &j, const char *value, const CUnit &unit)
{
if (!strcmp(value, "waiting-cycle")) {
++j;
this->WaitingCycle = LuaToNumber(l, -1, j + 1);
} else if (!strcmp(value, "range")) {
++j;
this->Range = LuaToNumber(l, -1, j + 1);
} else if (!strcmp(value, "tile")) {
++j;
lua_rawgeti(l, -1, j + 1);
CclGetPos(l, &this->goalPos.x , &this->goalPos.y);
lua_pop(l, 1);
} else {
return false;
}
return true;
}
/* virtual */ bool COrder_Explore::IsValid() const
{
return true;
}
/* virtual */ PixelPos COrder_Explore::Show(const CViewport &vp, const PixelPos &lastScreenPos) const
{
const PixelPos pos1 = vp.TilePosToScreen_Center(this->goalPos);
Video.DrawLineClip(ColorGreen, lastScreenPos, pos1);
Video.FillCircleClip(ColorBlue, pos1, 2);
return pos1;
}
/* virtual */ void COrder_Explore::UpdatePathFinderData(PathFinderInput &input)
{
input.SetMinRange(0);
input.SetMaxRange(this->Range);
const Vec2i tileSize(0, 0);
input.SetGoal(this->goalPos, tileSize);
}
/* virtual */ void COrder_Explore::Execute(CUnit &unit)
{
if (unit.Wait) {
if (!unit.Waiting) {
unit.Waiting = 1;
unit.WaitBackup = unit.Anim;
}
UnitShowAnimation(unit, unit.Type->Animations->Still);
unit.Wait--;
return;
}
if (unit.Waiting) {
unit.Anim = unit.WaitBackup;
unit.Waiting = 0;
}
switch (DoActionMove(unit)) {
case PF_FAILED:
this->WaitingCycle = 0;
break;
case PF_UNREACHABLE:
// Increase range and try again
this->WaitingCycle = 1;
this->Range++;
break;
case PF_REACHED:
{
this->WaitingCycle = 1;
this->Range = 0;
// pick a new place to explore
GetExplorationTarget(unit, this->goalPos);
}
break;
case PF_WAIT:
{
// Wait for a while then give up
this->WaitingCycle++;
if (this->WaitingCycle == 5) {
this->WaitingCycle = 0;
this->Range = 0;
// pick a new place to explore
GetExplorationTarget(unit, this->goalPos);
unit.pathFinderData->output.Cycles = 0; //moving counter
}
}
break;
default: // moving
this->WaitingCycle = 0;
break;
}
if (!unit.Anim.Unbreakable) {
if (AutoAttack(unit) || AutoRepair(unit) || AutoCast(unit)) {
this->Finished = true;
}
}
}
/**
** Get goal position
*/
/* virtual */ const Vec2i COrder_Explore::GetGoalPos() const
{
const Vec2i invalidPos(-1, -1);
if (goalPos != invalidPos) {
return goalPos;
}
if (this->HasGoal()) {
return this->GetGoal()->tilePos;
}
return invalidPos;
}
//@}

View file

@ -317,4 +317,19 @@ enum {
}
}
/**
** Get goal position
*/
/* virtual */ const Vec2i COrder_Follow::GetGoalPos() const
{
const Vec2i invalidPos(-1, -1);
if (goalPos != invalidPos) {
return goalPos;
}
if (this->HasGoal()) {
return this->GetGoal()->tilePos;
}
return invalidPos;
}
//@}

View file

@ -170,13 +170,22 @@ int DoActionMove(CUnit &unit)
}
if (unit.Type->UnitType == UnitTypeNaval) { // Boat (un)docking?
const CMapField &mf_cur = *Map.Field(unit.Offset);
const CMapField &mf_next = *Map.Field(unit.tilePos + posd);
bool foundCoast = false;
if (mf_cur.WaterOnMap() && mf_next.CoastOnMap()) {
PlayUnitSound(unit, VoiceDocking);
} else if (mf_cur.CoastOnMap() && mf_next.WaterOnMap()) {
PlayUnitSound(unit, VoiceDocking); // undocking
for (int i = 0; i < unit.Type->TileWidth && !foundCoast; i++) {
for (int j = 0; j < unit.Type->TileHeight && !foundCoast; j++) {
const Vec2i offset(i, j);
const CMapField &mf_next = *Map.Field(unit.tilePos + posd + offset);
const CMapField &mf_cur = *Map.Field(unit.tilePos + offset);
if (mf_cur.CoastOnMap() || mf_next.CoastOnMap()) {
foundCoast = true;
}
}
}
if (foundCoast) {
// Should play, even if unit already speaking
PlayUnitSound(unit, VoiceDocking, true);
}
}
Vec2i pos = unit.tilePos + posd;
@ -252,4 +261,19 @@ int DoActionMove(CUnit &unit)
}
}
/**
** Get goal position
*/
/* virtual */ const Vec2i COrder_Move::GetGoalPos() const
{
const Vec2i invalidPos(-1, -1);
if (goalPos != invalidPos) {
return goalPos;
}
if (this->HasGoal()) {
return this->GetGoal()->tilePos;
}
return invalidPos;
}
//@}

View file

@ -186,4 +186,19 @@
}
}
/**
** Get goal position
*/
/* virtual */ const Vec2i COrder_Patrol::GetGoalPos() const
{
const Vec2i invalidPos(-1, -1);
if (goalPos != invalidPos) {
return goalPos;
}
if (this->HasGoal()) {
return this->GetGoal()->tilePos;
}
return invalidPos;
}
//@}

View file

@ -319,5 +319,20 @@ static void AnimateActionRepair(CUnit &unit)
}
}
/**
** Get goal position
*/
/* virtual */ const Vec2i COrder_Repair::GetGoalPos() const
{
const Vec2i invalidPos(-1, -1);
if (goalPos != invalidPos) {
return goalPos;
}
if (this->HasGoal()) {
return this->GetGoal()->tilePos;
}
return invalidPos;
}
//@}

View file

@ -167,6 +167,15 @@ static bool FindNearestReachableTerrainType(int movemask, int resmask, int range
order->CurrentResource = harvester.CurrentResource;
order->DoneHarvesting = true;
if (harvester.CurrentResource) {
const ResourceInfo &resinfo = *harvester.Type->ResInfo[harvester.CurrentResource];
if (resinfo.TerrainHarvester && harvester.ResourcesHeld < resinfo.ResourceCapacity) {
// Need to finish harvesting first!
delete order;
return NewActionResource(harvester, harvester.tilePos);
}
}
if (depot == NULL) {
depot = FindDeposit(harvester, 1000, harvester.CurrentResource);
}
@ -345,6 +354,11 @@ COrder_Resource::~COrder_Resource()
}
if (this->IsGatheringStarted() && unit.ResourcesHeld > 0) {
// escape to Depot with what you have
const ResourceInfo &resinfo = *unit.Type->ResInfo[this->CurrentResource];
if (resinfo.TerrainHarvester && unit.ResourcesHeld < resinfo.ResourceCapacity) {
// We don't have anything yet.
return false;
}
this->DoneHarvesting = true;
return true;
}
@ -1355,4 +1369,19 @@ void COrder_Resource::Execute(CUnit &unit)
}
}
/**
** Get goal position
*/
/* virtual */ const Vec2i COrder_Resource::GetGoalPos() const
{
const Vec2i invalidPos(-1, -1);
if (goalPos != invalidPos) {
return goalPos;
}
if (this->HasGoal()) {
return this->GetGoal()->tilePos;
}
return invalidPos;
}
//@}

View file

@ -40,6 +40,7 @@
#include "ai.h"
#include "animation.h"
#include "iolib.h"
#include "luacallback.h"
#include "player.h"
#include "sound.h"
#include "translate.h"
@ -217,14 +218,19 @@ static void AnimateActionTrain(CUnit &unit)
newUnit->TTL = GameCycle + unit.Type->DecayRate * 6 * CYCLES_PER_SECOND;
}
/* Auto Group Add */
/* Remove this code from active status to allow buildings to be a group member
without trained units becoming part of the group. Reactivate to enable units
to be added to the group by uncommenting this code block
if (!unit.Player->AiEnabled && unit.GroupId) {
int num = 0;
while (!(unit.GroupId & (1 << num))) {
++num;
}
AddToGroup(&newUnit, 1, num);
}
} */
DropOutOnSide(*newUnit, LookingW, &unit);
player.Notify(NotifyGreen, newUnit->tilePos, _("New %s ready"), nType.Name.c_str());
@ -234,6 +240,11 @@ static void AnimateActionTrain(CUnit &unit)
if (unit.Player->AiEnabled) {
AiTrainingComplete(unit, *newUnit);
}
if (newUnit->Type->OnReady) {
newUnit->Type->OnReady->pushPreamble();
newUnit->Type->OnReady->pushInteger(UnitNumber(*newUnit));
newUnit->Type->OnReady->run();
}
if (unit.NewOrder && unit.NewOrder->HasGoal()
&& unit.NewOrder->GetGoal()->Destroyed) {

View file

@ -136,7 +136,7 @@ static int TransformUnitIntoType(CUnit &unit, const CUnitType &newtype)
unit.Variable[i].Enable = newstats.Variables[i].Enable;
} else {
unit.Variable[i].Value = newstats.Variables[i].Value;
unit.Variable[i].Max = unit.Variable[i].Value;
unit.Variable[i].Max = unit.Variable[i].Max;
unit.Variable[i].Enable = newstats.Variables[i].Enable;
}
}

View file

@ -46,6 +46,7 @@
#include "action/action_built.h"
#include "action/action_defend.h"
#include "action/action_die.h"
#include "action/action_explore.h"
#include "action/action_follow.h"
#include "action/action_move.h"
#include "action/action_patrol.h"
@ -200,6 +201,8 @@ void CclParseOrder(lua_State *l, CUnit &unit, COrderPtr *orderPtr)
*orderPtr = new COrder_Defend;
} else if (!strcmp(actiontype, "action-die")) {
*orderPtr = new COrder_Die;
} else if (!strcmp(actiontype, "action-explore")) {
*orderPtr = new COrder_Explore;
} else if (!strcmp(actiontype, "action-follow")) {
*orderPtr = new COrder_Follow;
} else if (!strcmp(actiontype, "action-move")) {
@ -397,6 +400,14 @@ static void HandleUnitAction(CUnit &unit)
SelectedUnitChanged();
}
}
if (unit.CurrentResource) {
const ResourceInfo &resinfo = *unit.Type->ResInfo[unit.CurrentResource];
if (resinfo.LoseResources && unit.Orders[0]->Action != UnitActionResource
&& (!resinfo.TerrainHarvester || unit.ResourcesHeld < resinfo.ResourceCapacity)) {
unit.CurrentResource = 0;
unit.ResourcesHeld = 0;
}
}
}
unit.Orders[0]->Execute(unit);
}

View file

@ -403,6 +403,19 @@ void CommandPatrolUnit(CUnit &unit, const Vec2i &pos, int flush)
if (IsUnitValidForNetwork(unit) == false) {
return ;
}
const Vec2i invalidPos(-1, -1);
Vec2i startPos = unit.tilePos;
COrderPtr *prevOrder = &unit.Orders.back();
if(*prevOrder != NULL) {
Vec2i prevGoalPos = (*prevOrder)->GetGoalPos();
if(prevGoalPos != invalidPos) {
startPos = prevGoalPos;
}
}
COrderPtr *order;
if (!unit.CanMove()) {
@ -414,7 +427,7 @@ void CommandPatrolUnit(CUnit &unit, const Vec2i &pos, int flush)
return;
}
}
*order = COrder::NewActionPatrol(unit.tilePos, pos);
*order = COrder::NewActionPatrol(startPos, pos);
ClearSavedAction(unit);
}
@ -499,6 +512,33 @@ void CommandBuildBuilding(CUnit &unit, const Vec2i &pos, CUnitType &what, int fl
ClearSavedAction(unit);
}
/**
** Send a unit exploring
**
** @param unit pointer to unit.
** @param flush if true, flush command queue.
*/
void CommandExplore(CUnit &unit, int flush)
{
if (IsUnitValidForNetwork(unit) == false) {
return ;
}
COrderPtr *order;
if (!unit.CanMove()) {
ClearNewAction(unit);
order = &unit.NewOrder;
} else {
order = GetNextOrder(unit, flush);
if (order == NULL) {
return;
}
}
*order = COrder::NewActionExplore(unit);
ClearSavedAction(unit);
}
/**
** Cancel the building construction, or kill a unit.
**

View file

@ -268,7 +268,7 @@ bool HallPlaceFinder::IsAUsableMine(const CUnit &mine) const
}
// Town hall may not be near but we may be using it, check
// for 2 buildings near it and assume it's been used
if (unit.Type->Building && !unit.Type->GivesResource == resource) {
if (unit.Type->Building && !(unit.Type->GivesResource == resource)) {
++buildings;
if (buildings == 2) {
return false;

View file

@ -57,6 +57,64 @@
#define AIATTACK_BUILDING 2
#define AIATTACK_AGRESSIVE 3
class EnemyUnitFinder
{
public:
EnemyUnitFinder(const CUnit &unit, CUnit **result_unit, int find_type) :
//Wyrmgus end
unit(unit),
movemask(unit.Type->MovementMask & ~(MapFieldLandUnit | MapFieldAirUnit | MapFieldSeaUnit)),
attackrange(unit.Stats->Variables[ATTACKRANGE_INDEX].Max),
find_type(find_type),
result_unit(result_unit)
{
*result_unit = NULL;
}
VisitResult Visit(TerrainTraversal &terrainTraversal, const Vec2i &pos, const Vec2i &from);
private:
const CUnit &unit;
unsigned int movemask;
const int attackrange;
const int find_type;
CUnit **result_unit;
};
VisitResult EnemyUnitFinder::Visit(TerrainTraversal &terrainTraversal, const Vec2i &pos, const Vec2i &from)
{
if (!CanMoveToMask(pos, movemask)) { // unreachable
return VisitResult_DeadEnd;
}
std::vector<CUnit *> table;
Vec2i minpos = pos - Vec2i(attackrange, attackrange);
Vec2i maxpos = pos + Vec2i(unit.Type->TileWidth - 1 + attackrange, unit.Type->TileHeight - 1 + attackrange);
Select(minpos, maxpos, table, HasNotSamePlayerAs(Players[PlayerNumNeutral]));
for (size_t i = 0; i != table.size(); ++i) {
CUnit *dest = table[i];
const CUnitType &dtype = *dest->Type;
if (
!unit.IsEnemy(*dest) // a friend or neutral
|| !CanTarget(*unit.Type, dtype)
) {
continue;
}
// Don't attack invulnerable units
if (dtype.BoolFlag[INDESTRUCTIBLE_INDEX].value || dest->Variable[UNHOLYARMOR_INDEX].Value) {
continue;
}
if ((find_type != AIATTACK_BUILDING || dtype.BoolFlag[BUILDING_INDEX].value) && (find_type != AIATTACK_AGRESSIVE || dest->IsAgressive())) {
*result_unit = dest;
return VisitResult_Finished;
} else if (*result_unit == NULL) { // if trying to search for buildings or aggressive units specifically, still put the first found unit (even if it doesn't fit those parameters) as the result unit, so that it can be returned if no unit with the specified parameters is found
*result_unit = dest;
}
}
return VisitResult_Ok;
}
template <const int FIND_TYPE>
class AiForceEnemyFinder
{
@ -84,21 +142,35 @@ public:
}
if (FIND_TYPE == AIATTACK_RANGE) {
*enemy = AttackUnitsInReactRange(*unit);
} else if (FIND_TYPE == AIATTACK_ALLMAP) {
*enemy = AttackUnitsInDistance(*unit, MaxMapWidth);
} else if (FIND_TYPE == AIATTACK_BUILDING) {
*enemy = AttackUnitsInDistance(*unit, MaxMapWidth, IsBuildingType());
Assert(!*enemy);
if (*enemy == NULL || !(*enemy)->Type->Building) {
*enemy = AttackUnitsInDistance(*unit, MaxMapWidth);
}
} else if (FIND_TYPE == AIATTACK_AGRESSIVE) {
*enemy = AttackUnitsInDistance(*unit, MaxMapWidth, IsAggresiveUnit());
Assert(!*enemy || (*enemy)->IsAgressive());
if (*enemy == NULL) {
*enemy = AttackUnitsInDistance(*unit, MaxMapWidth);
}
} else {
// Terrain traversal by Andrettin
TerrainTraversal terrainTraversal;
terrainTraversal.SetSize(Map.Info.MapWidth, Map.Info.MapHeight);
terrainTraversal.Init();
terrainTraversal.PushUnitPosAndNeighboor(*unit);
CUnit *result_unit = NULL;
EnemyUnitFinder enemyUnitFinder(*unit, &result_unit, FIND_TYPE);
terrainTraversal.Run(enemyUnitFinder);
*enemy = result_unit;
}
// Previous attack finding code before we added TerrainTraversal for all
// of these. Here for prosperity
// } else if (FIND_TYPE == AIATTACK_ALLMAP) {
// *enemy = AttackUnitsInDistance(*unit, MaxMapWidth);
// } else if (FIND_TYPE == AIATTACK_BUILDING) {
// *enemy = AttackUnitsInDistance(*unit, MaxMapWidth, IsBuildingType());
// Assert(!*enemy);
// if (*enemy == NULL || !(*enemy)->Type->Building) {
// *enemy = AttackUnitsInDistance(*unit, MaxMapWidth);
// }
// } else if (FIND_TYPE == AIATTACK_AGRESSIVE) {
// *enemy = AttackUnitsInDistance(*unit, MaxMapWidth, IsAggresiveUnit());
// Assert(!*enemy || (*enemy)->IsAgressive());
// if (*enemy == NULL) {
// *enemy = AttackUnitsInDistance(*unit, MaxMapWidth);
// }
// }
return *enemy == NULL;
}
private:
@ -1083,6 +1155,12 @@ void AiForceManager::Update()
}
}
}
if (force.Defending == false) {
// force is no longer defending
return;
}
// Find idle units and order them to defend
// Don't attack if there aren't our units near goal point
std::vector<CUnit *> nearGoal;

View file

@ -66,7 +66,7 @@
target->tilePos = resPos;
target->Place(resPos);
if (flags & SU_Summoned) {
target->Summoned = 1;
target->Summoned = GameCycle + 1;
}
if ((flags & SU_JoinToAIForce) && unit.Player->AiEnabled) {
int force = unit.Player->Ai->Force.GetForce(unit);

View file

@ -705,7 +705,6 @@ static void DrawTileIcons()
} else {
label.DrawCentered(x, y, "Filler");
}
y += 20;
int i = Editor.TileIndex;
Assert(Editor.TileIndex != -1);
@ -1301,7 +1300,7 @@ static void EditorCallbackKeyDown(unsigned key, unsigned keychar)
const char *ptr = strchr(UiGroupKeys.c_str(), key);
if (ptr) {
key = '0' + ptr - UiGroupKeys.c_str();
key = ((int)'0') + ptr - UiGroupKeys.c_str();
if (key > '9') {
key = SDLK_BACKQUOTE;
}
@ -1502,7 +1501,6 @@ static bool EditorCallbackMouse_EditUnitArea(const PixelPos &screenPos)
}
int i = Editor.UnitIndex;
by = UI.ButtonPanel.Y + 24;
for (size_t j = 0; j < UI.ButtonPanel.Buttons.size(); ++j) {
const int x = UI.ButtonPanel.Buttons[j].X;
const int y = UI.ButtonPanel.Buttons[j].Y;
@ -2080,4 +2078,4 @@ void StartEditor(const char *filename)
SetDefaultTextColors(nc, rc);
}
//@}
//@}

View file

@ -44,8 +44,8 @@
#include "unittype.h"
/// Callback for changed tile (with direction mask)
static void EditorChangeSurrounding(const Vec2i &pos, int d);
/// Callback for changed tile (with locked position)
static void EditorChangeSurrounding(const Vec2i &pos, const Vec2i &lock_pos);
/*----------------------------------------------------------------------------
-- Functions
@ -92,9 +92,9 @@ static unsigned QuadFromTile(const Vec2i &pos)
**
** @param pos map tile coordinate.
** @param tileIndex Tile type to edit.
** @param d Fix direction flag 8 up, 4 down, 2 left, 1 right.
** @param lock_pos map tile coordinate, that should not be changed in callback.
*/
void EditorChangeTile(const Vec2i &pos, int tileIndex, int d)
void EditorChangeTile(const Vec2i &pos, int tileIndex, const Vec2i &lock_pos)
{
Assert(Map.Info.IsPointOnMap(pos));
@ -125,16 +125,16 @@ void EditorChangeTile(const Vec2i &pos, int tileIndex, int d)
UI.Minimap.UpdateSeenXY(pos);
UI.Minimap.UpdateXY(pos);
EditorChangeSurrounding(pos, d);
EditorChangeSurrounding(pos, lock_pos);
}
/**
** Update surroundings for tile changes.
**
** @param pos Map tile position of change.
** @param d Fix direction flag 8 up, 4 down, 2 left, 1 right.
** @param lock_pos Original change position, that should not be altered.
*/
static void EditorChangeSurrounding(const Vec2i &pos, int d)
static void EditorChangeSurrounding(const Vec2i &pos, const Vec2i &lock_pos)
{
// Special case 1) Walls.
CMapField &mf = *Map.Field(pos);
@ -148,55 +148,61 @@ static void EditorChangeSurrounding(const Vec2i &pos, int d)
const unsigned int BH_QUAD_M = 0x0000FFFF; // Bottom half quad mask
const unsigned int LH_QUAD_M = 0xFF00FF00; // Left half quad mask
const unsigned int RH_QUAD_M = 0x00FF00FF; // Right half quad mask
const unsigned int DIR_UP = 8; // Go up allowed
const unsigned int DIR_DOWN = 4; // Go down allowed
const unsigned int DIR_LEFT = 2; // Go left allowed
const unsigned int DIR_RIGHT = 1; // Go right allowed
bool did_change = false; // if we changed any tiles
// How this works:
// first get the quad of the neighbouring tile,
// then check if the margin matches.
// Otherwise, call EditorChangeTile again.
if ((d & DIR_UP) && pos.y) {
if (pos.y) {
const Vec2i offset(0, -1);
// Insert into the bottom the new tile.
unsigned q2 = QuadFromTile(pos + offset);
unsigned u = (q2 & TH_QUAD_M) | ((quad >> 16) & BH_QUAD_M);
if (u != q2) {
if (u != q2 && (pos + offset) != lock_pos) {
did_change = true;
int tile = Map.Tileset->tileFromQuad(u & BH_QUAD_M, u);
EditorChangeTile(pos + offset, tile, d & ~DIR_DOWN);
EditorChangeTile(pos + offset, tile, lock_pos);
}
}
if ((d & DIR_DOWN) && pos.y < Map.Info.MapHeight - 1) {
if (pos.y < Map.Info.MapHeight - 1) {
const Vec2i offset(0, 1);
// Insert into the top the new tile.
unsigned q2 = QuadFromTile(pos + offset);
unsigned u = (q2 & BH_QUAD_M) | ((quad << 16) & TH_QUAD_M);
if (u != q2) {
if (u != q2 && (pos + offset) != lock_pos) {
did_change = true;
int tile = Map.Tileset->tileFromQuad(u & TH_QUAD_M, u);
EditorChangeTile(pos + offset, tile, d & ~DIR_UP);
EditorChangeTile(pos + offset, tile, lock_pos);
}
}
if ((d & DIR_LEFT) && pos.x) {
if (pos.x) {
const Vec2i offset(-1, 0);
// Insert into the left the new tile.
unsigned q2 = QuadFromTile(pos + offset);
unsigned u = (q2 & LH_QUAD_M) | ((quad >> 8) & RH_QUAD_M);
if (u != q2) {
if (u != q2 && (pos + offset) != lock_pos) {
did_change = true;
int tile = Map.Tileset->tileFromQuad(u & RH_QUAD_M, u);
EditorChangeTile(pos + offset, tile, d & ~DIR_RIGHT);
EditorChangeTile(pos + offset, tile, lock_pos);
}
}
if ((d & DIR_RIGHT) && pos.x < Map.Info.MapWidth - 1) {
if (pos.x < Map.Info.MapWidth - 1) {
const Vec2i offset(1, 0);
// Insert into the right the new tile.
unsigned q2 = QuadFromTile(pos + offset);
unsigned u = (q2 & RH_QUAD_M) | ((quad << 8) & LH_QUAD_M);
if (u != q2) {
if (u != q2 && (pos + offset) != lock_pos) {
did_change = true;
int tile = Map.Tileset->tileFromQuad(u & LH_QUAD_M, u);
EditorChangeTile(pos + offset, tile, d & ~DIR_LEFT);
EditorChangeTile(pos + offset, tile, lock_pos);
}
}
if (did_change) {
EditorChangeSurrounding(pos, lock_pos);
}
}
/**
@ -206,7 +212,7 @@ static void EditorChangeSurrounding(const Vec2i &pos, int d)
*/
void EditorTileChanged(const Vec2i &pos)
{
EditorChangeSurrounding(pos, 0x0F);
EditorChangeSurrounding(pos, pos);
}
/**
@ -235,7 +241,7 @@ static void TileFill(const Vec2i &pos, int tile, int size)
Vec2i itPos;
for (itPos.x = ipos.x; itPos.x <= apos.x; ++itPos.x) {
for (itPos.y = ipos.y; itPos.y <= apos.y; ++itPos.y) {
EditorChangeTile(itPos, tile, 15);
EditorChangeTile(itPos, tile, itPos);
}
}
}

View file

@ -625,6 +625,7 @@ int SaveStratagusMap(const std::string &mapName, CMap &map, int writeTerrain)
char *setupExtension = strstr(mapSetup, ".smp");
if (!setupExtension) {
fprintf(stderr, "%s: invalid Stratagus map filename\n", mapName.c_str());
return -1;
}
char previewName[PATH_MAX];
@ -878,6 +879,14 @@ void CreateGame(const std::string &filename, CMap *map)
InitPlayers();
if (IsNetworkGame()) {
// if is a network game, it is necessary to reinitialize the syncrand
// variables before beginning to load the map, due to random map
// generation
SyncHash = 0;
InitSyncRand();
}
if (Map.Info.Filename.empty() && !filename.empty()) {
const std::string path = LibraryFileName(filename.c_str());
@ -894,6 +903,15 @@ void CreateGame(const std::string &filename, CMap *map)
}
CreatePlayer(playertype);
}
if (!ThisPlayer && !IsNetworkGame()) {
// In demo or kiosk mode, pick first empty slot
for (int i = 0; i < PlayerMax; ++i) {
if (Players[i].Type == PlayerNobody) {
ThisPlayer = &Players[i];
break;
}
}
}
if (!filename.empty()) {
if (CurrentMapPath != filename) {
@ -1068,6 +1086,11 @@ void CreateGame(const std::string &filename, CMap *map)
} else {
unit.Colors = &unit.Player->UnitColors;
}
if (unit.Type->OnReady) {
unit.Type->OnReady->pushPreamble();
unit.Type->OnReady->pushInteger(UnitNumber(unit));
unit.Type->OnReady->run();
}
}
GameResult = GameNoResult;

View file

@ -850,6 +850,8 @@ static void DoNextReplay()
SendCommandUnload(*unit, pos, dunit, flags);
} else if (!strcmp(action, "build")) {
SendCommandBuildBuilding(*unit, pos, *UnitTypeByIdent(val), flags);
} else if (!strcmp(action, "explore")) {
SendCommandExplore(*unit, flags);
} else if (!strcmp(action, "dismiss")) {
SendCommandDismiss(*unit);
} else if (!strcmp(action, "resource-loc")) {

View file

@ -8,7 +8,7 @@
*
* Copyright (c) 2004, 2005 darkbits Js_./
* Per Larsson a.k.a finalman _RqZ{a<^_aa
* Olof Naessén a.k.a jansem/yakslem _asww7!uY`> )\a//
* Olof Naessén a.k.a jansem/yakslem _asww7!uY`> )\a//
* _Qhm`] _f "'c 1!5m
* Visit: http://guichan.darkbits.org )Qk<P ` _: :+' .' "{[
* .)j(] .d_/ '-( P . S
@ -78,7 +78,7 @@ namespace gcn
return 8;
}
void DefaultFont::drawString(Graphics* graphics, const std::string& text, int x, int y)
void DefaultFont::drawString(Graphics* graphics, const std::string& text, int x, int y, bool is_normal)
{
unsigned int i;

View file

@ -8,7 +8,7 @@
*
* Copyright (c) 2004, 2005 darkbits Js_./
* Per Larsson a.k.a finalman _RqZ{a<^_aa
* Olof Naessén a.k.a jansem/yakslem _asww7!uY`> )\a//
* Olof Naessén a.k.a jansem/yakslem _asww7!uY`> )\a//
* _Qhm`] _f "'c 1!5m
* Visit: http://guichan.darkbits.org )Qk<P ` _: :+' .' "{[
* .)j(] .d_/ '-( P . S
@ -129,8 +129,7 @@ namespace gcn
mFont = font;
}
void Graphics::drawText(const std::string& text, int x, int y,
unsigned int alignment)
void Graphics::drawText(const std::string& text, int x, int y, unsigned int alignment, bool is_normal)
{
if (mFont == NULL)
{
@ -141,13 +140,13 @@ namespace gcn
switch (alignment)
{
case LEFT:
mFont->drawString(this, text, x, y);
mFont->drawString(this, text, x, y, is_normal);
break;
case CENTER:
mFont->drawString(this, text, x - mFont->getWidth(text) / 2, y);
mFont->drawString(this, text, x - mFont->getWidth(text) / 2, y, is_normal);
break;
case RIGHT:
mFont->drawString(this, text, x - mFont->getWidth(text), y);
mFont->drawString(this, text, x - mFont->getWidth(text), y, is_normal);
break;
default:
assert(!"Unknown alignment.");

View file

@ -8,7 +8,7 @@
*
* Copyright (c) 2004, 2005 darkbits Js_./
* Per Larsson a.k.a finalman _RqZ{a<^_aa
* Olof Naessén a.k.a jansem/yakslem _asww7!uY`> )\a//
* Olof Naessén a.k.a jansem/yakslem _asww7!uY`> )\a//
* _Qhm`] _f "'c 1!5m
* Visit: http://guichan.darkbits.org )Qk<P ` _: :+' .' "{[
* .)j(] .d_/ '-( P . S
@ -208,7 +208,7 @@ namespace gcn
return mGlyph[glyph].width + mGlyphSpacing;
}
void ImageFont::drawString(Graphics* graphics, const std::string& text, int x, int y)
void ImageFont::drawString(Graphics* graphics, const std::string& text, int x, int y, bool is_normal)
{
unsigned int i;

View file

@ -8,7 +8,7 @@
*
* Copyright (c) 2004, 2005 darkbits Js_./
* Per Larsson a.k.a finalman _RqZ{a<^_aa
* Olof Naessén a.k.a jansem/yakslem _asww7!uY`> )\a//
* Olof Naessén a.k.a jansem/yakslem _asww7!uY`> )\a//
* _Qhm`] _f "'c 1!5m
* Visit: http://guichan.darkbits.org )Qk<P ` _: :+' .' "{[
* .)j(] .d_/ '-( P . S
@ -92,7 +92,7 @@ namespace gcn
// Inherited from Font
virtual void drawString(Graphics* graphics, const std::string& text, int x, int y);
virtual void drawString(Graphics* graphics, const std::string& text, int x, int y, bool is_normal);
virtual int getWidth(const std::string& text) const;

View file

@ -8,7 +8,7 @@
*
* Copyright (c) 2004, 2005 darkbits Js_./
* Per Larsson a.k.a finalman _RqZ{a<^_aa
* Olof Naessén a.k.a jansem/yakslem _asww7!uY`> )\a//
* Olof Naessén a.k.a jansem/yakslem _asww7!uY`> )\a//
* _Qhm`] _f "'c 1!5m
* Visit: http://guichan.darkbits.org )Qk<P ` _: :+' .' "{[
* .)j(] .d_/ '-( P . S
@ -113,7 +113,7 @@ namespace gcn
* @param x the x coordinate where to draw the string.
* @param y the y coordinate where to draw the string.
*/
virtual void drawString(Graphics* graphics, const std::string& text, int x, int y) = 0;
virtual void drawString(Graphics* graphics, const std::string& text, int x, int y, bool is_normal = true) = 0;
};
}

View file

@ -8,7 +8,7 @@
*
* Copyright (c) 2004, 2005 darkbits Js_./
* Per Larsson a.k.a finalman _RqZ{a<^_aa
* Olof Naessén a.k.a jansem/yakslem _asww7!uY`> )\a//
* Olof Naessén a.k.a jansem/yakslem _asww7!uY`> )\a//
* _Qhm`] _f "'c 1!5m
* Visit: http://guichan.darkbits.org )Qk<P ` _: :+' .' "{[
* .)j(] .d_/ '-( P . S
@ -247,8 +247,7 @@ namespace gcn
* @param alignment Graphics::LEFT, Graphics::CENTER or Graphics::RIGHT.
* @throws Exception when no Font is set.
*/
virtual void drawText(const std::string& text, int x, int y,
unsigned int alignment = LEFT);
virtual void drawText(const std::string& text, int x, int y, unsigned int alignment = LEFT, bool is_normal = true);
/**
* Alignments for text drawing.
*/

View file

@ -8,7 +8,7 @@
*
* Copyright (c) 2004, 2005 darkbits Js_./
* Per Larsson a.k.a finalman _RqZ{a<^_aa
* Olof Naessén a.k.a jansem/yakslem _asww7!uY`> )\a//
* Olof Naessén a.k.a jansem/yakslem _asww7!uY`> )\a//
* _Qhm`] _f "'c 1!5m
* Visit: http://guichan.darkbits.org )Qk<P ` _: :+' .' "{[
* .)j(] .d_/ '-( P . S
@ -185,7 +185,7 @@ pqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"); @endcode
virtual int getWidth(const std::string& text) const;
virtual void drawString(Graphics* graphics, const std::string& text, int x, int y);
virtual void drawString(Graphics* graphics, const std::string& text, int x, int y, bool is_normal = true);
virtual int getHeight() const;

View file

@ -171,7 +171,7 @@ namespace gcn
textX = getWidth() - 4;
break;
default:
textX = 0;
//textX = 0;
//throw GCN_EXCEPTION("Unknown alignment.");
assert(!"Unknown alignment.");
}

View file

@ -41,7 +41,7 @@ class COrder_Attack : public COrder
friend COrder *COrder::NewActionAttackGround(const CUnit &attacker, const Vec2i &dest);
public:
explicit COrder_Attack(bool ground) : COrder(ground ? UnitActionAttackGround : UnitActionAttack),
State(0), MinRange(0), Range(0), goalPos(-1, -1) {}
State(0), MinRange(0), Range(0), SkirmishRange(0), goalPos(-1, -1) {}
virtual COrder_Attack *Clone() const { return new COrder_Attack(*this); }
@ -68,6 +68,7 @@ private:
int State;
int MinRange;
int Range;
int SkirmishRange;
Vec2i goalPos;
};
//@}

View file

@ -50,6 +50,7 @@ public:
virtual void Execute(CUnit &unit);
virtual PixelPos Show(const CViewport &vp, const PixelPos &lastScreenPos) const;
virtual void UpdatePathFinderData(PathFinderInput &input);
virtual const Vec2i GetGoalPos() const;
private:
bool WaitForTransporter(CUnit &unit);
int MoveToTransporter(CUnit &unit);

View file

@ -58,7 +58,7 @@ public:
virtual void AiUnitKilled(CUnit &unit);
const CUnitType &GetUnitType() const { return *Type; }
virtual const Vec2i GetGoalPos() const { return goalPos; }
virtual const Vec2i GetGoalPos() const;
private:
bool MoveToLocation(CUnit &unit);

View file

@ -54,6 +54,7 @@ public:
virtual void Execute(CUnit &unit);
virtual PixelPos Show(const CViewport &vp, const PixelPos &lastScreenPos) const;
virtual void UpdatePathFinderData(PathFinderInput &input);
virtual const Vec2i GetGoalPos() const;
private:
unsigned int State;
int Range;

View file

@ -0,0 +1,66 @@
// _________ __ __
// / _____// |_____________ _/ |______ ____ __ __ ______
// \_____ \\ __\_ __ \__ \\ __\__ \ / ___\| | \/ ___/
// / \| | | | \// __ \| | / __ \_/ /_/ > | /\___ |
// /_______ /|__| |__| (____ /__| (____ /\___ /|____//____ >
// \/ \/ \//_____/ \/
// ______________________ ______________________
// T H E W A R B E G I N S
// Stratagus - A free fantasy real time strategy game engine
//
/**@name action_explore.h - The actions headerfile. */
//
// (c) Copyright 1998-2019 by Lutz Sammer, Jimmy Salmon and Talas
//
// 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; only version 2 of the License.
//
// 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., 59 Temple Place - Suite 330, Boston, MA
// 02111-1307, USA.
//
#ifndef __ACTION_EXPLORE_H__
#define __ACTION_EXPLORE_H__
#include "actions.h"
//@{
class COrder_Explore : public COrder
{
friend COrder *COrder::NewActionExplore(const CUnit &unit);
public:
COrder_Explore() : COrder(UnitActionExplore), WaitingCycle(0), Range(0)
{
goalPos.x = -1;
goalPos.y = -1;
}
virtual COrder_Explore *Clone() const { return new COrder_Explore(*this); }
virtual bool IsValid() const;
virtual void Save(CFile &file, const CUnit &unit) const;
virtual bool ParseSpecificData(lua_State *l, int &j, const char *value, const CUnit &unit);
virtual void Execute(CUnit &unit);
virtual PixelPos Show(const CViewport &vp, const PixelPos &lastScreenPos) const;
virtual void UpdatePathFinderData(PathFinderInput &input);
virtual const Vec2i GetGoalPos() const;
private:
unsigned int WaitingCycle; /// number of cycle pathfinder wait.
int Range;
Vec2i goalPos;
};
//@}
#endif // !__ACTION_EXPLORE_H__

View file

@ -54,6 +54,7 @@ public:
virtual void Execute(CUnit &unit);
virtual PixelPos Show(const CViewport &vp, const PixelPos &lastScreenPos) const;
virtual void UpdatePathFinderData(PathFinderInput &input);
virtual const Vec2i GetGoalPos() const;
private:
unsigned int State;
int Range;

View file

@ -54,6 +54,7 @@ public:
virtual void Execute(CUnit &unit);
virtual PixelPos Show(const CViewport &vp, const PixelPos &lastScreenPos) const;
virtual void UpdatePathFinderData(PathFinderInput &input);
virtual const Vec2i GetGoalPos() const;
private:
int Range;

View file

@ -56,6 +56,7 @@ public:
virtual void UpdatePathFinderData(PathFinderInput &input);
const Vec2i &GetWayPoint() const { return WayPoint; }
virtual const Vec2i GetGoalPos() const;
private:
Vec2i WayPoint; /// position for patroling.
unsigned int WaitingCycle; /// number of cycle pathfinder wait.

View file

@ -57,6 +57,7 @@ public:
virtual void UpdatePathFinderData(PathFinderInput &input);
const CUnitPtr &GetReparableTarget() const { return ReparableTarget; }
virtual const Vec2i GetGoalPos() const;
private:
bool RepairUnit(const CUnit &unit, CUnit &goal);
private:

View file

@ -68,6 +68,7 @@ public:
bool IsGatheringStarted() const;
bool IsGatheringFinished() const;
bool IsGatheringWaiting() const;
virtual const Vec2i GetGoalPos() const;
private:
int MoveToResource_Terrain(CUnit &unit);
int MoveToResource_Unit(CUnit &unit);

View file

@ -54,6 +54,7 @@ public:
virtual void Execute(CUnit &unit);
virtual PixelPos Show(const CViewport &vp, const PixelPos &lastScreenPos) const;
virtual void UpdatePathFinderData(PathFinderInput &input);
virtual const Vec2i GetGoalPos() const { return goalPos; }
private:
bool LeaveTransporter(CUnit &transporter);

View file

@ -70,6 +70,7 @@ enum UnitAction {
UnitActionUnload, /// unit leaving transporter
UnitActionPatrol, /// unit paroling area
UnitActionBuild, /// unit builds building
UnitActionExplore, /// unit explores map
UnitActionRepair, /// unit repairing
UnitActionResource, /// unit harvesting resources
@ -133,6 +134,7 @@ public:
static COrder *NewActionBuilt(CUnit &builder, CUnit &unit);
static COrder *NewActionDefend(CUnit &dest);
static COrder *NewActionDie();
static COrder *NewActionExplore(const CUnit &unit);
static COrder *NewActionFollow(CUnit &dest);
static COrder *NewActionMove(const Vec2i &pos);
static COrder *NewActionPatrol(const Vec2i &currentPos, const Vec2i &dest);

View file

@ -84,6 +84,8 @@ extern void CommandBoard(CUnit &unit, CUnit &dest, int flush);
extern void CommandUnload(CUnit &unit, const Vec2i &pos, CUnit *what, int flush);
/// Prepare command build
extern void CommandBuildBuilding(CUnit &unit, const Vec2i &pos, CUnitType &, int flush);
/// Prepare command explore
extern void CommandExplore(CUnit &unit, int flush);
/// Prepare command dismiss
extern void CommandDismiss(CUnit &unit);
/// Prepare command resource location
@ -152,6 +154,8 @@ extern void SendCommandBoard(CUnit &unit, CUnit &dest, int flush);
extern void SendCommandUnload(CUnit &unit, const Vec2i &pos, CUnit *what, int flush);
/// Send build building command
extern void SendCommandBuildBuilding(CUnit &unit, const Vec2i &pos, CUnitType &what, int flush);
/// Send explore command
extern void SendCommandExplore(CUnit &unit, int flush);
/// Send cancel building command
extern void SendCommandDismiss(CUnit &unit);
/// Send harvest location command

View file

@ -92,7 +92,7 @@ public:
virtual int getHeight() const { return Height(); }
virtual int getWidth(const std::string &text) const { return Width(text); }
virtual void drawString(gcn::Graphics *graphics, const std::string &text, int x, int y);
virtual void drawString(gcn::Graphics *graphics, const std::string &text, int x, int y, bool is_normal = true);
void Load();
void Reload() const;
@ -207,7 +207,7 @@ public:
int Draw(int x, int y, int number) const;
/// Draw text/number clipped
int DrawClip(int x, int y, const char *const text) const;
int DrawClip(int x, int y, const std::string &text) const;
int DrawClip(int x, int y, const std::string &text, bool is_normal = true) const;
int DrawClip(int x, int y, int number) const;
/// Draw reverse text/number unclipped
int DrawReverse(int x, int y, const char *const text) const;

View file

@ -63,6 +63,7 @@ enum ButtonCmd {
ButtonHarvest, /// order harvest
ButtonBuild, /// order build
ButtonPatrol, /// order patrol
ButtonExplore, /// order explore
ButtonAttackGround, /// order attack ground
ButtonSpellCast, /// order cast spell
ButtonUnload, /// order unload unit

View file

@ -61,6 +61,7 @@ public:
int GetLastRecvState() { return lastRecvState; }
int GetLogSize() { return events.size(); }
CClientLog *GetLastMessage() { return events.back(); }
int CreateGame(std::string desc, std::string map, std::string players);
private:
CTCPSocket metaSocket; /// This is a TCP socket

View file

@ -462,7 +462,7 @@ public:
static unsigned int Count; /// slot number generator.
};
extern bool MissileInitMove(Missile &missile);
extern bool MissileInitMove(Missile &missile, bool pointToPoint = false);
extern bool PointToPointMissile(Missile &missile);
extern void MissileHandlePierce(Missile &missile, const Vec2i &pos);
extern bool MissileHandleBlocking(Missile &missile, const PixelPos &position);
@ -627,9 +627,7 @@ extern void InitMissiles();
/// Clean missiles
extern void CleanMissiles();
#ifdef DEBUG
extern void FreeBurningBuildingFrames();
#endif
//@}

View file

@ -51,6 +51,7 @@
# include <netdb.h>
# include <sys/socket.h>
# include <sys/ioctl.h>
# include <ifaddrs.h>
# ifndef __BEOS__
# include <net/if.h>
# include <arpa/inet.h>

View file

@ -105,7 +105,7 @@ enum _ic_message_subtype_ {
ICMConfig, /// Setup message configure clients
ICMEngineMismatch, /// Stratagus engine version doesn't match
ICMProtocolMismatch, /// Network protocol version doesn't match
ICMLuaFilesMismatch, /// Network protocol version doesn't match
ICMEngineConfMismatch, /// UNUSED:Engine configuration isn't identical
ICMMapUidMismatch, /// MAP UID doesn't match
@ -161,7 +161,7 @@ private:
public:
char PlyName[NetPlayerNameSize]; /// Name of player
int32_t Stratagus; /// Stratagus engine version
int32_t Version; /// Network protocol version
uint32_t Version; /// Lua files version
};
class CInitMessage_Config
@ -194,10 +194,10 @@ public:
int32_t Stratagus; /// Stratagus engine version
};
class CInitMessage_ProtocolMismatch
class CInitMessage_LuaFilesMismatch
{
public:
CInitMessage_ProtocolMismatch();
CInitMessage_LuaFilesMismatch();
const CInitMessage_Header &GetHeader() const { return header; }
const unsigned char *Serialize() const;
void Deserialize(const unsigned char *p);
@ -205,7 +205,7 @@ public:
private:
CInitMessage_Header header;
public:
int32_t Version; /// Network protocol version
uint32_t Version; /// Lua files version
};
class CInitMessage_Welcome
@ -299,6 +299,7 @@ enum _message_type_ {
MessageCommandBoard, /// Unit command board
MessageCommandUnload, /// Unit command unload
MessageCommandBuild, /// Unit command build building
MessageCommandExplore, /// Unit command explore
MessageCommandDismiss, /// Unit command dismiss unit
MessageCommandResourceLoc, /// Unit command resource location
MessageCommandResource, /// Unit command resource

View file

@ -80,7 +80,7 @@ enum _net_client_con_state_ {
ccs_goahead, /// Server wants to start game
ccs_started, /// Server has started game
ccs_incompatibleengine, /// Incompatible engine version
ccs_incompatiblenetwork /// Incompatible netowrk version
ccs_incompatibleluafiles /// Incompatible lua files
};
/*----------------------------------------------------------------------------

View file

@ -67,6 +67,7 @@ public:
//
int HasDataToRead(int timeout);
bool IsValid() const;
int GetSocketAddresses(unsigned long *ips, int maxAddr);
#ifdef DEBUG

View file

@ -373,9 +373,7 @@ extern void GraphicPlayerPixels(CPlayer &player, const CGraphic &sprite);
/// Output debug information for players
extern void DebugPlayers();
#ifdef DEBUG
void FreePlayerColors();
#endif
/// register ccl features
extern void PlayerCclRegister();

View file

@ -2,8 +2,14 @@
#define __SHADERS_H__
#ifdef USE_OPENGL
#define MAX_SHADERS 5
extern unsigned ShaderIndex;
extern void LoadShaders();
// #define SHADERDEBUG // Uncomment for loading shaders from file
#ifndef __APPLE__
extern PFNGLBINDFRAMEBUFFEREXTPROC glBindFramebuffer;
#else
#define glBindFramebuffer glBindFramebufferEXT
#endif
extern GLuint fullscreenFramebuffer;
extern bool LoadShaders(int direction, char* shadernameOut);
extern bool LoadShaderExtensions();
extern void SetupFramebuffer();
extern void RenderFramebufferToScreen();

Some files were not shown because too many files have changed in this diff Show more