Open gmodmurderserver opened 2 years ago
Great question!
I'm afraid it's a bit complicated. Our webserver setup is a proprietary system that lets us interact with our game servers from a web address.
If you wanted to mimic the web server portion for a specific server, ultimately you'll need a public endpoint that returns a json payload in the format of: { "server-is-up": true/false }
.
One way of accomplishing this is using a language that has an rcon
library available. You can use the rcon
library to send a simple status
command to your server, and if it replies, you can respond to the API caller with { "server-is-up": true }
, if it times out or errors, you can respond with { "server-is-up": false }
Here's a simple (probably functional?) proof-of-concept:
# rcon_interface.py
# be sure to set the RCON_IP, RCON_PORT, and RCON_PASSWORD environment variables
import os
import valve.rcon
class RCONInterface:
def __init__(self):
self.set_rcon_credentials()
def set_rcon_credentials(self):
self.address = os.getenv("RCON_IP")
self.port = os.getenv("RCON_PORT")
self.password = os.getenv("RCON_PASSWORD")
def issue_command(self, command):
connection_address = (self.address, int(self.port))
try:
with valve.rcon.RCON(connection_address, self.password, timeout=5) as rcon:
response = rcon(command)
print("Rcon response:")
print(response)
if response:
return True, response
except valve.rcon.RCONCommunicationError as socket_err:
print(f"Hit a communication error when trying to issue: '{command}' to '{self.address}:{self.port}'")
print(socket_err)
return False, socket_err
except valve.rcon.RCONTimeoutError as timeout_err:
print(f"Hit a timeout error when trying to issue: '{command}' to '{self.address}:{self.port}'")
print(timeout_err)
return False, timeout_err
except Exception as generic_err:
print(f"Hit an unknown error when trying to issue: '{command}' to '{self.address}:{self.port}'")
return False, generic_err
print("No conditions met, assuming failure?")
return False
# web.py
from rcon_interface.py import RCONInterface
from flask import Flask
import time
app = Flask(__name__)
rcon = RCONInterface()
last_status = True
last_check = 0
@app.route("/ping")
def ping():
# Cache the response for a few seconds so you're not sending tons of rcon requests
if last_check > time.time() - 3:
return { "server-is-up": last_status }
is_up, err_message = rcon.issue_command("status")
last_status = is_up
last_check = time.time()
return { "server-is-up": is_up }
You could deploy this script on the same host as the game server, or you could retrofit it to work in something like Amazon's AWS Lambda. If you know Javascript (or can be bothered to transpile to JS), you could use Cloudflare Workers, too.
Sorry this is a hassle. We had to make a generic solution for all of our game servers, and it's very specific to how we have things set up, so it wasn't made to be nicely shareable.
hmmm, thanks, pretty much all i need it to do is run when the server itself does, and when its detected its up, it could run the restart command, etc
Yeah I suppose you could do that with this web server too.
When you return a server-is-up: false
response, you could also kick off the restart command (you'd have to be 100% sure it doesn't run multiple times though, that'd be a mess)
i tried the python stuff, and it seems to do pretty much nothing when the server restarts or crashes
i can recommend using https://github.com/Yepoleb/python-a2s instead of rcon
im guessing i just replace "valve.rcon" with a2s?
roughly, yeah. you'd only need the web.py part and just run a a2s.info to the server to see if its up, if it times out it isnt
ah right i see, i am pretty new to python and all lol
it can be done with any language has a a2s / rcon library, this is just a rough example
https://files.catbox.moe/or4t5m.png does this look right? lol
no, you'd have to call the a2s function whenever you want to do a info request, check their examples
how does one run a webserver when the server runs, so that this could work properly?