From 7a4908e972a1ce842bec74e56c0158dc48cb857b Mon Sep 17 00:00:00 2001 From: cclecle Date: Sun, 8 May 2022 17:19:48 +0200 Subject: [PATCH] first commit --- Help/XServerQuery_ReadMe.txt | 227 +++++++++++++++++++++++++++++++++++ Readme.md | 3 + Run.sh | 91 ++++++++++++++ System/XServerQuery.u | Bin 0 -> 51408 bytes 4 files changed, 321 insertions(+) create mode 100644 Help/XServerQuery_ReadMe.txt create mode 100644 Readme.md create mode 100644 Run.sh create mode 100644 System/XServerQuery.u diff --git a/Help/XServerQuery_ReadMe.txt b/Help/XServerQuery_ReadMe.txt new file mode 100644 index 0000000..8279872 --- /dev/null +++ b/Help/XServerQuery_ReadMe.txt @@ -0,0 +1,227 @@ +Modname: XServerQuery +Version: 2.1.1 +Release date: 24. january 2022 +Autor: (G)ott + + + +Index: +------ +1. what is it? +2. Installation +3. Update +4. Settings +5. Changelog +6. Thanks + + + +1. What is it: +-------------- + +XServerQuery is a much-improved way of showing your server's current +information. There are new headings like "Spectators" and "Protection +Type" as well as the country of the current players. It also does more +then the same job like SecureValidate. + +To show you your server's new information, you need the latest +XBrowser for the UT installation. Remember: XServerQuery is for the +server, XBrowser is for the client. They work together to bring you +all this new information. Also, if you using a server viewer page +(like statistics displayed on a webpage), you need to modify it. + +For more information and to see how it works, follow this link: +http://wiki.beyondunreal.com/XServerQuery + +If you find bugs, strange log entries or you have feedback, ideas or +anything else.. Support pages are unrealadmin.org and UT99.org + +-> https://unrealadmin.org/forums/showthread.php?t=30595 +-> https://ut99.org/viewtopic.php?t=3284 + + +2. Installation: +---------------- + +- Extract the XServerQuery.u file to your Server's System directory. + +- Stop your Server. + +- Open your server's UnrealTournament.ini and then locate this +line in the ServerActors. When you do simply add a ';' at the front, so +your line looks like this: + +;ServerActors=IpServer.UdpServerQuery +;ServerActors=IpServer.UdpServerUplink MasterServerAddress=utmaster.epicgames.com MasterServerPort=27900 +;ServerActors=IpServer.UdpServerUplink MasterServerAddress=unreal.epicgames.com MasterServerPort=27900 + + +- If you have SecureValidate installed: + +;ServerActors=SecureValidate.SVUdpServerQuery +;ServerActors=SecureValidate.SVUdpServerUplink MasterServerAddress=utmaster.epicgames.com MasterServerPort=27900 +;ServerActors=SecureValidate.SVUdpServerUplink MasterServerAddress=unreal.epicgames.com MasterServerPort=27900 + + +- Now add the following new actors to your ServerActors list: + +ServerActors=XServerQuery.XServerQuery +ServerActors=XServerQuery.XServerUplink MasterServerAddress=utmaster.epicgames.com MasterServerPort=27900 +ServerActors=XServerQuery.XServerUplink MasterServerAddress=333networks.com MasterServerPort=27900 +ServerActors=XServerQuery.XServerUplink MasterServerAddress=unreal.epicgames.com MasterServerPort=27900 + +- Now you have two options, choose one of them: + +- a) Start and stop your server for short time. This will auto install default + settings in your server's UnrealTournament.ini. + +- b) Add the following lines at the end of your server's UnrealTournament.ini: + +[XServerQuery.XServerQuery] +netAddress= +homepage=www.example-hp.com +bSendMailURL=false +bShowProtection=hidden +bShowSpectators=true +bShowPlayerCountry=true +iMaxConnPerIPPerSec=2 +iNumPacketsBeforBlock=8 +iNumSecToBlockIP=5 +bLogSpecialQuerys=true +bLogUnknownQuerys=true +bShowTimeStamp=true +bShowAdvancedTimeStamp=false + + +- Change the settings as you want them. + +- If you want to use IpToCountry to show the current country of the players +and server, then you need to install IpToCountry from the included .zip file. +If you already are running IpToCountry then you are fine. + +- Save your server's UnrealTournament.ini and restart your Server as usual. + + + +3. Update: +---------- + +- Stop your Server. + +- Overwrite the XServerQuery.u in your Server's System directory with the new one +in this zip file. + +- Update your settings as you want them (4. Settings). + +- NOTE: "iNumPacketsBeforLog" dosn't exist anymore. Rename it to "iNumPacketsBeforBlock". + +- Save your server's UnrealTournament.ini and restart your Server as usual. + + + +4. Settings: +------------ + +netAddress // This is optional and will only needed if the server don't returns + the real networkaddress for ITC. + // Server will auto set IP if found. +homepage // Returns your homepage if set. Adding "http://" or "https://" in front + of your page will enable the link function in XBrowser for it. +bSendMailURL // If true XSQ will send the admin e-mail with "mailto:" in front and + will enable the link function in XBrowser for it. +bShowProtection // Valid values are "true", "hidden" and something else mean "false". Its dependent on ACE! + // (if ACE is installed) e.g. hidden returns "ACE"; true returns "ACEv1.2f" +bShowSpectators // Spectator informations will send, if your server allows spectators. + False will hide spectators on the player list. +bShowPlayerCountry // Allow sending the players country, if IPtoCountry is installed. +iMaxConnPerIPPerSec // Spam security. How many requests can a client send per second. 2 is the minimum. +iNumPacketsBeforBlock // Spam security. After how many requests the server will block a client. 1 is the minimum. +iNumSecToBlockIP // Spam security. How many seconds before the server stops blocking a client. +bLogSpecialQuerys // Log query errors and 'secure' querys. +bLogUnknownQuerys // Log unknown querys. +bShowTimeStamp // Adds the time to the log. +bShowAdvancedTimeStamp // Additionally adds the date and milliseconds to the log (bShowTimeStamp must be true). + + +6. Changelog: +------------- + +from 210 to 211 +- fixed server will not shown, when ACE is installed and bShowProtection=true. + +from 201 to 210 +- added optional timestamp log. +- added config bShowTimeStamp & bShowAdvancedTimeStamp. +- fixed time check on query request. +- added config iNumSecToBlockIP. +- changed config iNumPacketsBeforLog to iNumPacketsBeforBlock !! +- fixed players country memory. +- removed querytype "NewNet". +- changed config bShowProtection is now by default "hidden". +- changed querytype "Protection" - it has now only focus to ACE. +- some small changes and cleanups. + +from 200 to 201 +- fixed a small bug where the server runs in a small loop and gets a timeout while receiving a unknown querytype. (vanilla servers has the same bug ;) ) +- some minor changes. + +from 110 to 200 +- added query spam security. +- added config iMaxConnPerIPPerSec & iNumPacketsBeforLog. +- changed config bShowProtection to a multi bool. +- removed config bShowCPName. +- removed config ServerCountry. +- renamed config ServerIP to NetAddress. +- added a country memory for players and server. This will stop spamming ItC. +- added "NewNet" as QueryType. If found, return the version. eg.: 0.9 +- changed the player time: the time will now return seconds instead minutes. +- changed "RemainingTime" -> if bOverTime, return ElapsedTime. +- added log prefix. +- renamed class "UdpXServerQuery" to "XServerQuery". +- added new class "XServerUplink". +--> This does the same like SecureValidate.SVUdpServerUplink. +--> changed default MasterServerAddress from master0.gamespy.com to utmaster.epicgames.com. + +from 105 to 110 +- added more info logs. +- added config bLogSpecialQuerys & bLogUnknownQuerys. +- added config ServerCountry (use it if ServerIP not set). +- fixed problem, sending players on nexgen servers befor game is started. +- fixed players time. +- added auto saving default config on first installation. +- some small changes. + +from 104 to 105 +- added crash-protection of Secure Validate. +- added \teams\ as QueryType to support the UT Watcher program. +- added new config "bSendMailURL" (link-support for the new XBrowser > 110). +- renamed "ServerAddress" to "ServerIP". + +from 103 to 104 +- fixed a bug with hidden spectators (part 2). +- fixed problems with server country. +- fixed some minor bugs. + +from 102 to 103 +- fixed a bug with hidden spectators (part 1). + +from 101 to 102 +- added querytype "RemainingTime". +- added UTPure to the protection list. +- fixed a mistake with the querytype "Protaction"/"Protection". +- fixed some minor bugs. + +from 100 to 101 +- added new optional config -> ServerAddress, to bypass a unknown bug with the + servers networkaddress. +- fixed some problems with the country support. + + +6. Thanks: +---------- + +- A big thanks goes to gopostal for creating the readme. +- The Crash-Protection of SecureValidate is working with XSQ. Thanks goes to JustDoIt. +- For the suggestion to add SecureValidate, big thanks to Face. +- Added \teams\ as QueryType to support the UT Watcher program. Thanks goes to El Muerte. +- Last but not least, the UT community. diff --git a/Readme.md b/Readme.md new file mode 100644 index 0000000..2ff9317 --- /dev/null +++ b/Readme.md @@ -0,0 +1,3 @@ +# XServerQuery Release GIT repository + +checkout official release thread: https://ut99.org/viewtopic.php?f=34&t=6061 \ No newline at end of file diff --git a/Run.sh b/Run.sh new file mode 100644 index 0000000..cea1430 --- /dev/null +++ b/Run.sh @@ -0,0 +1,91 @@ +#!/bin/bash + +SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) +OUTPUT_DIR="$2" +CFG_FILE="$3" +DEFAULT_CFG_FILE=UnrealTournament.ini + + +function install() { + cp $SCRIPT_DIR/Help $OUTPUT_DIR/Help -Rf + cp $SCRIPT_DIR/System $OUTPUT_DIR/System -Rf + + echo install ok +} + +function enable() { + # Warning: ugly hack with sed to allow multiple key instances + #crudini --set $OUTPUT_DIR/System/$CFG_FILE 'Engine.GameEngine' _ServerPackages $SSBBaseName + #sed -i 's/_ServerPackages/ServerPackages/g' $OUTPUT_DIR/System/$CFG_FILE + #crudini --set $OUTPUT_DIR/System/$CFG_FILE 'Engine.GameEngine' _ServerActors $SSBBaseName.SmartSBServerActor + #sed -i 's/_ServerActors/ServerActors/g' $OUTPUT_DIR/System/$CFG_FILE + # TODO + + echo enable ok +} + +function disable() { + #sed -i "/ServerPackages[[:space:]]*=[[:space:]]*$SSBBaseName/d" $OUTPUT_DIR/System/$CFG_FILE + #sed -i "/ServerPackages[[:space:]]*=[[:space:]]*SmartSBStats/d" $OUTPUT_DIR/System/$CFG_FILE + #sed -i "/ServerActors[[:space:]]*=[[:space:]]*$SSBBaseName.SmartSBServerActor/d" $OUTPUT_DIR/System/$CFG_FILE + # TODO + + echo disable ok +} + +function show_help() { + echo + echo "Usage: $0 { install | enable | disable } []" + echo +} + +function check_cfg_file() { + if [ -z ${CFG_FILE} ] + then + echo "CFG_FILE is unset, setting it to $DEFAULT_CFG_FILE" + CFG_FILE=$DEFAULT_CFG_FILE + else + echo "CFG_FILE is set to '$CFG_FILE'" + fi + + if [ ! -f $OUTPUT_DIR/System/$CFG_FILE ] + then + echo "$OUTPUT_DIR/System/$CFG_FILE does not exist" + show_help + exit 9999 # die with error code 9999 + fi +} + +function check_game_dir() { + ### Check if a directory does not exist ### + if [ ! -d $OUTPUT_DIR ] + then + echo "incorrect " + show_help + exit 9999 # die with error code 9999 + fi +} + +case "$1" in + 'install') + check_game_dir + install + ;; + 'enable') + check_game_dir + check_cfg_file + disable + enable + ;; + 'disable') + check_game_dir + check_cfg_file + disable + ;; + *) + show_help + exit 1 + ;; +esac + +exit 0 \ No newline at end of file diff --git a/System/XServerQuery.u b/System/XServerQuery.u new file mode 100644 index 0000000000000000000000000000000000000000..2c52d5c80b7ec8b91ecc7f63cd98451f977ee8a7 GIT binary patch literal 51408 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 literal 0 HcmV?d00001