Skip to content

Instantly share code, notes, and snippets.

@eiszfuchs
Last active August 29, 2015 14:22
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save eiszfuchs/a38597bfb2209237a6bf to your computer and use it in GitHub Desktop.
Save eiszfuchs/a38597bfb2209237a6bf to your computer and use it in GitHub Desktop.
import arrow
import os
import shutil
import subprocess
import tarfile
import threading
import time
class Server:
@staticmethod
def echo(message):
message = message.decode('utf-8').strip()
print(message)
return message
def __init__(self, filename, memory_max=1024):
self.filename = filename
self.memory_max = memory_max
self.working_dir = 'survival/'
self.server = None
self.server_started = None
self.server_expectancy = None
def eula(self, accepted=False):
eula_filename = os.path.join(self.working_dir, 'eula.txt')
# fuck yeah legal shit
with open(eula_filename, 'w') as eula_file:
eula_file.write('eula=%s' % 'true' if accepted else 'false')
def setup(self, filename):
setup_filename = os.path.join(self.working_dir, filename)
properties_filename = os.path.join(self.working_dir, 'server.properties')
with open(setup_filename, 'r') as setup_file:
with open(properties_filename, 'w') as properties_file:
properties_file.write(setup_file.read())
def decay(self, minutes_until_decay):
self.server_expectancy = minutes_until_decay
def decay_check(self):
now = arrow.now('local')
uptime_in_minutes = (now - self.server_started).total_seconds() / 60
if uptime_in_minutes > self.server_expectancy:
self.stop()
else:
thread = threading.Timer(10, self.decay_check)
thread.start()
def backup(self):
timestamp = arrow.now('local').format('YYYYMMDDHHmmss')
backup_dir = os.path.join(self.working_dir, '../backup')
backup_filename = os.path.join(backup_dir, 'survival-%s.tar.xz' % timestamp)
# TODO: parse world name from config
world_dir = os.path.join(self.working_dir, 'world')
with tarfile.open(backup_filename, 'w:xz') as tarball:
# bug? using no arcname will add an empty folder named after archive
tarball.add(world_dir, arcname=timestamp)
def reset(self):
dirs = [
'logs/',
'world/',
]
files = [
'eula.txt',
'server.properties',
'usercache.json',
]
for filename in dirs:
shutil.rmtree(os.path.join(self.working_dir, filename))
for filename in files:
os.remove(os.path.join(self.working_dir, filename))
def server_command(self, command):
print(command)
# no end of line at all will not run the command
self.server.stdin.write((command + '\r\n').encode('utf-8'))
self.server.stdin.flush()
def stop(self):
for stop_timeout in [60, 30, 10]:
self.server_command('say Server will stop in %d seconds!' % stop_timeout)
time.sleep(float(stop_timeout))
self.server_command('stop')
def run(self):
command = [
'java',
'-Xms%dM' % 256, # initial Java heap size
'-Xmx%dM' % self.memory_max, # maximum Java heap size
'-jar', self.filename,
'nogui',
]
pipe = subprocess.PIPE
self.server = subprocess.Popen(command, cwd=self.working_dir, stdin=pipe, stdout=pipe, stderr=pipe, bufsize=1)
for line in self.server.stdout:
line = self.echo(line)
if line.find('INFO]: Done (') > -1:
self.on_ready()
self.on_stop()
def on_ready(self):
if self.server_expectancy is not None:
self.server_started = arrow.now('local')
self.decay_check()
def on_stop(self):
self.backup()
survival = Server('../bin/server.jar')
while True:
survival.eula(True)
survival.setup('../bin/survival.properties')
# reset every week:
survival.decay(7 * 24 * 60)
survival.run()
survival.reset()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment