Skip to content

Commit

Permalink
Support for multiple games
Browse files Browse the repository at this point in the history
* Supporft for multiple games WIP.

* pylint updates.

* Support for multiple games WIP.

* Requirements update.

* DEM multiplier for FS25.

* Dev scripts update.

* Bot updates for FS25.

* Actions update.
  • Loading branch information
iwatkot authored Nov 12, 2024
1 parent 253eff8 commit ffbae01
Show file tree
Hide file tree
Showing 21 changed files with 696 additions and 259 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/checks.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ name: Tests
on:
push:
branches:
- main
- '**'

jobs:
check:
Expand Down
24 changes: 24 additions & 0 deletions .github/workflows/pypi.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
name: Publish Python Package to PyPI
on:
release:
types: [published]
jobs:
build-and-publish:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Set up Python
uses: actions/setup-python@v2
with:
python-version: '3.11'
- name: Install dependencies
run: |
python -m pip install --upgrade pip
python -m pip install build twine
- name: Build package
run: |
python -m build
- name: Publish package to PyPI
uses: pypa/gh-action-pypi-publish@release/v1
with:
password: ${{ secrets.PYPI_API_TOKEN }}
12 changes: 0 additions & 12 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
@@ -1,18 +1,6 @@
{
"version": "0.2.0",
"configurations": [
{
"name": "Linux / Mac Script",
"type": "python",
"request": "launch",
"program": "maps4fs/ui.py",
"console": "integratedTerminal",
"justMyCode": true,
"env": {
"PYTHONPATH": "${workspaceFolder}:${PYTHONPATH}",
"LOG_LEVEL": "DEBUG",
}
},
{
"name": "Streamlit: webui",
"type": "process",
Expand Down
47 changes: 39 additions & 8 deletions bot/bot.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@
logger = mfs.Logger(__name__, level="DEBUG")

# region constants
GAME_CODES = {
"FS22": "Farming Simulator 22",
"FS25": "Farming Simulator 25",
}
MAP_SIZES = ["2048", "4096", "8192", "16384"]
MAX_HEIGHTS = {
"100": "🍀 For flatlands",
Expand All @@ -29,7 +33,6 @@

# region directories
working_directory = os.getcwd()
map_template = os.path.join(working_directory, "data", "map-template.zip")
maps_directory = os.path.join(working_directory, "maps")
archives_directory = os.path.join(working_directory, "archives")
stats_directory = os.path.join(working_directory, "stats")
Expand Down Expand Up @@ -77,12 +80,13 @@ class Session:
dem_settings (generate.DemSettings): DEM settings.
"""

def __init__(self, telegram_id: int, coordinates: tuple[float, float]):
def __init__(self, telegram_id: int, game_code: str):
self.telegram_id = telegram_id
self.timestamp = int(datetime.now().timestamp())
self.name = f"{self.telegram_id}_{self.timestamp}"
self.map_directory = os.path.join(maps_directory, self.name)
self.coordinates = coordinates
self.game = mfs.Game.from_code(game_code)
self.coordinates = None
self.distance = None
self.max_height = None

Expand All @@ -93,17 +97,17 @@ def run(self) -> tuple[str, str]:
tuple[str, str]: Paths to the preview and the archive.
"""
mp = mfs.Map(
self.game,
self.coordinates,
self.distance,
self.map_directory,
blur_seed=5,
max_height=self.max_height,
map_template=map_template,
logger=logger,
)
mp.generate()
# preview_path = mp.previews()[0]
preview_path = None # Disabled to avoid Docker 137 error (OUT OF MEMORY).
preview_path = None # Disabled to avoid Docker 137 error (OUT OF MEMORY).
archive_path = mp.pack(os.path.join(archives_directory, self.name))
return preview_path, archive_path

Expand Down Expand Up @@ -198,13 +202,38 @@ async def button_coffee(message: types.Message) -> None:

@dp.message_handler(Text(equals=Buttons.GENERATE.value))
async def button_generate(message: types.Message) -> None:
"""Handles the Generate button, registers the coordinates handler.
"""Handles the Generate button, creates inline buttons for the game selection.
Args:
message (types.Message): Message, which triggered the handler.
"""
await log_event(message)

buttons = {}
for game_code, game_name in GAME_CODES.items():
buttons[f"game_code_{game_code}"] = game_name

await bot.send_message(
message.from_user.id,
Messages.CHOOSE_GAME.value,
reply_markup=await keyboard(buttons),
)


@dp.callback_query_handler(text_contains="game_code_")
async def game_choose(message: types.Message) -> None:
"""Handles the catch of the game selection, registers the coordinates handler.
Args:
message (types.Message): Message, which triggered the handler.
"""
await log_event(message)

game_code = message.data.rsplit("_", 1)[-1]

session = Session(message.from_user.id, game_code)
sessions[message.from_user.id] = session

dp.register_message_handler(coordinates)

await bot.send_message(
Expand Down Expand Up @@ -263,8 +292,10 @@ async def coordinates(message: types.Message) -> None:
)
return

telegram_id = message.from_user.id
sessions[telegram_id] = Session(telegram_id, (latitude, longitude))
session = sessions.get(message.from_user.id)
if not session:
return
session.coordinates = (latitude, longitude)

sizes = MAP_SIZES
indicators = ["🟢", "🟢", "🟡", "🔴"]
Expand Down
2 changes: 2 additions & 0 deletions bot/bot_templates.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ class Messages(Enum):

CANCELLED = "The operation has been cancelled."

CHOOSE_GAME = "Choose the game for which you want to generate a map."

ENTER_COORDINATES = (
"Enter the coordinates of the center of the map\."
"The coordinates are latitude and longitude separated by a comma\.\n\n"
Expand Down
File renamed without changes.
96 changes: 96 additions & 0 deletions data/fs22-texture-schema.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
[
{
"name": "animalMud",
"count": 4
},
{
"name": "asphalt",
"count": 4,
"tags": { "highway": ["motorway", "trunk", "primary"] },
"width": 8,
"color": [70, 70, 70]
},
{
"name": "cobbleStone",
"count": 4
},
{
"name": "concrete",
"count": 4,
"tags": { "building": "true" },
"width": 8,
"color": [130, 130, 130]
},
{
"name": "concreteRubble",
"count": 4
},
{
"name": "concreteTiles",
"count": 4
},
{
"name": "dirt",
"count": 4
},
{
"name": "dirtDark",
"count": 2,
"tags": { "highway": ["unclassified", "residential", "track"] },
"width": 2,
"color": [33, 67, 101]
},
{
"name": "forestGround",
"count": 4,
"tags": { "landuse": "farmland" },
"color": [47, 107, 85]
},
{
"name": "forestGroundLeaves",
"count": 4
},
{
"name": "grass",
"count": 4,
"tags": { "natural": "grassland" },
"color": [34, 255, 34]
},
{
"name": "grassDirt",
"count": 4,
"tags": { "natural": ["wood", "tree_row"] },
"width": 2,
"color": [0, 252, 124]
},
{
"name": "gravel",
"count": 4,
"tags": { "highway": ["secondary", "tertiary", "road"] },
"width": 4,
"color": [140, 180, 210]
},
{
"name": "groundBricks",
"count": 4
},
{
"name": "mountainRock",
"count": 4
},
{
"name": "mountainRockDark",
"count": 4
},
{
"name": "riverMud",
"count": 4
},
{
"name": "waterPuddle",
"count": 0,
"tags": { "natural": "water", "waterway": "true" },
"width": 10,
"color": [255, 20, 20]
}
]
2 changes: 1 addition & 1 deletion dev/clean_trash.sh
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#!/bin/sh

# Directories to be removed
dirs=".mypy_cache .pytest_cache htmlcov dist"
dirs=".mypy_cache .pytest_cache htmlcov dist archives cache logs maps temp"

# Files to be removed
files=".coverage"
Expand Down
2 changes: 1 addition & 1 deletion dev/requirements.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
opencv-python
osmnx
osmnx<2.0.0
rasterio
python_dotenv
aiogram==2.25.1
Expand Down
2 changes: 1 addition & 1 deletion docker/requirements_bot.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
opencv-python
osmnx
osmnx<2.0.0
rasterio
python_dotenv
aiogram==2.25.1
Expand Down
2 changes: 1 addition & 1 deletion docker/requirements_webui.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
opencv-python
osmnx
osmnx<2.0.0
rasterio
streamlit
tqdm
1 change: 1 addition & 0 deletions maps4fs/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
# pylint: disable=missing-module-docstring
from maps4fs.generator.game import Game
from maps4fs.generator.map import Map
from maps4fs.logger import Logger
22 changes: 20 additions & 2 deletions maps4fs/generator/component.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
"""This module contains the base class for all map generation components."""

from typing import Any
from __future__ import annotations

from typing import TYPE_CHECKING, Any

if TYPE_CHECKING:
from maps4fs.generator.game import Game


# pylint: disable=R0801, R0903
Expand All @@ -17,16 +22,29 @@ class Component:

def __init__(
self,
game: Game,
coordinates: tuple[float, float],
distance: int,
map_directory: str,
logger: Any = None,
**kwargs, # pylint: disable=W0613
**kwargs, # pylint: disable=W0613, R0913, R0917
):
self.game = game
self.coordinates = coordinates
self.distance = distance
self.map_directory = map_directory
self.logger = logger
self.kwargs = kwargs

self.preprocess()

def preprocess(self) -> None:
"""Prepares the component for processing. Must be implemented in the child class.
Raises:
NotImplementedError: If the method is not implemented in the child class.
"""
raise NotImplementedError

def process(self) -> None:
"""Launches the component processing. Must be implemented in the child class.
Expand Down
16 changes: 5 additions & 11 deletions maps4fs/generator/config.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
"""This module contains the Config class for map settings and configuration."""

from __future__ import annotations

import os
from typing import Any
from xml.etree import ElementTree as ET

from maps4fs.generator.component import Component
Expand All @@ -19,16 +20,9 @@ class Config(Component):
info, warning. If not provided, default logging will be used.
"""

def __init__(
self,
coordinates: tuple[float, float],
distance: int,
map_directory: str,
logger: Any = None,
**kwargs,
):
super().__init__(coordinates, distance, map_directory, logger)
self._map_xml_path = os.path.join(self.map_directory, "maps", "map", "map.xml")
def preprocess(self) -> None:
self._map_xml_path = self.game.map_xml_path(self.map_directory)
self.logger.debug(f"Map XML path: {self._map_xml_path}")

def process(self):
self._set_map_size()
Expand Down
Loading

0 comments on commit ffbae01

Please sign in to comment.