Exemplo n.º 1
0
    def __init__(self, interface: bytes, config_dict: Dict[str, Any]) -> None:
        # logfile path relative to config dir if not abs path
        log_filename = logfile.get()
        if log_filename.strip():  # catches empty filename
            if not os.path.isabs(log_filename):
                log_filename = os.path.join(config.config_dir, log_filename)
            ensure_dir_exists(log_filename)
            if logging_rotate_daily.get():
                logging_file = DailyLogFile(log_filename, '.')
            else:
                logging_file = open(log_filename, 'a')
            predicate = LogLevelFilterPredicate(
                LogLevel.levelWithName(loglevel.get()))
            observers = [
                FilteringLogObserver(textFileLogObserver(sys.stderr),
                                     [predicate]),
                FilteringLogObserver(textFileLogObserver(logging_file),
                                     [predicate])
            ]
            globalLogBeginner.beginLoggingTo(observers)
            log.info('piqueserver started on %s' % time.strftime('%c'))

        self.config = config_dict
        if random_rotation.get():
            self.map_rotator_type = random_choice_cycle
        else:
            self.map_rotator_type = itertools.cycle
        self.default_time_limit = default_time_limit.get()
        self.default_cap_limit = cap_limit.get()
        self.advance_on_win = int(advance_on_win.get())
        self.win_count = itertools.count(1)
        self.bans = NetworkDict()

        # attempt to load a saved bans list
        try:
            with open(os.path.join(config.config_dir, bans_file.get()),
                      'r') as f:
                self.bans.read_list(json.load(f))
            log.debug("loaded {count} bans", count=len(self.bans))
        except FileNotFoundError:
            log.debug("skip loading bans: file unavailable",
                      count=len(self.bans))
        except IOError as e:
            log.error('Could not read bans.txt: {}'.format(e))
        except ValueError as e:
            log.error('Could not parse bans.txt: {}'.format(e))

        self.hard_bans = set()  # possible DDoS'ers are added here
        self.player_memory = deque(maxlen=100)
        if len(self.name) > MAX_SERVER_NAME_SIZE:
            log.warn('(server name too long; it will be truncated to "%s")' %
                     (self.name[:MAX_SERVER_NAME_SIZE]))
        self.respawn_time = respawn_time_option.get()
        self.respawn_waves = respawn_waves.get()

        # since AoS only supports CTF and TC at a protocol level, we need to get
        # the base game mode if we are using a custom game mode.
        game_mode_name = game_mode.get()
        if game_mode_name == 'ctf':
            self.game_mode = CTF_MODE
        elif game_mode.get() == 'tc':
            self.game_mode = TC_MODE
        elif self.game_mode not in [CTF_MODE, TC_MODE]:
            raise ValueError(
                'invalid game mode: custom game mode "{}" does not set '
                'protocol.game_mode to one of TC_MODE or CTF_MODE. Are '
                'you sure the thing you have specified is a game mode?'.format(
                    game_mode_name))

        self.game_mode_name = game_mode.get().split('.')[-1]
        self.team1_name = team1_name.get()[:9]
        self.team2_name = team2_name.get()[:9]
        self.team1_color = tuple(team1_color.get())
        self.team2_color = tuple(team2_color.get())
        self.friendly_fire = friendly_fire.get()
        self.friendly_fire_on_grief = friendly_fire_on_grief.get()
        self.friendly_fire_time = grief_friendly_fire_time.get()
        self.spade_teamkills_on_grief = spade_teamkills_on_grief.get()
        self.fall_damage = fall_damage.get()
        self.teamswitch_interval = teamswitch_interval.get()
        self.teamswitch_allowed = teamswitch_allowed.get()
        self.max_players = max_players.get()
        self.melee_damage = melee_damage.get()
        self.max_connections_per_ip = max_connections_per_ip.get()
        self.passwords = passwords.get()
        self.server_prefix = server_prefix.get()
        self.time_announcements = time_announcements.get()
        self.balanced_teams = balanced_teams.get()
        self.login_retries = login_retries.get()

        # voting configuration
        self.default_ban_time = default_ban_duration.get()

        self.speedhack_detect = speedhack_detect.get()
        self.rubberband_distance = rubberband_distance.get()
        if user_blocks_only.get():
            self.user_blocks = set()
        self.set_god_build = set_god_build.get()
        self.debug_log = debug_log_enabled.get()
        if self.debug_log:
            # TODO: make this configurable
            pyspades.debug.open_debug_log(
                os.path.join(config.config_dir, 'debug.log'))
        if ssh_enabled.get():
            from piqueserver.ssh import RemoteConsole
            self.remote_console = RemoteConsole(self)
        irc = irc_options.get()
        if irc.get('enabled', False):
            from piqueserver.irc import IRCRelay
            self.irc_relay = IRCRelay(self, irc)
        if status_server_enabled.get():
            from piqueserver.statusserver import StatusServer
            self.status_server = StatusServer(self)
            ensureDeferred(self.status_server.listen())
        if ban_publish.get():
            from piqueserver.banpublish import PublishServer
            self.ban_publish = PublishServer(self, ban_publish_port.get())
        if bans_urls.get():
            from piqueserver import bansubscribe
            self.ban_manager = bansubscribe.BanManager(self)
        self.start_time = time.time()
        self.end_calls = []
        # TODO: why is this here?
        create_console(self)

        for user_type, func_names in rights.get().items():
            for func_name in func_names:
                commands.add_rights(user_type, func_name)

        self.port = port_option.get()
        ServerProtocol.__init__(self, self.port, interface)
        self.host.intercept = self.receive_callback

        try:
            self.set_map_rotation(self.config['rotation'])
        except MapNotFound as e:
            log.critical('Invalid map in map rotation (%s), exiting.' % e.map)
            raise SystemExit

        map_load_d = self.advance_rotation()
        # discard the result of the map advance for now
        map_load_d.addCallback(lambda x: self._post_init())

        ip_getter = ip_getter_option.get()
        if ip_getter:
            ensureDeferred(as_deferred(self.get_external_ip(ip_getter)))

        self.new_release = None
        notify_new_releases = config.option("release_notifications",
                                            default=True)
        if notify_new_releases.get():
            ensureDeferred(as_deferred(self.watch_for_releases()))

        self.vacuum_loop = LoopingCall(self.vacuum_bans)
        # Run the vacuum every 6 hours, and kick it off it right now
        self.vacuum_loop.start(60 * 60 * 6, True)

        reactor.addSystemEventTrigger('before', 'shutdown',
                                      lambda: ensureDeferred(self.shutdown()))
Exemplo n.º 2
0
"""
Protects players when they first spawn for a given time

CONFIG SETTING EXAMPLE for 3 seconds of protection
"spawn_protection_time": 3

Script by Rugg
"""
from pyspades.constants import FALL_KILL
from piqueserver.config import config
from twisted.internet import reactor

spawntimer_config = config.option('spawn_protection_time', default=3)


def apply_script(protocol, connection, config):
    class invincibilityConnection(connection):
        invulnerable = True
        spawntimer = None
        protectionTime = spawntimer_config.get()

        def on_shoot_set(self, fire):
            if fire and self.invulnerable:
                self.invulnerable = False
            connection.on_shoot_set(self, fire)

        def on_hit(self, hit_amount, hit_player, kill_type, grenade):
            if hit_player.invulnerable:
                return False
            connection.on_hit(self, hit_amount, hit_player, kill_type, grenade)
Exemplo n.º 3
0

def sleep(secs):
    return deferLater(reactor, secs, lambda: None)


# declare configuration options
bans_config = config.section('bans')
logging_config = config.section('logging')
team1_config = config.section('team1')
team2_config = config.section('team2')

bans_file = bans_config.option('file', default='bans.txt')
bans_urls = bans_config.option('urls', [])
respawn_time_option = config.option('respawn_time',
                                    default="8sec",
                                    cast=cast_duration)
respawn_waves = config.option('respawn_waves', default=False)
game_mode = config.option('game_mode', default='ctf')
random_rotation = config.option('random_rotation', default=False)
passwords = config.option('passwords', default={})
logfile = logging_config.option('logfile', default='./logs/log.txt')
loglevel = logging_config.option('loglevel', default='info')
map_rotation = config.option('rotation',
                             default=['classicgen', 'random'],
                             validate=lambda x: isinstance(x, list))
default_time_limit = config.option('default_time_limit',
                                   default="20min",
                                   cast=lambda x: cast_duration(x) / 60)
cap_limit = config.option('cap_limit',
                          default=10,
Exemplo n.º 4
0
from piqueserver.config import config
from twisted.internet import reactor
from pyspades.constants import FALL_KILL
from twisted.internet.error import AlreadyCalled

sectionConfig = config.section('regen')
regenDelay = sectionConfig.option('regenDelay', default=5.0).get()
healSpeed = sectionConfig.option('healSpeed', default=0.05).get()
healAmount = sectionConfig.option('healAmount', default=1.0).get()

friendly_fire = config.option('friendly_fire', default=True).get()


def apply_script(protocol, connection, config):
    class regenConnection(connection):
        regenCallID = None

        def regen(self):
            if (self.hp is not None):
                connection.set_hp(self,
                                  self.hp + healAmount,
                                  kill_type=FALL_KILL)
                self.regenCallID = reactor.callLater(healSpeed, self.regen)

        def stopRegen(self):
            try:
                self.regenCallID.cancel()
            except AttributeError as aterr:
                pass
            except AlreadyCalled as acerr:
                pass
Exemplo n.º 5
0
from PIL import Image
from io import BytesIO
from aiohttp.abc import AbstractAccessLogger
from twisted.logger import Logger
from piqueserver.utils import as_deferred

from piqueserver.config import config, cast_duration

status_server_config = config.section("status_server")
host_option = status_server_config.option("host", "0.0.0.0")
port_option = status_server_config.option("port", 32886)
logging_option = status_server_config.option("logging", False)
interval_option = status_server_config.option("update_interval",
                                              default="1min",
                                              cast=cast_duration)
scripts_option = config.option("scripts", [])


class AccessLogger(AbstractAccessLogger):
    def log(self, request, response, time):
        self.logger.info(
            "{remote} {method} {url}: {status} {time:0.2f}ms -- {ua}",
            remote=request.remote,
            ua=request.headers["User-Agent"],
            method=request.method,
            url=request.url,
            time=time * 1000,
            status=response.status)


async def set_default_headers(request, response):
Exemplo n.º 6
0
                                MELEE, HIT_TOLERANCE, MELEE_DISTANCE,
                                MELEE_KILL, HEAD, HEADSHOT_KILL, WEAPON_KILL)
from pyspades.team import Team
from pyspades.constants import *
from pyspades.packet import call_packet_handler, register_packet_handler
from pyspades import contained as loaders
from pyspades.collision import vector_collision, collision_3d
from pyspades import world
from pyspades.common import Vertex3, get_color, make_color
from pyspades.weapon import WEAPONS
from pyspades.mapgenerator import ProgressiveMapGenerator
from piqueserver.config import config

log = Logger()
# distance the server tolerates between the place it thinks the client is to where the client actually is.
rubberband_distance = config.option('rubberband_distance', default=10)

set_tool = loaders.SetTool()
block_action = loaders.BlockAction()
position_data = loaders.PositionData()
restock = loaders.Restock()
create_player = loaders.CreatePlayer()
intel_pickup = loaders.IntelPickup()
intel_capture = loaders.IntelCapture()
intel_drop = loaders.IntelDrop()
player_left = loaders.PlayerLeft()
set_hp = loaders.SetHP()
existing_player = loaders.ExistingPlayer()
kill_action = loaders.KillAction()
chat_message = loaders.ChatMessage()
map_data = loaders.MapChunk()
Exemplo n.º 7
0
            seen.add(script)
    if dups:
        log.warn("Scripts included multiple times: {}".format(dups))
        return False
    return True


# declare configuration options
bans_config = config.section('bans')
logging_config = config.section('logging')
team1_config = config.section('team1')
team2_config = config.section('team2')

bans_file = bans_config.option('file', default='bans.txt')
bans_urls = bans_config.option('urls', [])
respawn_time_option = config.option('respawn_time', default=8)
respawn_waves = config.option('respawn_waves', default=False)
game_mode = config.option('game_mode', default='ctf')
random_rotation = config.option('random_rotation', default=False)
passwords = config.option('passwords', default={})
logfile = logging_config.option('logfile', default='./logs/log.txt')
map_rotation = config.option('rotation',
                             default=['classicgen', 'random'],
                             validate=lambda x: isinstance(x, list))
default_time_limit = config.option(
    'default_time_limit',
    default=20,
    validate=lambda x: isinstance(x, (int, float)))
cap_limit = config.option('cap_limit',
                          default=10,
                          validate=lambda x: isinstance(x, (int, float)))
Exemplo n.º 8
0
Gives the player infinite blocks and a given amount of grenades

CONFIG SETTING EXAMPLE for 5 grenades

"starting_grenades": 5,

Script by Rugg
"""
import math
from twisted.internet import reactor
from pyspades.constants import GRENADE_KILL
from pyspades.contained import *
from pyspades.constants import BLOCK_TOOL
from pyspades import contained as loaders
from piqueserver.config import config
grenades_config = config.option('starting_grenades', default = 3)
def apply_script(protocol, connection, config):
	class EnterConnection(connection):
		startinggrenades = grenades_config.get()
		grenadecount = 0
		
		def on_spawn(self, position):
			self.grenadecount = self.startinggrenades
			connection.on_spawn(self, position)

		def on_grenade_thrown(self, grenade):
			self.grenadecount -= 1
			if(self.grenadecount<-4):
				grenade.fuse = 500000
				connection.send_chat(self, "You have thrown too many dud grenades.",global_message = False)
				connection.kill(self)