You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
187 lines
6.2 KiB
187 lines
6.2 KiB
import asyncio
|
|
import json
|
|
import logging
|
|
import pathlib
|
|
from shutil import copyfile
|
|
from types import SimpleNamespace
|
|
from typing import Optional, Union
|
|
|
|
import discord
|
|
from PIL import Image, ImageOps
|
|
from redbot.core import commands
|
|
|
|
from conquest.regioner import ConquestMap, composite_regions
|
|
|
|
log = logging.getLogger("red.fox_v3.conquest.conquestgame")
|
|
|
|
|
|
class ConquestGame:
|
|
ext = "PNG"
|
|
ext_format = "PNG"
|
|
|
|
default_zoom_json = {"enabled": False, "x": -1, "y": -1, "zoom": 1.0}
|
|
|
|
def __init__(self, map_path: pathlib.Path, game_name: str, custom_map_path: pathlib.Path):
|
|
self.source_map = ConquestMap(map_path)
|
|
self.source_map.load_data()
|
|
self.game_name = game_name
|
|
self.current_map_folder = custom_map_path
|
|
|
|
self.settings_json = self.current_map_folder / "settings.json"
|
|
|
|
self.current_filename = f"current.{self.ext}"
|
|
self.current_map = self.current_map_folder / self.current_filename
|
|
|
|
self.zoomed_current_filename = f"current_zoomed.{self.ext}"
|
|
self.zoomed_current_map = self.current_map_folder / self.zoomed_current_filename
|
|
|
|
self.numbered_current_filename = f"current_numbered.{self.ext}"
|
|
self.numbered_current_map = self.current_map_folder / self.numbered_current_filename
|
|
|
|
self.zoomed_numbered_current_filename = f"current_zoomed_numbered.{self.ext}"
|
|
self.zoomed_numbered_current_map = (
|
|
self.current_map_folder / self.zoomed_numbered_current_filename
|
|
)
|
|
|
|
self.region_max = self.source_map.region_max
|
|
|
|
# self.zoom_is_out_of_date = {'current': True, 'blank': True}
|
|
|
|
async def save_region(self, region):
|
|
if not self.custom:
|
|
return False
|
|
pass # TODO: region data saving
|
|
|
|
async def start_game(self):
|
|
if not self.current_map_folder.exists():
|
|
self.current_map_folder.mkdir()
|
|
copyfile(self.source_map.blank_path(), self.current_map)
|
|
|
|
async def resume_game(self, ctx: commands.Context, reset: bool):
|
|
|
|
if not reset and self.current_map.exists():
|
|
await ctx.maybe_send_embed(
|
|
"This map is already in progress, resuming from last game\n"
|
|
"Use `[p]conquest set map [mapname] True` to start a new game"
|
|
)
|
|
else:
|
|
await self.start_game()
|
|
|
|
async def _process_take_regions(self, color, regions):
|
|
im = Image.open(self.current_map)
|
|
|
|
out: Optional[Image.Image] = await composite_regions(
|
|
im,
|
|
regions,
|
|
color,
|
|
self.source_map.masks_path(),
|
|
)
|
|
out.save(self.current_map, self.ext_format) # Overwrite current map with new map
|
|
# self.zoom_is_out_of_date.current = True
|
|
|
|
async def create_numbered_map(self):
|
|
if (
|
|
not self.source_map.numbers_path().exists()
|
|
): # No numbers map, can't add numbers to current
|
|
return self.source_map.numbered_path()
|
|
|
|
current_map = Image.open(self.current_map)
|
|
numbers = Image.open(self.source_map.numbers_path()).convert("L")
|
|
|
|
inverted_map = ImageOps.invert(current_map)
|
|
|
|
loop = asyncio.get_running_loop()
|
|
current_numbered_img = await loop.run_in_executor(
|
|
None, Image.composite, current_map, inverted_map, numbers
|
|
)
|
|
|
|
current_numbered_img.save(self.numbered_current_map, self.ext_format)
|
|
|
|
return self.numbered_current_map
|
|
|
|
async def create_zoomed_map(
|
|
self,
|
|
x,
|
|
y,
|
|
zoom,
|
|
source_map: Union[Image.Image, pathlib.Path],
|
|
target_path: pathlib.Path,
|
|
**kwargs,
|
|
):
|
|
"""Pass out_of_date when created a zoomed map based on something other than the settings json"""
|
|
# if out_of_date:
|
|
# self.zoom_is_out_of_date.current = True
|
|
|
|
# if current_map is None:
|
|
# current_map = Image.open(self.current_map_folder)
|
|
# target_map = self.zoomed_current_map
|
|
|
|
if not isinstance(source_map, Image.Image):
|
|
source_map = Image.open(source_map)
|
|
|
|
w, h = source_map.size
|
|
zoom2 = zoom * 2
|
|
zoomed_map = source_map.crop((x - w / zoom2, y - h / zoom2, x + w / zoom2, y + h / zoom2))
|
|
# zoomed_map = zoomed_map.resize((w, h), Image.LANCZOS)
|
|
zoomed_map.save(target_path, self.ext_format)
|
|
|
|
return True
|
|
|
|
async def get_maybe_zoomed_map(self, version):
|
|
zoom_data = {"enabled": False}
|
|
|
|
if self.settings_json.exists():
|
|
with self.settings_json.open() as zoom_json:
|
|
zoom_data = json.load(zoom_json)
|
|
|
|
if version == "numbered":
|
|
map_path = self.create_numbered_map()
|
|
zoomed_path = self.zoomed_numbered_current_map
|
|
else: # version == "current"
|
|
map_path = self.current_map
|
|
zoomed_path = self.zoomed_current_map
|
|
|
|
if zoom_data["enabled"]: # Send zoomed map instead of current map
|
|
# if self.zoom_is_out_of_date:
|
|
await self.create_zoomed_map(**zoom_data, source_map=map_path, target_map=zoomed_path)
|
|
map_path = zoomed_path
|
|
# self.zoom_is_out_of_date = False
|
|
|
|
return discord.File(fp=map_path) # lol file names
|
|
|
|
async def reset_zoom(self):
|
|
if not self.settings_json.exists():
|
|
return False
|
|
|
|
with self.settings_json.open("w+") as zoom_json:
|
|
json.dump({"enabled": False}, zoom_json, sort_keys=True, indent=4)
|
|
|
|
# self.zoom_is_out_of_date = True
|
|
|
|
return True
|
|
|
|
async def set_zoom(self, x, y, zoom):
|
|
|
|
zoom_data = self.default_zoom_json.copy()
|
|
zoom_data["enabled"] = True
|
|
zoom_data["x"] = x
|
|
zoom_data["y"] = y
|
|
zoom_data["zoom"] = zoom
|
|
|
|
# self.zoom_is_out_of_date = True
|
|
|
|
with self.settings_json.open("w+") as zoom_json:
|
|
json.dump(zoom_data, zoom_json, sort_keys=True, indent=4)
|
|
|
|
async def save_as(self, save_name):
|
|
copyfile(self.current_map, self.current_map_folder / f"{save_name}.{self.ext}")
|
|
|
|
async def load_from(self, save_name):
|
|
saved_map = self.current_map_folder / f"{save_name}.{self.ext}"
|
|
|
|
if not saved_map.exists():
|
|
return False
|
|
|
|
copyfile(saved_map, self.current_map) # Overwrite current map with saved map
|
|
return True
|