Skip to content

Commit

Permalink
Merge pull request #36 from agentsofthesystem/develop
Browse files Browse the repository at this point in the history
Refactor files & Add Palworld game support
  • Loading branch information
jreed1701 authored Jan 20, 2024
2 parents b1c65c8 + 4d66164 commit b3407f1
Show file tree
Hide file tree
Showing 43 changed files with 251 additions and 37 deletions.
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@ Here's a short list of some games Agent Smith is currently programmed to manage.

1. 7 Days To Die
2. V-Rising
3. More to come!!!
3. Palworld
4. More to come!!!

# Getting Started

Expand Down
2 changes: 1 addition & 1 deletion agent-smith.spec
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ a = Analysis(
['agent-smith.py'],
pathex=[],
binaries=[],
datas=[('./application/config/nginx/*', './application/config/nginx'), ('./application/gui/resources/agent-white.png', 'u./application/gui/resources'), ('./application/gui/resources/agent-green.png', './application/gui/resources'), ('./application/source/games/*.py', './application/source/games'), ('./application/source/games/resources/*', './application/source/games/resources'), ('./application/source/alembic/alembic.ini', './application/source/alembic'), ('./application/source/alembic/env.py', './application/source/alembic'), ('./application/source/alembic/script.py.mako', './application/source/alembic'), ('./application/source/alembic/versions/*.py', './application/source/alembic/versions')],
datas=[('./application/config/nginx/*', './application/config/nginx'), ('./application/gui/resources/agent-white.png', 'u./application/gui/resources'), ('./application/gui/resources/agent-green.png', './application/gui/resources'), ('./application/games/*.py', './application/games'), ('./application/games/resources/*', './application/games/resources'), ('./application/alembic/alembic.ini', './application/alembic'), ('./application/alembic/env.py', './application/alembic'), ('./application/alembic/script.py.mako', './application/alembic'), ('./application/alembic/versions/*.py', './application/alembic/versions')],
hiddenimports=['xml.etree.ElementTree', 'telnetlib'],
hookspath=[],
hooksconfig={},
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
2 changes: 1 addition & 1 deletion application/api/controllers/games.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from flask import request

from application.common import toolbox
from application.source.models.games import Games
from application.models.games import Games


@staticmethod
Expand Down
4 changes: 2 additions & 2 deletions application/api/v1/blueprints/access.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@
from application.common.decorators import authorization_required
from application.common.exceptions import InvalidUsage
from application.extensions import DATABASE
from application.source.models.settings import Settings
from application.source.models.tokens import Tokens
from application.models.settings import Settings
from application.models.tokens import Tokens

access = Blueprint("access", __name__, url_prefix="/v1")

Expand Down
2 changes: 1 addition & 1 deletion application/api/v1/blueprints/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from flask import Blueprint, jsonify, request
from flask.views import MethodView

from application.source.models.settings import Settings
from application.models.settings import Settings
from application.common import logger
from application.common.decorators import authorization_required
from application.common.exceptions import InvalidUsage
Expand Down
4 changes: 2 additions & 2 deletions application/api/v1/blueprints/game.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@
from application.common.exceptions import InvalidUsage
from application.common.game_base import BaseGame
from application.extensions import DATABASE
from application.source.models.games import Games
from application.source.models.game_arguments import GameArguments
from application.models.games import Games
from application.models.game_arguments import GameArguments

game = Blueprint("game", __name__, url_prefix="/v1")

Expand Down
2 changes: 1 addition & 1 deletion application/api/v1/blueprints/steam.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
from application.common import logger
from application.common.decorators import authorization_required
from application.common.exceptions import InvalidUsage
from application.source.steam_manager import SteamManager
from application.managers.steam_manager import SteamManager

steam = Blueprint("steam", __name__, url_prefix="/v1")

Expand Down
4 changes: 2 additions & 2 deletions application/common/authorization.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
from flask.wrappers import Request

from application.common import constants
from application.source.models.settings import Settings
from application.source.models.tokens import Tokens
from application.models.settings import Settings
from application.models.tokens import Tokens


def _verify_bearer_token(request: Request) -> int:
Expand Down
4 changes: 2 additions & 2 deletions application/common/game_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@
from application.common.game_argument import GameArgument
from application.common.exceptions import InvalidUsage
from application.extensions import DATABASE
from application.source.models.games import Games
from application.source.models.game_arguments import GameArguments
from application.models.games import Games
from application.models.game_arguments import GameArguments


class BaseGame:
Expand Down
2 changes: 1 addition & 1 deletion application/common/toolbox.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
from application.common import logger
from application.common.exceptions import InvalidUsage
from application.common.game_base import BaseGame
from application.source import games
from application import games


@staticmethod
Expand Down
6 changes: 3 additions & 3 deletions application/factory.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,13 @@
from application.api.v1.blueprints.architect import architect
from application.api.v1.blueprints.game import game
from application.api.v1.blueprints.steam import steam
from application.source.models.games import Games
from application.source.models.settings import Settings
from application.models.games import Games
from application.models.settings import Settings

CURRENT_FOLDER = toolbox._get_application_path()
STATIC_FOLDER = os.path.join(CURRENT_FOLDER, "static")
TEMPLATE_FOLDER = os.path.join(CURRENT_FOLDER, "templates")
ALEMBIC_FOLDER = os.path.join(CURRENT_FOLDER, "source", "alembic")
ALEMBIC_FOLDER = os.path.join(CURRENT_FOLDER, "alembic")


def _startup_checks():
Expand Down
2 changes: 2 additions & 0 deletions application/games/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# Intentially import here unused
from application import games # noqa: F401
195 changes: 195 additions & 0 deletions application/games/palworld_game.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,195 @@
import os
import time

from jinja2 import Environment, FileSystemLoader

from application.common import logger, constants
from application.common.game_argument import GameArgument
from application.common.game_base import BaseGame
from application.common.toolbox import _get_proc_by_name, get_resources_dir
from application.extensions import DATABASE
from application.models.games import Games


class PalworldGame(BaseGame):
def __init__(self, defaults_dict: dict = {}) -> None:
super(PalworldGame, self).__init__(defaults_dict)

self._game_name = "palworld"
self._game_pretty_name = "Palworld"
self._game_executable = "PalServer.exe"
self._game_steam_id = "2394010"
self._game_info_url = (
"https://www.gtxgaming.co.uk/palworld-dedicated-server-setup-guide/"
)

# if self._game_default_install_dir:
# default_persistent_data_path = os.path.join(
# self._game_default_install_dir,
# constants.GAME_INSTALL_FOLDER,
# self._game_name,
# )
# else:
# default_persistent_data_path = None

# Add Args here, can update later.
self._add_argument(
GameArgument(
"-ServerName",
value="loverland's place",
required=True,
use_quotes=True,
is_permanent=True,
)
)
self._add_argument(
GameArgument(
"-AdminPasssword",
value="WithGreatPowerComesGreatResponsibility",
required=True,
use_quotes=True,
is_permanent=True,
)
)
self._add_argument(
GameArgument(
"-ServerPassword",
value="teamrocket",
required=True,
use_quotes=True,
is_permanent=True,
)
)
self._add_argument(
GameArgument(
"-MaxPlayers",
value="12",
required=True,
use_quotes=True,
is_permanent=True,
)
)
# Default is 27015
self._add_argument(
GameArgument(
"-serverPort",
value=8211,
required=True,
use_quotes=True,
is_permanent=True,
)
)

def startup(self) -> None:
# Run base class checks
super().startup()

# Format command string.
command = self._game_executable

arguments = self._get_argument_dict()

logger.debug("************************************")
logger.debug(arguments)
logger.debug("************************************")

# Create a formatted batch file.
env = Environment(loader=FileSystemLoader(get_resources_dir(__file__)))

bat_template = env.get_template("start_palworld_server_template.bat.j2")
output_from_parsed_bat_template = bat_template.render(
GAME_STEAM_ID=self._game_steam_id,
GAME_NAME=self._game_name,
GAME_COMMAND=command,
)

# server_port = arguments['-serverPort']

ini_template = env.get_template("DefaultPalWorldSettings.ini.j2")
output_from_parsed_ini_template = ini_template.render(
PUBLIC_PORT=arguments["-serverPort"]._value,
SERVER_NAME=arguments["-ServerName"]._value,
MAX_PLAYER_COUNT=arguments["-MaxPlayers"]._value,
ADMIN_PASSWORD=arguments["-AdminPasssword"]._value,
SERVER_PASSWORD=arguments["-ServerPassword"]._value,
)

# Print the formatted jinja
logger.debug(output_from_parsed_bat_template)
logger.debug(output_from_parsed_ini_template)

# In theory, the software has already check that the game is installed, so no check/guard
# needed.
game_qry = Games.query.filter_by(game_steam_id=self._game_steam_id)
game_obj = game_qry.first()
game_install_dir = game_obj.game_install_dir

# Need game install location to write batch file.
full_path_startup_script = os.path.join(
game_install_dir, constants.STARTUP_BATCH_FILE_NAME
)

full_path_game_ini_config = os.path.join(
game_install_dir,
"Pal",
"Saved",
"Config",
"WindowsServer",
"PalWorldSettings.ini",
)

# If file exists, remove it.
if os.path.exists(full_path_startup_script):
os.remove(full_path_startup_script)
if os.path.exists(full_path_game_ini_config):
os.remove(full_path_game_ini_config)

# Write the batch file.
with open(full_path_startup_script, "w") as myfile:
myfile.write(output_from_parsed_bat_template)

with open(full_path_game_ini_config, "w") as myfile:
myfile.write(output_from_parsed_ini_template)

# Call the batch file on another process as to not block this one.
command = f'START /MIN CMD.EXE /C "{full_path_startup_script}"'
result = self._run_game(command, game_install_dir)

time.sleep(1)

process = _get_proc_by_name(self._game_executable)

logger.info(result)
logger.info("Process:")
logger.info(process)

update_dict = {"game_pid": int(process.pid)}

game_qry.update(update_dict)
DATABASE.session.commit()

def shutdown(self) -> None:
game_qry = Games.query.filter_by(game_steam_id=self._game_steam_id)
game_obj = game_qry.first()
game_pid = game_obj.game_pid

process = _get_proc_by_name(self._game_executable)

if process:
logger.info(process)
logger.info(game_pid)

process.terminate()
process.wait()

update_dict = {"game_pid": None}
game_qry.update(update_dict)
DATABASE.session.commit()

# Pal server throws in an extra executable that needs to be shutdown.
process = _get_proc_by_name("PalServer-Win64-Test-Cmd.exe")

if process:
logger.info(process)
process.terminate()
process.wait()
7 changes: 7 additions & 0 deletions application/games/resources/DefaultPalWorldSettings.ini.j2
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
; This configuration file is a sample of the default server settings.
; Changes to this file will NOT be reflected on the server.
; To change the server settings, modify Pal/Saved/Config/WindowsServer/PalWorldSettings.ini.
[/Script/Pal.PalGameWorldSettings]
OptionSettings=(Difficulty=None,DayTimeSpeedRate=1.000000,NightTimeSpeedRate=1.000000,ExpRate=1.000000,PalCaptureRate=1.000000,PalSpawnNumRate=1.000000,PalDamageRateAttack=1.000000,PalDamageRateDefense=1.000000,PlayerDamageRateAttack=1.000000,PlayerDamageRateDefense=1.000000,PlayerStomachDecreaceRate=1.000000,PlayerStaminaDecreaceRate=1.000000,PlayerAutoHPRegeneRate=1.000000,PlayerAutoHpRegeneRateInSleep=1.000000,PalStomachDecreaceRate=1.000000,PalStaminaDecreaceRate=1.000000,PalAutoHPRegeneRate=1.000000,PalAutoHpRegeneRateInSleep=1.000000,BuildObjectDamageRate=1.000000,BuildObjectDeteriorationDamageRate=1.000000,CollectionDropRate=1.000000,CollectionObjectHpRate=1.000000,CollectionObjectRespawnSpeedRate=1.000000,EnemyDropItemRate=1.000000,DeathPenalty=All,bEnablePlayerToPlayerDamage=False,bEnableFriendlyFire=False,bEnableInvaderEnemy=True,bActiveUNKO=False,bEnableAimAssistPad=True,bEnableAimAssistKeyboard=False,DropItemMaxNum=3000,DropItemMaxNum_UNKO=100,BaseCampMaxNum=128,BaseCampWorkerMaxNum=15,DropItemAliveMaxHours=1.000000,bAutoResetGuildNoOnlinePlayers=False,AutoResetGuildTimeNoOnlinePlayers=72.000000,GuildPlayerMaxNum=20,PalEggDefaultHatchingTime=72.000000,WorkSpeedRate=1.000000,bIsMultiplay=False,bIsPvP=False,bCanPickupOtherGuildDeathPenaltyDrop=False,bEnableNonLoginPenalty=True,bEnableFastTravel=True,bIsStartLocationSelectByMap=True,bExistPlayerAfterLogout=False,bEnableDefenseOtherGuildPlayer=False,CoopPlayerMaxNum={{MAX_PLAYER_COUNT}},ServerPlayerMaxNum={{MAX_PLAYER_COUNT}},ServerName="{{SERVER_NAME}}",ServerDescription="",AdminPassword="{{ADMIN_PASSWORD}}",ServerPassword="{{SERVER_PASSWORD}}",PublicPort={{PUBLIC_PORT}},PublicIP="",RCONEnabled=False,RCONPort=25575,Region="",bUseAuth=True,BanListURL="https://api.palworldgame.com/api/banlist.txt")


Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
@echo off
set SteamAppId={{GAME_STEAM_ID}}
echo "Starting {{GAME_NAME}} Dedicated Server - PRESS CTRL-C to exit"

@echo on
{{GAME_COMMAND}}
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
from application.common.game_base import BaseGame
from application.common.toolbox import _get_proc_by_name, get_resources_dir
from application.extensions import DATABASE
from application.source.models.games import Games
from application.models.games import Games


class SevenDaysToDieGame(BaseGame):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
from application.common.game_base import BaseGame
from application.common.toolbox import _get_proc_by_name, get_resources_dir
from application.extensions import DATABASE
from application.source.models.games import Games
from application.models.games import Games


class VrisingGame(BaseGame):
Expand Down
2 changes: 1 addition & 1 deletion application/gui/globals.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

from application.gui.intalled_games_menu import InstalledGameMenu
from application.gui.widgets.add_argument_widget import AddArgumentWidget
from application.source.nginx_manager import NginxManager
from application.managers.nginx_manager import NginxManager
from operator_client import Operator


Expand Down
2 changes: 1 addition & 1 deletion application/gui/intalled_games_menu.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from PyQt5.QtWidgets import QMenu, QWidget, QWidgetAction, QPushButton

from application.common import toolbox, logger
from application.source import games
from application import games
from operator_client import Operator

BACKGROUND_STR = "background-color: {color}; padding: 8 8 8 8px;"
Expand Down
2 changes: 1 addition & 1 deletion application/gui/launch.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
from application.gui.intalled_games_menu import InstalledGameMenu
from application.gui.widgets.add_argument_widget import AddArgumentWidget
from application.gui.widgets.settings_widget import SettingsWidget
from application.source.nginx_manager import NginxManager
from application.managers.nginx_manager import NginxManager
from application.factory import create_app
from operator_client import Operator

Expand Down
2 changes: 1 addition & 1 deletion application/gui/widgets/game_manager_widget.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@

from application.common import toolbox, logger
from application.common.game_base import BaseGame
from application.source import games
from application import games
from application.gui.widgets.add_argument_widget import AddArgumentWidget
from application.gui.intalled_games_menu import InstalledGameMenu
from application.gui.widgets.game_arguments_widget import GameArgumentsWidget
Expand Down
2 changes: 1 addition & 1 deletion application/gui/widgets/new_game_widget.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
from application.gui.globals import GuiGlobals
from application.gui.widgets.file_select_widget import FileSelectWidget
from application.gui.widgets.game_arguments_widget import GameArgumentsWidget
from application.source import games
from application import games


class NewGameWidget(QWidget):
Expand Down
Loading

0 comments on commit b3407f1

Please sign in to comment.