Merge branch 'develop' into feature-email

This commit is contained in:
RElesgoe 2020-07-25 11:37:46 -07:00 committed by GitHub
commit 3b434de746
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
17 changed files with 463 additions and 346 deletions

View file

@ -33,6 +33,8 @@ message(STATUS "*** {fmt} ***")
add_subdirectory(fmt)
message(STATUS "*** {fmt} ***")
set(USE_INCLUDED_ZLIB_LIBRARY OFF)
if(WITH_BNETD)
if (WIN32)
set(CURL_LIBRARY ${CMAKE_SOURCE_DIR}/lib/curl/7.70.0/libcurl.lib)
@ -43,9 +45,12 @@ if(WITH_BNETD)
if (POLICY CMP0074)
cmake_policy(SET CMP0074 NEW)
endif()
if (NOT DEFINED ZLIB_ROOT)
set(USE_INCLUDED_ZLIB_LIBRARY ON)
set(ZLIB_ROOT ${CMAKE_SOURCE_DIR}/include/zlib/1.2.11 ${CMAKE_SOURCE_DIR}/lib/zlib/1.2.11)
endif()
find_package(ZLIB REQUIRED)
endif(WITH_BNETD)

View file

@ -44,6 +44,7 @@ By default, tracking is enabled and is only used for the purpose of sending info
- **Emperor: Battle for Dune**: 1.09
\* WarCraft 3 clients are unable to connect to PvPGN servers without a client-side modification, through tools such as [W3L](https://github.com/w3lh/w3l), to disable server signature verification.
\* StarCraft clients beginning with patch 1.18 will not be supported by PvPGN-PRO due to protocol changes. A 1.18.0 versioncheck entry is included for compatibility with bot software.
## Support
@ -79,7 +80,7 @@ make
make install
```
#### Ubuntu 16.04
#### Ubuntu 16.04, 18.04
```
sudo apt-get -y install build-essential git cmake zlib1g-dev
git clone https://github.com/pvpgn/pvpgn-server.git
@ -102,7 +103,7 @@ cd pvpgn-server && cmake -G "Unix Makefiles" -H./ -B./build
cd build && make
```
#### Debian 8
#### Debian 8 with clang compiler
```
sudo apt-get -y install build-essential zlib1g-dev clang libc++-dev git
wget https://cmake.org/files/v3.7/cmake-3.7.1-Linux-x86_64.tar.gz
@ -143,6 +144,11 @@ cd build && make
Full instructions: [Русский](http://harpywar.com/?a=articles&b=2&c=1&d=74) | [English](http://harpywar.com/?a=articles&b=2&c=1&d=74&lang=en)
## Hosting on LAN or VPS with private IP address
Some VPS providers do not assign your server a direct public IP. If that is the case or you host at home behind NAT you need to setup the route translation in `address_translation.conf`. The public address is pushed as the route server address to game clients when seeking games. Failure to push the correct address to game clients results in players not being able to match and join games (long game search and error).
If your network interface is directly bound to public IP, PvPGN can figure it out on it's own and this step is not necessary.
## License
This program is free software; you can redistribute it and/or

View file

@ -22,8 +22,7 @@ environment:
db_id: 5
configuration:
# - Debug
- Release
- RelWithDebInfo
matrix:
fast_finish: true
@ -40,15 +39,14 @@ install:
- cmd: xcopy /E /R /K /Y /Q "c:\pvpgn" "c:\builder\source\"
- cmd: cd c:\builder\
- cmd: mkdir bin
- cmd: mkdir pdb
before_build:
- cmd: set APPVEYOR_REPO_COMMIT_SHORT=%APPVEYOR_REPO_COMMIT:~0,7%
# read version string from version.h to %PVPGN_VERSION% and append commit string inside that file
- cmd: module\tools\pvpgn_version.bat %APPVEYOR_REPO_COMMIT_SHORT%
- cmd: set COMPLETE_BUILD_VERSION=pvpgn-%APPVEYOR_REPO_BRANCH%-%PVPGN_VERSION%-%APPVEYOR_REPO_COMMIT_SHORT%
- ps: $env:PVPGN_ZIP=$env:COMPLETE_BUILD_VERSION + "_" + $env:DB + $(If ($env:CONFIGURATION -ne "Release") {"_" + ($env:CONFIGURATION).ToLower()} Else {""}) + ".zip"
- ps: $env:PVPGN_PDB_ZIP=$env:COMPLETE_BUILD_VERSION + "_" + $env:DB + $(If ($env:CONFIGURATION -ne "Release") {"_" + ($env:CONFIGURATION).ToLower()} Else {".pdb"}) + ".zip"
- ps: $env:PVPGN_ZIP=$env:COMPLETE_BUILD_VERSION + "_" + $env:DB + ".zip"
build_script:
@ -56,27 +54,23 @@ build_script:
# build_pvpgn.bat params:
# 1. automatic build flag
# 2. visual studio version
# 3. console or gui
# 3. console | gui | console x64 | gui x64
# 4. storage type
# 5. with or without lua
# 6. Release or Debug
# 6. RelWithDebInfo | Release | Debug
# gui
- cmd: build_pvpgn.bat auto auto 2 %DB_ID% y %CONFIGURATION%
- cmd: move /Y %CONFIGURATION%\*.pdb pdb\ # move pdb files
- cmd: copy /Y %CONFIGURATION%\* bin\ # backup binary files
- cmd: copy /Y release\* bin\ # backup binary files
# console
- cmd: build_pvpgn.bat auto auto 1 %DB_ID% y %CONFIGURATION%
- cmd: move /Y %CONFIGURATION%\*.pdb pdb\ # move pdb files
- cmd: move /Y bin\* %CONFIGURATION% # move back binaries after build console version
- cmd: move /Y bin\* release # move back binaries after build console version
# create zip artifacts
- cmd: 7z.exe a %PVPGN_ZIP% .\%CONFIGURATION%\*
- cmd: 7z.exe a %PVPGN_PDB_ZIP% .\pdb\*
- cmd: 7z.exe a %PVPGN_ZIP% .\release\*
deploy_script:
- ps: |
Push-AppveyorArtifact $env:PVPGN_ZIP
Push-AppveyorArtifact $env:PVPGN_PDB_ZIP
# check the latest build executable for exists
test:

View file

@ -1,95 +1,80 @@
#--------------------------------------------------------
# Copyright (C) 1995-2007 MySQL AB
# - Try to find MySQL.
# Once done this will define:
# MYSQL_FOUND - If false, do not try to use MySQL.
# MYSQL_INCLUDE_DIRS - Where to find mysql.h, etc.
# MYSQL_LIBRARIES - The libraries to link against.
# MYSQL_VERSION_STRING - Version in a string of MySQL.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of version 2 of the GNU General Public License as
# published by the Free Software Foundation.
# Created by RenatoUtsch based on eAthena implementation.
#
# There are special exceptions to the terms and conditions of the GPL
# as it is applied to this software. View the full text of the exception
# in file LICENSE.exceptions in the top-level directory of this software
# distribution.
# Please note that this module only supports Windows and Linux officially, but
# should work on all UNIX-like operational systems too.
#
# 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.
#=============================================================================
# Copyright 2012 RenatoUtsch
#
# 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
# Distributed under the OSI-approved BSD License (the "License");
# see accompanying file Copyright.txt for details.
#
# The MySQL Connector/ODBC is licensed under the terms of the
# GPL, like most MySQL Connectors. There are special exceptions
# to the terms and conditions of the GPL as it is applied to
# this software, see the FLOSS License Exception available on
# mysql.com.
##########################################################################
# This software is distributed WITHOUT ANY WARRANTY; without even the
# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
# See the License for more information.
#=============================================================================
# (To distribute this file outside of CMake, substitute the full
# License text for the above reference.)
if( WIN32 )
set(MYENV "PROGRAMFILES(X86)")
find_path( MYSQL_INCLUDE_DIR
NAMES "mysql.h"
PATHS "$ENV{PROGRAMFILES}/MySQL/*/include"
"$ENV{${MYENV}}/MySQL/*/include"
"$ENV{SYSTEMDRIVE}/MySQL/*/include" )
find_library( MYSQL_LIBRARY
NAMES "mysqlclient" "mysqlclient_r" "libmysql"
PATHS "$ENV{PROGRAMFILES}/MySQL/*/lib"
"$ENV{${MYENV}}/MySQL/*/lib"
"$ENV{SYSTEMDRIVE}/MySQL/*/lib" )
else()
find_path( MYSQL_INCLUDE_DIR
NAMES "mysql.h"
PATHS "/usr/include/mysql"
"/usr/local/include/mysql"
"/usr/mysql/include/mysql" )
find_library( MYSQL_LIBRARY
NAMES "mysqlclient" "mysqlclient_r"
PATHS "/lib/mysql"
"/lib64/mysql"
"/usr/lib/mysql"
"/usr/lib64/mysql"
"/usr/local/lib/mysql"
"/usr/local/lib64/mysql"
"/usr/mysql/lib/mysql"
"/usr/mysql/lib64/mysql" )
endif()
#-------------- FIND MYSQL_INCLUDE_DIR ------------------
FIND_PATH(MYSQL_INCLUDE_DIR mysql.h
/usr/include/mysql
/usr/local/include/mysql
/opt/mysql/mysql/include
/opt/mysql/mysql/include/mysql
/opt/mysql/include
/opt/local/include/mysql5
/usr/local/mysql/include
/usr/local/mysql/include/mysql
$ENV{ProgramW6432}/MySQL/*/include
$ENV{ProgramFiles}/MySQL/*/include
$ENV{SystemDrive}/MySQL/*/include)
#----------------- FIND MYSQL_LIB_DIR -------------------
IF (WIN32)
FIND_LIBRARY(MYSQL_LIB NAMES mysqlclient
PATHS
$ENV{MYSQL_DIR}/lib/
$ENV{MYSQL_DIR}/libmysql
$ENV{MYSQL_DIR}/libmysql/
$ENV{MYSQL_DIR}/client/
$ENV{MYSQL_DIR}/libmysql/
$ENV{ProgramW6432}/MySQL/*/lib/
$ENV{ProgramFiles}/MySQL/*/lib/
$ENV{SystemDrive}/MySQL/*/lib/)
ELSE (WIN32)
FIND_LIBRARY(MYSQL_LIB NAMES mysqlclient_r mysqlclient
PATHS
/usr/lib/mysql
/usr/local/lib/mysql
/usr/local/mysql/lib
/usr/local/mysql/lib/mysql
/opt/local/mysql5/lib
/opt/local/lib/mysql5/mysql
/opt/mysql/mysql/lib/mysql
/opt/mysql/lib/mysql)
ENDIF (WIN32)
IF(MYSQL_LIB)
GET_FILENAME_COMPONENT(MYSQL_LIB_DIR ${MYSQL_LIB} PATH)
ENDIF(MYSQL_LIB)
IF (MYSQL_INCLUDE_DIR AND MYSQL_LIB_DIR)
IF (MYSQL_INCLUDE_DIR AND MYSQL_LIBRARY)
SET(MYSQL_FOUND TRUE)
SET( MYSQL_LIBRARIES ${MYSQL_LIBRARY} )
ELSE (MYSQL_INCLUDE_DIR AND MYSQL_LIBRARY)
SET(MYSQL_FOUND FALSE)
SET( MYSQL_LIBRARIES )
ENDIF (MYSQL_INCLUDE_DIR AND MYSQL_LIBRARY)
INCLUDE_DIRECTORIES(${MYSQL_INCLUDE_DIR})
LINK_DIRECTORIES(${MYSQL_LIB_DIR})
IF (MYSQL_FOUND)
MESSAGE(STATUS "Found MySQL: ${MYSQL_LIBRARY}")
ELSE (MYSQL_FOUND)
IF (MySQL_FIND_REQUIRED)
MESSAGE(STATUS "Looked for MySQL libraries named ${MYSQL_NAMES}.")
MESSAGE(FATAL_ERROR "Could NOT find MySQL library")
ENDIF (MySQL_FIND_REQUIRED)
ENDIF (MYSQL_FOUND)
IF (MYSQL_LIB)
SET(MYSQL_CLIENT_LIBS ${MYSQL_LIB})
ELSE()
SET(MYSQL_CLIENT_LIBS mysqlclient_r)
ENDIF()
# Added needed mysqlclient dependencies on Windows
IF (WIN32)
SET(MYSQL_CLIENT_LIBS ${MYSQL_CLIENT_LIBS} ws2_32)
ENDIF (WIN32)
MESSAGE(STATUS "MySQL Include dir: ${MYSQL_INCLUDE_DIR} library dir: ${MYSQL_LIB_DIR}")
MESSAGE(STATUS "MySQL client libraries: ${MYSQL_CLIENT_LIBS}")
ELSEIF (MySQL_FIND_REQUIRED)
MESSAGE(FATAL_ERROR "Cannot find MySQL. Include dir: ${MYSQL_INCLUDE_DIR} library dir: ${MYSQL_LIB_DIR}")
ENDIF (MYSQL_INCLUDE_DIR AND MYSQL_LIB_DIR)
MARK_AS_ADVANCED(
MYSQL_LIBRARY
MYSQL_INCLUDE_DIR
)

View file

@ -35,24 +35,44 @@
# ${-19} - substitute arguments 0-19 here #
# ${2-} - substitue all arguments from 2 until the end here #
# #
@
//doubt //dt //d
[0]/me looks with doubt
[1+]/me looks at ${1-} with doubt
@
//numusers //nu
[0]%IThere are %u users online.
[0]%IThere are %g games online.
[0]%IThere are %c channels online.
[1+]%EThat command does not take any arguments.
@
//askban //ab
[2+]/w $1 Please ban ${2-}.
@
//statsme //sm
[0]/stats %u
@
//pvpgn
[*]/announce PVPGN rulez!
# %a - Number of registered accounts #
# %c - Number of existing channels #
# %g - Number of running games #
# %G - Number of games with the same clienttag #
# %h - Hostname of the server #
# %H - Contact name (as set in bnetd.conf) #
# %i - The userid of the user #
# %I - The username of the user #
# %N - Name of the game the user has connected with #
# %m - Check the user's mail #
# %r - IP address of the user #
# %s - Servername #
# %t - The clienttag of the user #
# %u - Number of users currently logged in #
# %U - Number of users logged in with the same clienttag #
# %v - Server version #
# #
# Examples #
#@
#//doubt //dt //d
#[0]/me looks with doubt
#[1+]/me looks at ${1-} with doubt
#@
#//numusers //nu
#[0]%IThere are %u users online.
#[0]%IThere are %g games online.
#[0]%IThere are %c channels online.
#[1+]%EThat command does not take any arguments.
#@
#//askban //ab
#[2+]/w $1 Please ban ${2-}.
#@
#//statsme //sm
#[0]/stats %u
#@
#//pvpgn
#[*]/announce PVPGN rulez!
#
# #
##############################################################################

View file

@ -434,12 +434,12 @@ max_friends = 20
# Set track=0 to disable tracking. Any other number will set number
# of seconds between sending tracking packets. This is ON by default.
#track = 0
track = 0
track = 60
# Tracking server(s)
# Use a comma delimited list of hostnames with optional UDP port numbers
# after colons. (port 6114 is the default for the newer tracking protocol)
trackaddrs = "track.pvpgn.org,bntrack.darkwings.org,bnet.mivabe.nl,track.eurobattle.net"
trackaddrs = "track.pvpgn.pro,track.pvpgn.org,bnet.mivabe.nl,track.eurobattle.net"
# Change these to match your system, for example:
location = "unknown"

View file

@ -420,7 +420,7 @@ track = 60
# Tracking server(s)
# Use a comma delimited list of hostnames with optional UDP port numbers
# after colons. (port 6114 is the default for the newer tracking protocol)
trackaddrs = "track.pvpgn.org,bntrack.darkwings.org,bnet.mivabe.nl,track.eurobattle.net"
trackaddrs = "track.pvpgn.pro,track.pvpgn.org,bnet.mivabe.nl,track.eurobattle.net"
# Change these to match your system, for example:
location = "unknown"

View file

@ -2068,47 +2068,50 @@
<original>User "{}" is offline</original>
<translate></translate>
</item>
<item id="516" file="command.cpp" function="_handle_email_command">
<item id="516" file="clan.cpp" function="clan_create">
<original>This is a newly created clan</original>
<translate></translate>
<item id="517" file="command.cpp" function="_handle_email_command">
<original>An error has occurred.</original>
<translate></translate>
</item>
<item id="517" file="command.cpp" function="_handle_email_command">
<item id="518" file="command.cpp" function="_handle_email_command">
<original>Your email address is: {}</original>
<translate></translate>
</item>
<item id="518" file="command.cpp" function="_handle_email_command">
<item id="519" file="command.cpp" function="_handle_email_command">
<original>Email address successfully set to {}.</original>
<translate></translate>
</item>
<item id="519" file="command.cpp" function="_handle_email_command">
<item id="520" file="command.cpp" function="_handle_email_command">
<original>Successfully verified email address.</original>
<translate></translate>
</item>
<item id="520" file="command.cpp" function="_handle_email_command">
<item id="521" file="command.cpp" function="_handle_email_command">
<original>The code has already expired.</original>
<translate></translate>
</item>
<item id="521" file="command.cpp" function="_handle_email_command">
<item id="522" file="command.cpp" function="_handle_email_command">
<original>The code is incorrect.</original>
<translate></translate>
</item>
<item id="522" file="command.cpp" function="_handle_email_command">
<item id="523" file="command.cpp" function="_handle_email_command">
<original>Regenerated verification code. Check your email.</original>
<translate></translate>
</item>
<item id="523" file="command.cpp" function="_handle_email_command">
<item id="524" file="command.cpp" function="_handle_email_command">
<original>Your email address is already set to {}.</original>
<translate></translate>
</item>
<item id="524" file="command.cpp" function="_handle_email_command">
<item id="525" file="command.cpp" function="_handle_email_command">
<original>Email address verification is disabled.</original>
<translate></translate>
</item>
<item id="525" file="command.cpp" function="_handle_email_command">
<item id="526" file="command.cpp" function="_handle_email_command">
<original>The email address is too long, please use another one.</original>
<translate></translate>
</item>
<item id="526" file="command.cpp" function="_handle_email_command">
<item id="527" file="command.cpp" function="_handle_email_command">
<original>You have not set an email address yet.</original>
<translate></translate>
</item>

View file

@ -864,6 +864,21 @@
}
]
}
},
"PMAC": {
"0x4f": {
"checkRevisionFile": "PMACver1.mpq",
"equation": "A=3845581634 B=880823580 C=1363937103 4 A=A-S B=B-C C=C-A A=A-B",
"entries": [
{
"title": "Warcraft II BNE 2.02",
"version": "2.0.2.1",
"hash": "0xaed93b05",
"fileMetadata": "Warcraft II BNE 05/21/101 15:44:14 931587",
"versionTag": "W2BN_202"
}
]
}
}
},
"STAR": {
@ -1329,6 +1344,21 @@
}
]
}
},
"PMAC": {
"0xd1": {
"checkRevisionFile": "PMACver1.mpq",
"equation": "A=3845581634 B=880823580 C=1363937103 4 A=A-S B=B-C C=C-A A=A-B",
"entries": [
{
"title": "Starcraft - Broodwar (Expansion) 1.15 - (Starcraft mode)",
"version": "1.15.0.1",
"hash": "0xeb5f82bd",
"fileMetadata": "Starcraft 07/16/107 18:00:00 1606200",
"versionTag": "STAR_115"
}
]
}
}
},
"SEXP": {
@ -1613,6 +1643,21 @@
}
]
}
},
"PMAC": {
"0xd1": {
"checkRevisionFile": "PMACver1.mpq",
"equation": "A=3845581634 B=880823580 C=1363937103 4 A=A-S B=B-C C=C-A A=A-B",
"entries": [
{
"title": "Starcraft - Broodwar (Expansion) 1.15 - (Broodwar mode)",
"version": "1.15.0.1",
"hash": "0xeb5f82bd",
"fileMetadata": "Starcraft 07/16/107 18:00:00 1606200",
"versionTag": "SEXP_115"
}
]
}
}
},
"DRTL": {
@ -1650,6 +1695,34 @@
}
]
}
},
"PMAC": {
"0x2a": {
"checkRevisionFile": "PMACver1.mpq",
"equation": "A=3845581634 B=880823580 C=1363937103 4 A=A-S B=B-C C=C-A A=A-B",
"entries": [
{
"title": "Diablo 109",
"version": "1.0.9.2",
"hash": "0x2b079060",
"fileMetadata": "Diablo 05/12/101 15:42:00 1160990",
"versionTag": "DRTL_109"
}
]
},
"0x28": {
"checkRevisionFile": "PMACver1.mpq",
"equation": "A=3845581634 B=880823580 C=1363937103 4 A=A-S B=B-C C=C-A A=A-B",
"entries": [
{
"title": "Diablo 108",
"version": "1.0.8.0",
"hash": "0x82f94d6a",
"fileMetadata": "Diablo 06/13/100 12:00:00 1113966",
"versionTag": "DRTL_108"
}
]
}
}
},
"D2XP": {

View file

@ -60,9 +60,19 @@ target_include_directories(bnetd
${ODBC_INCLUDE_DIR}
)
target_link_libraries(bnetd PRIVATE common compat fmt::fmt win32 ${NETWORK_LIBRARIES} ZLIB::ZLIB ${CURL_LIBRARIES} ${MYSQL_CLIENT_LIBS} ${SQLITE3_LIBRARIES} ${PGSQL_LIBRARIES} ${ODBC_LIBRARIES} ${LUA_LIBRARIES})
target_link_libraries(bnetd PRIVATE common compat fmt win32 ${NETWORK_LIBRARIES} ${ZLIB_LIBRARIES} ${MYSQL_LIBRARIES} ${SQLITE3_LIBRARIES} ${PGSQL_LIBRARIES} ${ODBC_LIBRARIES} ${LUA_LIBRARIES})
install(TARGETS bnetd DESTINATION ${SBINDIR})
if(WIN32 AND MSVC)
install(FILES $<TARGET_PDB_FILE:bnetd> DESTINATION ${SBINDIR} OPTIONAL)
endif()
if (WIN32 AND USE_INCLUDED_ZLIB_LIBRARY)
install(
FILES
"${PROJECT_SOURCE_DIR}/lib/zlib/1.2.11/zlib1.dll"
DESTINATION
${SBINDIR}
)
endif()

View file

@ -48,6 +48,7 @@
#include "anongame.h"
#include "storage.h"
#include "server.h"
#include "i18n.h"
#include "common/setup_after.h"
@ -1401,6 +1402,7 @@ namespace pvpgn
{
t_clan *clan;
t_clanmember *member;
t_connection * c;
clan = (t_clan*)xmalloc(sizeof(t_clan));
member = (t_clanmember*)xmalloc(sizeof(t_clanmember));
@ -1412,11 +1414,11 @@ namespace pvpgn
xfree((void *)member);
return NULL;
}
c = account_get_conn(chieftain_acc);
clan->clanname = xstrdup(clanname);
if (!(motd))
clan->clan_motd = xstrdup("This is a newly created clan");
clan->clan_motd = xstrdup(localize(c, "This is a newly created clan").c_str());
else
clan->clan_motd = xstrdup(motd);

View file

@ -2921,7 +2921,7 @@ namespace pvpgn
bn_int_set(&rpacket->u.server_motd_w3.timestamp2, SERVER_MOTD_W3_WELCOME);
// read text from bnmotd_w3.txt
// read text from w3motd.txt
{
fmt::memory_buffer serverinfo;
@ -2932,16 +2932,22 @@ namespace pvpgn
while (char* buff = file_get_line(fp))
{
char* line = message_format_line(c, buff);
fmt::format_to(serverinfo, "{}" + '\n', (line + 1));
fmt::format_to(std::back_inserter(serverinfo), "{}\n", line + 1);
xfree((void*)line);
}
if (std::fclose(fp) == EOF)
{
eventlog(eventlog_level_error, __FUNCTION__, "could not close motdw3 file \"{}\" after reading (std::fopen: {})", filename, std::strerror(errno));
eventlog(eventlog_level_error, __FUNCTION__, "Failed to close w3motd file \"{}\" after reading (std::fopen: {})", filename, std::strerror(errno));
}
}
packet_append_string(rpacket, fmt::to_string(serverinfo).c_str());
else
{
eventlog(eventlog_level_error, __FUNCTION__, "Failed to open w3motd file \"{}\"", filename);
fmt::format_to(serverinfo, "An error has occurred.");
}
packet_append_string(rpacket, serverinfo.data());
}
conn_push_outqueue(c, rpacket);

View file

@ -172,7 +172,14 @@ namespace pvpgn
// mysql->reconnect = 1;
#endif
#if MYSQL_VERSION_ID >= 50019
#if MYSQL_VERSION_ID < 80001
my_bool my_true = true;
#endif
#if MYSQL_VERSION_ID >= 80001
// Since 8.0.1 the my_bool type is no longer used in MySQL source code. Any third-party code that used this type to represent C boolean variables should use the bool or int C type instead.
// The change from my_bool to bool means that the mysql.h header file now requires a C++ or C99 compiler to compile.
bool my_true = true;
#endif
if (mysql_options(mysql, MYSQL_OPT_RECONNECT, &my_true)){
eventlog(eventlog_level_warn, __FUNCTION__, "Failed to turn on MYSQL_OPT_RECONNECT.");
}

View file

@ -533,20 +533,24 @@ namespace pvpgn
}
tstr = xstrdup(str);
int fail = 0;
int success = 0;
for (tok = std::strtok(tstr, ","); tok; tok = std::strtok(NULL, ",")) /* std::strtok modifies the string it is passed */
{
if (!(addr = addr_create_str(tok, defipaddr, defport)))
{
eventlog(eventlog_level_error, __FUNCTION__, "could not create addr");
xfree(tstr);
return -1;
eventlog(eventlog_level_error, __FUNCTION__, "could not create addr for {}", tok);
fail++;
continue;
}
list_append_data(addrlist, addr);
success++;
}
xfree(tstr);
return 0;
return (fail == 0 || success > 0) ? 0 : -1;
}
extern t_addrlist * addrlist_create(char const * str, unsigned int defipaddr, unsigned short defport)

View file

@ -854,57 +854,74 @@ static int on_client_charlistreq(t_connection * c, t_packet * packet)
packet_set_type(rpacket,D2CS_CLIENT_CHARLISTREPLY);
bn_short_set(&rpacket->u.d2cs_client_charlistreply.u1,0);
n=0;
try {
Directory dir(path);
while ((charname=dir.read())) {
charinfo = (t_d2charinfo_file*)xmalloc(sizeof(t_d2charinfo_file));
if (d2charinfo_load(account,charname,charinfo)<0) {
eventlog(eventlog_level_error,__FUNCTION__,"error loading charinfo for {}(*{})",charname,account);
xfree((void *)charinfo);
continue;
bool retry = true;
while (retry)
{
try {
Directory dir(path);
while ((charname = dir.read())) {
charinfo = (t_d2charinfo_file*)xmalloc(sizeof(t_d2charinfo_file));
if (d2charinfo_load(account, charname, charinfo) < 0) {
eventlog(eventlog_level_error, __FUNCTION__, "error loading charinfo for {}(*{})", charname, account);
xfree((void*)charinfo);
continue;
}
eventlog(eventlog_level_debug, __FUNCTION__, "adding char {} (*{})", charname, account);
d2charlist_add_char(&charlist_head, charinfo, 0);
n++;
if (n >= maxchar) break;
}
eventlog(eventlog_level_debug,__FUNCTION__,"adding char {} (*{})", charname, account);
d2charlist_add_char(&charlist_head,charinfo,0);
n++;
if (n>=maxchar) break;
}
if (prefs_allow_newchar() && (n<maxchar)) {
bn_short_set(&rpacket->u.d2cs_client_charlistreply.maxchar,maxchar);
} else {
bn_short_set(&rpacket->u.d2cs_client_charlistreply.maxchar,0);
}
if (!std::strcmp(charlist_sort_order, "ASC"))
{
t_elist * curr, * safe;
t_d2charlist * ccharlist;
if (prefs_allow_newchar() && (n < maxchar)) {
bn_short_set(&rpacket->u.d2cs_client_charlistreply.maxchar, maxchar);
}
else {
bn_short_set(&rpacket->u.d2cs_client_charlistreply.maxchar, 0);
}
if (!std::strcmp(charlist_sort_order, "ASC"))
{
t_elist* curr, * safe;
t_d2charlist* ccharlist;
elist_for_each_safe(curr,&charlist_head,safe)
{
ccharlist = elist_entry(curr,t_d2charlist,list);
packet_append_string(rpacket,(char*)ccharlist->charinfo->header.charname);
packet_append_string(rpacket,(char *)&ccharlist->charinfo->portrait);
xfree((void *)ccharlist->charinfo);
xfree((void *)ccharlist);
}
}
else
{
t_elist * curr, * safe;
t_d2charlist * ccharlist;
elist_for_each_safe(curr, &charlist_head, safe)
{
ccharlist = elist_entry(curr, t_d2charlist, list);
packet_append_string(rpacket, (char*)ccharlist->charinfo->header.charname);
packet_append_string(rpacket, (char*)&ccharlist->charinfo->portrait);
xfree((void*)ccharlist->charinfo);
xfree((void*)ccharlist);
}
}
else
{
t_elist* curr, * safe;
t_d2charlist* ccharlist;
elist_for_each_safe_rev(curr,&charlist_head,safe)
{
ccharlist = elist_entry(curr,t_d2charlist,list);
packet_append_string(rpacket,(char*)ccharlist->charinfo->header.charname);
packet_append_string(rpacket,(char *)&ccharlist->charinfo->portrait);
xfree((void *)ccharlist->charinfo);
xfree((void *)ccharlist);
elist_for_each_safe_rev(curr, &charlist_head, safe)
{
ccharlist = elist_entry(curr, t_d2charlist, list);
packet_append_string(rpacket, (char*)ccharlist->charinfo->header.charname);
packet_append_string(rpacket, (char*)&ccharlist->charinfo->portrait);
xfree((void*)ccharlist->charinfo);
xfree((void*)ccharlist);
}
}
}
retry = false;
}
catch (const Directory::OpenError&) {
ERROR1("(*{}) charinfo directory do not exist, building it", account);
if (p_mkdir(path, S_IRWXU) == 0)
{
INFO1("Successfully created charinfo directory ({})", path);
}
else
{
ERROR2("Failed to create charinfo directory ({}), errno = {}", path, errno);
retry = false;
bn_short_set(&rpacket->u.d2cs_client_charlistreply.maxchar, 0);
}
}
} catch(const Directory::OpenError&) {
INFO1("(*{}) charinfo directory do not exist, building it",account);
p_mkdir(path,S_IRWXU);
}
bn_short_set(&rpacket->u.d2cs_client_charlistreply.currchar,n);
bn_short_set(&rpacket->u.d2cs_client_charlistreply.currchar2,n);
@ -953,70 +970,87 @@ static int on_client_charlistreq_110(t_connection * c, t_packet * packet)
packet_set_type(rpacket,D2CS_CLIENT_CHARLISTREPLY_110);
bn_short_set(&rpacket->u.d2cs_client_charlistreply_110.u1,0);
n=0;
try {
Directory dir(path);
bool retry = true;
while (retry)
{
try {
Directory dir(path);
exp_time = prefs_get_char_expire_time();
while ((charname=dir.read())) {
charinfo = (t_d2charinfo_file*)xmalloc(sizeof(t_d2charinfo_file));
if (d2charinfo_load(account,charname,charinfo)<0) {
eventlog(eventlog_level_error,__FUNCTION__,"error loading charinfo for {}(*{})",charname,account);
xfree(charinfo);
continue;
exp_time = prefs_get_char_expire_time();
while ((charname = dir.read())) {
charinfo = (t_d2charinfo_file*)xmalloc(sizeof(t_d2charinfo_file));
if (d2charinfo_load(account, charname, charinfo) < 0) {
eventlog(eventlog_level_error, __FUNCTION__, "error loading charinfo for {}(*{})", charname, account);
xfree(charinfo);
continue;
}
if (exp_time) {
curr_exp_time = bn_int_get(charinfo->header.last_time) + exp_time;
}
else {
curr_exp_time = 0x7FFFFFFF;
}
eventlog(eventlog_level_debug, __FUNCTION__, "adding char {} (*{})", charname, account);
d2charlist_add_char(&charlist_head, charinfo, curr_exp_time);
n++;
if (n >= maxchar) break;
}
if (exp_time) {
curr_exp_time = bn_int_get(charinfo->header.last_time)+exp_time;
} else {
curr_exp_time = 0x7FFFFFFF;
if (n >= maxchar)
maxchar = 0;
if (!std::strcmp(charlist_sort_order, "ASC"))
{
t_elist* curr, * safe;
t_d2charlist* ccharlist;
elist_for_each_safe(curr, &charlist_head, safe)
{
bn_int bn_exp_time;
ccharlist = elist_entry(curr, t_d2charlist, list);
bn_int_set(&bn_exp_time, ccharlist->expiration_time);
packet_append_data(rpacket, bn_exp_time, sizeof(bn_exp_time));
packet_append_string(rpacket, (char*)ccharlist->charinfo->header.charname);
packet_append_string(rpacket, (char*)&ccharlist->charinfo->portrait);
xfree((void*)ccharlist->charinfo);
xfree((void*)ccharlist);
}
}
eventlog(eventlog_level_debug,__FUNCTION__,"adding char {} (*{})", charname, account);
d2charlist_add_char(&charlist_head,charinfo,curr_exp_time);
n++;
if (n>=maxchar) break;
else
{
t_elist* curr, * safe;
t_d2charlist* ccharlist;
elist_for_each_safe_rev(curr, &charlist_head, safe)
{
bn_int bn_exp_time;
ccharlist = elist_entry(curr, t_d2charlist, list);
bn_int_set(&bn_exp_time, ccharlist->expiration_time);
packet_append_data(rpacket, bn_exp_time, sizeof(bn_exp_time));
packet_append_string(rpacket, (char*)ccharlist->charinfo->header.charname);
packet_append_string(rpacket, (char*)&ccharlist->charinfo->portrait);
xfree((void*)ccharlist->charinfo);
xfree((void*)ccharlist);
}
}
retry = false;
}
if (n>=maxchar)
maxchar = 0;
if (!std::strcmp(charlist_sort_order, "ASC"))
{
t_elist * curr, *safe;
t_d2charlist * ccharlist;
elist_for_each_safe(curr,&charlist_head,safe)
{
bn_int bn_exp_time;
ccharlist = elist_entry(curr,t_d2charlist,list);
bn_int_set(&bn_exp_time,ccharlist->expiration_time);
packet_append_data(rpacket,bn_exp_time,sizeof(bn_exp_time));
packet_append_string(rpacket,(char*)ccharlist->charinfo->header.charname);
packet_append_string(rpacket,(char *)&ccharlist->charinfo->portrait);
xfree((void *)ccharlist->charinfo);
xfree((void *)ccharlist);
}
catch (const Directory::OpenError&) {
ERROR1("(*{}) charinfo directory do not exist, building it", account);
if (p_mkdir(path, S_IRWXU) == 0)
{
INFO1("Successfully created charinfo directory ({})", path);
}
else
{
ERROR2("Failed to create charinfo directory ({}), errno = {}", path, errno);
retry = false;
}
}
else
{
t_elist * curr, *safe;
t_d2charlist * ccharlist;
elist_for_each_safe_rev(curr,&charlist_head,safe)
{
bn_int bn_exp_time;
ccharlist = elist_entry(curr,t_d2charlist,list);
bn_int_set(&bn_exp_time,ccharlist->expiration_time);
packet_append_data(rpacket,bn_exp_time,sizeof(bn_exp_time));
packet_append_string(rpacket,(char*)ccharlist->charinfo->header.charname);
packet_append_string(rpacket,(char *)&ccharlist->charinfo->portrait);
xfree((void *)ccharlist->charinfo);
xfree((void *)ccharlist);
}
}
} catch (const Directory::OpenError&) {
INFO1("(*{}) charinfo directory do not exist, building it",account);
p_mkdir(path,S_IRWXU);
}
bn_short_set(&rpacket->u.d2cs_client_charlistreply.currchar,n);
bn_short_set(&rpacket->u.d2cs_client_charlistreply.currchar2,n);
bn_short_set(&rpacket->u.d2cs_client_charlistreply.maxchar,maxchar);

View file

@ -1,5 +1,15 @@
#include "console_resource.h"
#define APSTUDIO_READONLY_SYMBOLS
#ifndef __BORLANDC__
#ifdef __AFXRES_H__
#include "afxres.h"
#else
#include "winres.h"
#endif
#endif
/* Icon */
ID_ICON1 ICON DISCARDABLE "win32/logo01.ico"

View file

@ -17,13 +17,9 @@
#ifdef WIN32
#include <cstring>
#include <cwchar>
#include <string>
#include <vector>
#include <windows.h>
#ifndef WINADVAPI
#if !defined(WINADVAPI)
#if !defined(_ADVAPI32_)
#define WINADVAPI DECLSPEC_IMPORT
#else
@ -38,100 +34,72 @@ extern char serviceDescription[];
extern int g_ServiceStatus;
#ifdef WIN32_GUI
extern int app_main(int argc, char ** argv);
extern int app_main(int argc, char** argv);
#else
extern int main(int argc, char ** argv);
extern int main(int argc, char** argv);
#endif
SERVICE_STATUS serviceStatus;
SERVICE_STATUS_HANDLE serviceStatusHandle = 0;
typedef WINADVAPI BOOL(WINAPI *CSD_T)(SC_HANDLE hService, DWORD dwInfoLevel, LPVOID lpInfo);
typedef WINADVAPI BOOL(WINAPI* CSD_T)(SC_HANDLE, DWORD, LPCVOID);
void Win32_ServiceInstall()
{
SC_HANDLE serviceControlManager = OpenSCManagerW(nullptr, nullptr, SC_MANAGER_CREATE_SERVICE);
if (!serviceControlManager)
{
return;
}
SERVICE_DESCRIPTIONA sdBuf;
CSD_T ChangeServiceDescription;
HMODULE advapi32;
SC_HANDLE serviceControlManager = OpenSCManagerA(0, 0, SC_MANAGER_CREATE_SERVICE);
wchar_t path[MAX_PATH + 10] = {};
if (GetModuleFileNameW(nullptr, path, sizeof path / sizeof *path) != 0)
if (serviceControlManager)
{
return;
}
char path[_MAX_PATH + 10];
if (GetModuleFileNameA(0, path, sizeof(path) / sizeof(path[0])) > 0)
{
SC_HANDLE service;
std::strcat(path, " --service");
service = CreateServiceA(serviceControlManager,
serviceName, serviceLongName,
SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS,
SERVICE_AUTO_START, SERVICE_ERROR_IGNORE, path,
0, 0, 0, 0, 0);
if (service)
{
sdBuf.lpDescription = serviceDescription;
std::wcscat(path, L"--service");
if (!(advapi32 = GetModuleHandleA("ADVAPI32.DLL")))
{
CloseServiceHandle(service);
CloseServiceHandle(serviceControlManager);
return;
}
auto utf8_decode = [](const std::string& str)
{
if (str.empty())
return std::wstring();
int size_needed = MultiByteToWideChar(CP_UTF8, 0, &str[0], (int)str.size(), NULL, 0);
std::wstring wstrTo(size_needed, 0);
MultiByteToWideChar(CP_UTF8, 0, &str[0], (int)str.size(), &wstrTo[0], size_needed);
return wstrTo;
};
if (!(ChangeServiceDescription = (CSD_T)GetProcAddress(advapi32, "ChangeServiceConfig2A")))
{
CloseServiceHandle(service);
CloseServiceHandle(serviceControlManager);
return;
}
SC_HANDLE service = CreateServiceW(serviceControlManager,
utf8_decode(serviceName).c_str(), utf8_decode(serviceLongName).c_str(),
SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS,
SERVICE_AUTO_START, SERVICE_ERROR_IGNORE, path,
0, 0, 0, 0, 0);
if (service == NULL)
{
return;
}
SERVICE_DESCRIPTIONW sdBuf = {};
auto temp = utf8_decode(serviceDescription);
std::vector<wchar_t> buffer(temp.begin(), temp.end());
sdBuf.lpDescription = buffer.data();
HMODULE advapi32 = GetModuleHandleW(L"advapi32.dll");
if (advapi32 == NULL)
{
CloseServiceHandle(service);
ChangeServiceDescription(
service, // handle to service
SERVICE_CONFIG_DESCRIPTION, // change: description
&sdBuf);
CloseServiceHandle(service);
}
}
CloseServiceHandle(serviceControlManager);
return;
}
auto ChangeServiceDescription = reinterpret_cast<CSD_T>(GetProcAddress(advapi32, "ChangeServiceConfig2W"));
if (ChangeServiceDescription == NULL)
{
CloseServiceHandle(service);
CloseServiceHandle(serviceControlManager);
return;
}
ChangeServiceDescription(
service, // handle to service
SERVICE_CONFIG_DESCRIPTION, // change: description
&sdBuf);
CloseServiceHandle(service);
CloseServiceHandle(serviceControlManager);
}
void Win32_ServiceUninstall()
{
SC_HANDLE serviceControlManager = OpenSCManagerW(nullptr, nullptr, SC_MANAGER_CONNECT);
SC_HANDLE serviceControlManager = OpenSCManagerA(0, 0, SC_MANAGER_CONNECT);
if (serviceControlManager)
{
auto utf8_decode = [](const std::string& str)
{
if (str.empty())
return std::wstring();
int size_needed = MultiByteToWideChar(CP_UTF8, 0, &str[0], (int)str.size(), NULL, 0);
std::wstring wstrTo(size_needed, 0);
MultiByteToWideChar(CP_UTF8, 0, &str[0], (int)str.size(), &wstrTo[0], size_needed);
return wstrTo;
};
SC_HANDLE service = OpenServiceW(serviceControlManager,
utf8_decode(serviceName).c_str(), SERVICE_QUERY_STATUS | DELETE);
SC_HANDLE service = OpenServiceA(serviceControlManager,
serviceName, SERVICE_QUERY_STATUS | DELETE);
if (service)
{
SERVICE_STATUS serviceStatus;
@ -201,29 +169,17 @@ void WINAPI ServiceMain(DWORD argc, char* argv[])
serviceStatus.dwCheckPoint = 0;
serviceStatus.dwWaitHint = 0;
auto utf8_decode = [](const std::string& str)
{
if (str.empty())
return std::wstring();
int size_needed = MultiByteToWideChar(CP_UTF8, 0, &str[0], (int)str.size(), NULL, 0);
std::wstring wstrTo(size_needed, 0);
MultiByteToWideChar(CP_UTF8, 0, &str[0], (int)str.size(), &wstrTo[0], size_needed);
return wstrTo;
};
serviceStatusHandle = RegisterServiceCtrlHandlerW(utf8_decode(serviceName).c_str(), ServiceControlHandler);
serviceStatusHandle = RegisterServiceCtrlHandlerA(serviceName, ServiceControlHandler);
if (serviceStatusHandle)
{
wchar_t path[MAX_PATH + 1] = {};
unsigned last_slash = 0;
char path[_MAX_PATH + 1];
unsigned int i, last_slash = 0;
GetModuleFileNameW(0, path, sizeof path / sizeof *path);
GetModuleFileNameA(0, path, sizeof(path) / sizeof(path[0]));
for (std::size_t i = 0; i < std::wcslen(path); i++)
{
if (path[i] == '\\')
last_slash = i;
for (i = 0; i < std::strlen(path); i++) {
if (path[i] == '\\') last_slash = i;
}
path[last_slash] = 0;
@ -233,7 +189,7 @@ void WINAPI ServiceMain(DWORD argc, char* argv[])
SetServiceStatus(serviceStatusHandle, &serviceStatus);
// do initialisation here
SetCurrentDirectoryW(path);
SetCurrentDirectoryA(path);
// running
serviceStatus.dwControlsAccepted |= (SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN);
@ -277,7 +233,9 @@ void Win32_ServiceRun()
{ 0, 0 }
};
StartServiceCtrlDispatcherA(serviceTable);
if (!StartServiceCtrlDispatcherA(serviceTable))
{
}
}
#endif
#endif