More progress on switched to ConquestGame class

conquest_develop
bobloy 4 years ago
parent 2d0c9e31b3
commit 25e90c350f

@ -1,14 +1,16 @@
import asyncio import asyncio
import json import json
import pathlib import pathlib
from collections import defaultdict
from io import BytesIO from io import BytesIO
from shutil import copyfile from shutil import copyfile
from typing import Optional, Union from typing import Optional, Union, Dict
import discord import discord
from PIL import Image, ImageColor, ImageOps from PIL import Image, ImageColor, ImageOps
from discord.ext.commands import Greedy from discord.ext.commands import Greedy
from redbot.core import Config, commands from redbot.core import Config, commands
from redbot.core.commands import Context
from redbot.core.bot import Red from redbot.core.bot import Red
from redbot.core.data_manager import bundled_data_path, cog_data_path from redbot.core.data_manager import bundled_data_path, cog_data_path
from redbot.core.utils.predicates import MessagePredicate from redbot.core.utils.predicates import MessagePredicate
@ -19,14 +21,12 @@ from conquest.regioner import ConquestMap, MapMaker, composite_regions
class Conquest(commands.Cog): class Conquest(commands.Cog):
""" """
Cog for creating and modifying maps for RPGs and War Games Create and modify maps for RPGs and War Games
""" """
default_zoom_json = {"enabled": False, "x": -1, "y": -1, "zoom": 1.0}
default_maps_json = {"maps": []} default_maps_json = {"maps": []}
# Usage: self.config.games.get_raw("game_name", "is_custom") # Usage: await self.config.games.get_raw("game_name", "is_custom")
default_games = {"map_name": None, "is_custom": False} default_games = {"map_name": None, "is_custom": False}
ext = "PNG" ext = "PNG"
@ -46,10 +46,10 @@ class Conquest(commands.Cog):
self.data_path: pathlib.Path = cog_data_path(self) self.data_path: pathlib.Path = cog_data_path(self)
self.custom_map_path = self.data_path / "custom_maps" self.custom_map_folder = self.data_path / "custom_maps"
if not self.custom_map_path.exists() or not self.custom_map_path.is_dir(): if not self.custom_map_folder.exists() or not self.custom_map_folder.is_dir():
self.custom_map_path.mkdir() self.custom_map_folder.mkdir()
with (self.custom_map_path / "maps.json").open("w+") as dj: with (self.custom_map_folder / "maps.json").open("w+") as dj:
json.dump(self.default_maps_json.copy(), dj, sort_keys=True, indent=4) json.dump(self.default_maps_json.copy(), dj, sort_keys=True, indent=4)
self.current_map_folder = self.data_path / "current_maps" self.current_map_folder = self.data_path / "current_maps"
@ -58,7 +58,7 @@ class Conquest(commands.Cog):
self.asset_path: Optional[pathlib.Path] = None self.asset_path: Optional[pathlib.Path] = None
self.current_games = {} # key, value = guild.id, game_name self.current_games: Dict[int, Optional[ConquestGame]] = defaultdict(lambda: None) # key, value = guild.id, game_name
self.map_data = {} # key, value = guild.id, ConquestGame self.map_data = {} # key, value = guild.id, ConquestGame
self.mm: Optional[MapMaker] = None self.mm: Optional[MapMaker] = None
@ -70,7 +70,7 @@ class Conquest(commands.Cog):
def _path_if_custom(self, custom_custom: bool = None) -> pathlib.Path: def _path_if_custom(self, custom_custom: bool = None) -> pathlib.Path:
check_value = custom_custom # if custom_custom is not None else self.is_custom check_value = custom_custom # if custom_custom is not None else self.is_custom
if check_value: if check_value:
return self.custom_map_path return self.custom_map_folder
return self.asset_path return self.asset_path
async def load_data(self): async def load_data(self):
@ -87,14 +87,24 @@ class Conquest(commands.Cog):
# await self.current_map_load(guild_id, game_name) # await self.current_map_load(guild_id, game_name)
async def load_guild_data(self, guild: discord.Guild, game_name: str): async def load_guild_data(self, guild: discord.Guild, game_name: str):
map_data = self.config.games.get_raw(game_name) map_data = await self.config.games.get_raw(game_name)
if map_data is None:
return False
map_name = map_data["map_name"] map_name = map_data["map_name"]
map_path = self._path_if_custom(map_data["is_custom"]) / map_name map_path = self._path_if_custom(map_data["is_custom"]) / map_name
if (
not (self.current_map_folder / guild.id).exists()
or not (self.current_map_folder / guild.id / map_name).exists()
):
return False
self.current_games[guild.id] = ConquestGame( self.current_games[guild.id] = ConquestGame(
map_path, map_name, self.current_map_folder / map_name map_path, map_name, self.current_map_folder / guild.id / map_name
) )
return True
# async def current_map_load(self): # async def current_map_load(self):
# map_path = self._path_if_custom() # map_path = self._path_if_custom()
# self.map_data = ConquestMap(map_path / self.current_map) # self.map_data = ConquestMap(map_path / self.current_map)
@ -108,49 +118,16 @@ class Conquest(commands.Cog):
# # await self.config.current_map.set(None) # # await self.config.current_map.set(None)
# # return # # return
async def _get_current_map_path(self): async def _get_current_map_folder(self, guild):
return self.current_map_folder / self.current_map return self.current_map_folder / guild.id / self.current_map
async def _create_zoomed_map(self, map_path, x, y, zoom, **kwargs):
current_map = Image.open(map_path)
w, h = current_map.size
zoom2 = zoom * 2
zoomed_map = current_map.crop((x - w / zoom2, y - h / zoom2, x + w / zoom2, y + h / zoom2))
# zoomed_map = zoomed_map.resize((w, h), Image.LANCZOS)
current_map_path_ = await self._get_current_map_path()
zoomed_map.save(current_map_path_ / f"zoomed.{self.ext}", self.ext_format)
return current_map_path_ / f"zoomed.{self.ext}"
async def _send_maybe_zoomed_map(self, ctx, map_path, filename):
zoom_data = {"enabled": False}
zoom_json_path = await self._get_current_map_path() / "settings.json"
if zoom_json_path.exists():
with zoom_json_path.open() as zoom_json:
zoom_data = json.load(zoom_json)
if zoom_data["enabled"]:
map_path = await self._create_zoomed_map(map_path, **zoom_data)
await ctx.send(file=discord.File(fp=map_path, filename=filename))
async def _process_take_regions(self, color, ctx, regions):
current_img_path = await self._get_current_map_path() / f"current.{self.ext}"
im = Image.open(current_img_path)
async with ctx.typing():
out: Image.Image = await composite_regions(
im, regions, color, self._path_if_custom() / self.current_map / "masks"
)
out.save(current_img_path, self.ext_format)
await self._send_maybe_zoomed_map(ctx, current_img_path, f"map.{self.ext}")
async def _mm_save_map(self, map_name, target_save): async def _mm_save_map(self, map_name, target_save):
return await self.mm.change_name(map_name, target_save) return await self.mm.change_name(map_name, target_save)
@commands.group() @commands.group()
async def mapmaker(self, ctx: commands.context): async def mapmaker(self, ctx: Context):
""" """
Base command for managing current maps or creating new ones Base command for managing current maps or creating new ones
""" """
@ -158,7 +135,7 @@ class Conquest(commands.Cog):
pass pass
@mapmaker.command(name="numbers") @mapmaker.command(name="numbers")
async def _mapmaker_numbers(self, ctx: commands.Context): async def _mapmaker_numbers(self, ctx: Context):
"""Regenerates the number mask and puts it in the channel""" """Regenerates the number mask and puts it in the channel"""
if not self.mm: if not self.mm:
await ctx.maybe_send_embed("No map currently being worked on") await ctx.maybe_send_embed("No map currently being worked on")
@ -171,14 +148,14 @@ class Conquest(commands.Cog):
await ctx.send(file=discord.File(im, filename="map.png")) await ctx.send(file=discord.File(im, filename="map.png"))
@mapmaker.command(name="close") @mapmaker.command(name="close")
async def _mapmaker_close(self, ctx: commands.Context): async def _mapmaker_close(self, ctx: Context):
"""Close the currently open map.""" """Close the currently open map."""
self.mm = None self.mm = None
await ctx.tick() await ctx.tick()
@mapmaker.command(name="save") @mapmaker.command(name="save")
async def _mapmaker_save(self, ctx: commands.Context, *, map_name: str): async def _mapmaker_save(self, ctx: Context, *, map_name: str):
"""Save the current map to the specified map name""" """Save the current map to the specified map name"""
if not self.mm: if not self.mm:
await ctx.maybe_send_embed("No map currently being worked on") await ctx.maybe_send_embed("No map currently being worked on")
@ -188,7 +165,7 @@ class Conquest(commands.Cog):
await ctx.maybe_send_embed("This map already has that name, no reason to save") await ctx.maybe_send_embed("This map already has that name, no reason to save")
return return
target_save = self.custom_map_path / map_name target_save = self.custom_map_folder / map_name
result = await self._mm_save_map(map_name, target_save) result = await self._mm_save_map(map_name, target_save)
if not result: if not result:
@ -197,7 +174,7 @@ class Conquest(commands.Cog):
await ctx.maybe_send_embed(f"Map successfully saved to {target_save}") await ctx.maybe_send_embed(f"Map successfully saved to {target_save}")
@mapmaker.command(name="upload") @mapmaker.command(name="upload")
async def _mapmaker_upload(self, ctx: commands.Context, map_name: str, map_path=""): async def _mapmaker_upload(self, ctx: Context, map_name: str, map_path=""):
"""Load a map image to be modified. Upload one with this command or provide a path""" """Load a map image to be modified. Upload one with this command or provide a path"""
message: discord.Message = ctx.message message: discord.Message = ctx.message
if not message.attachments and not map_path: if not message.attachments and not map_path:
@ -206,7 +183,7 @@ class Conquest(commands.Cog):
) )
return return
target_save = self.custom_map_path / map_name target_save = self.custom_map_folder / map_name
if target_save.exists() and target_save.is_dir(): if target_save.exists() and target_save.is_dir():
await ctx.maybe_send_embed(f"{map_name} already exists, okay to overwrite?") await ctx.maybe_send_embed(f"{map_name} already exists, okay to overwrite?")
@ -221,7 +198,7 @@ class Conquest(commands.Cog):
return return
if not self.mm: if not self.mm:
self.mm = MapMaker(self.custom_map_path) self.mm = MapMaker(self.custom_map_folder)
self.mm.custom = True self.mm.custom = True
if map_path: if map_path:
@ -256,7 +233,7 @@ class Conquest(commands.Cog):
await ctx.maybe_send_embed("Failed to upload to that name") await ctx.maybe_send_embed("Failed to upload to that name")
return return
maps_json_path = self.custom_map_path / "maps.json" maps_json_path = self.custom_map_folder / "maps.json"
with maps_json_path.open("r+") as maps: with maps_json_path.open("r+") as maps:
map_data = json.load(maps) map_data = json.load(maps)
map_data["maps"].append(map_name) map_data["maps"].append(map_name)
@ -266,7 +243,7 @@ class Conquest(commands.Cog):
await ctx.maybe_send_embed(f"Map successfully uploaded to {target_save}") await ctx.maybe_send_embed(f"Map successfully uploaded to {target_save}")
@mapmaker.command(name="sample") @mapmaker.command(name="sample")
async def _mapmaker_sample(self, ctx: commands.Context): async def _mapmaker_sample(self, ctx: Context):
"""Print the currently being modified map as a sample""" """Print the currently being modified map as a sample"""
if not self.mm: if not self.mm:
await ctx.maybe_send_embed("No map currently being worked on") await ctx.maybe_send_embed("No map currently being worked on")
@ -280,7 +257,7 @@ class Conquest(commands.Cog):
await ctx.send(file=discord.File(f, filename="map.png")) await ctx.send(file=discord.File(f, filename="map.png"))
@mapmaker.command(name="load") @mapmaker.command(name="load")
async def _mapmaker_load(self, ctx: commands.Context, map_name: str): async def _mapmaker_load(self, ctx: Context, map_name: str):
"""Load an existing map to be modified.""" """Load an existing map to be modified."""
if self.mm: if self.mm:
await ctx.maybe_send_embed( await ctx.maybe_send_embed(
@ -288,10 +265,10 @@ class Conquest(commands.Cog):
) )
return return
map_path = self.custom_map_path / map_name map_path = self.custom_map_folder / map_name
if not map_path.exists() or not map_path.is_dir(): if not map_path.exists() or not map_path.is_dir():
await ctx.maybe_send_embed(f"Map {map_name} not found in {self.custom_map_path}") await ctx.maybe_send_embed(f"Map {map_name} not found in {self.custom_map_folder}")
return return
self.mm = MapMaker(map_path) self.mm = MapMaker(map_path)
@ -300,13 +277,13 @@ class Conquest(commands.Cog):
await ctx.tick() await ctx.tick()
@mapmaker.group(name="masks") @mapmaker.group(name="masks")
async def _mapmaker_masks(self, ctx: commands.Context): async def _mapmaker_masks(self, ctx: Context):
"""Base command for managing map masks""" """Base command for managing map masks"""
if ctx.invoked_subcommand is None: if ctx.invoked_subcommand is None:
pass pass
@_mapmaker_masks.command(name="generate") @_mapmaker_masks.command(name="generate")
async def _mapmaker_masks_generate(self, ctx: commands.Context): async def _mapmaker_masks_generate(self, ctx: Context):
""" """
Generate masks for the map Generate masks for the map
@ -332,7 +309,7 @@ class Conquest(commands.Cog):
await ctx.maybe_send_embed(f"{len(regions)} masks generated into {masks_dir}") await ctx.maybe_send_embed(f"{len(regions)} masks generated into {masks_dir}")
@_mapmaker_masks.command(name="delete") @_mapmaker_masks.command(name="delete")
async def _mapmaker_masks_delete(self, ctx: commands.Context, mask_list: Greedy[int]): async def _mapmaker_masks_delete(self, ctx: Context, mask_list: Greedy[int]):
""" """
Delete the listed masks from the map Delete the listed masks from the map
""" """
@ -358,7 +335,7 @@ class Conquest(commands.Cog):
@_mapmaker_masks.command(name="combine") @_mapmaker_masks.command(name="combine")
async def _mapmaker_masks_combine( async def _mapmaker_masks_combine(
self, ctx: commands.Context, mask_list: Greedy[int], recommended=False self, ctx: Context, mask_list: Greedy[int], recommended=False
): ):
"""Generate masks for the map""" """Generate masks for the map"""
if not mask_list and not recommended: if not mask_list and not recommended:
@ -400,25 +377,25 @@ class Conquest(commands.Cog):
await ctx.maybe_send_embed(f"Combined masks into mask # {result}") await ctx.maybe_send_embed(f"Combined masks into mask # {result}")
@commands.group() @commands.group()
async def conquest(self, ctx: commands.Context): async def conquest(self, ctx: Context):
""" """
Base command for conquest cog. Start with `[p]conquest set map` to select a map. Base command for conquest cog. Start with `[p]conquest set map` to select a map.
""" """
if ctx.invoked_subcommand is None: # if ctx.invoked_subcommand is None:
if self.current_maps[ctx.guild.id] is not None: # if self.current_maps[ctx.guild.id] is not None:
await self._conquest_current(ctx) # await self._conquest_current(ctx)
@conquest.command(name="list") @conquest.command(name="list")
async def _conquest_list(self, ctx: commands.Context): async def _conquest_list(self, ctx: Context):
""" """
List currently available maps List maps available for starting a Conquest game.
""" """
maps_json = self.asset_path / "maps.json" maps_json = self.asset_path / "maps.json"
with maps_json.open() as maps: with maps_json.open() as maps:
maps_json = json.load(maps) maps_json = json.load(maps)
map_list = maps_json["maps"] map_list = maps_json["maps"]
maps_json = self.custom_map_path / "maps.json" maps_json = self.custom_map_folder / "maps.json"
if maps_json.exists(): if maps_json.exists():
with maps_json.open() as maps: with maps_json.open() as maps:
maps_json = json.load(maps) maps_json = json.load(maps)
@ -429,32 +406,26 @@ class Conquest(commands.Cog):
await ctx.maybe_send_embed(f"Current maps:\n{map_list}\n\nCustom maps:\n{custom_map_list}") await ctx.maybe_send_embed(f"Current maps:\n{map_list}\n\nCustom maps:\n{custom_map_list}")
@conquest.group(name="set") @conquest.group(name="set")
async def conquest_set(self, ctx: commands.Context): async def conquest_set(self, ctx: Context):
"""Base command for admin actions like selecting a map""" """Base command for admin actions like selecting a map"""
if ctx.invoked_subcommand is None: if ctx.invoked_subcommand is None:
pass pass
@conquest_set.command(name="resetzoom") @conquest_set.command(name="resetzoom")
async def _conquest_set_resetzoom(self, ctx: commands.Context): async def _conquest_set_resetzoom(self, ctx: Context):
"""Resets the zoom level of the current map""" """Resets the zoom level of the current map"""
if self.current_map is None: if self.current_games[ctx.guild.id] is None:
await ctx.maybe_send_embed("No map is currently set. See `[p]conquest set map`") await ctx.maybe_send_embed("No map is currently set. See `[p]conquest set map`")
return return
zoom_json_path = await self._get_current_map_path() / "settings.json" if not await self.current_games[ctx.guild.id].reset_zoom():
if not zoom_json_path.exists():
await ctx.maybe_send_embed( await ctx.maybe_send_embed(
f"No zoom data found for {self.current_map}, reset not needed" f"No zoom data found, reset not needed"
) )
return
with zoom_json_path.open("w+") as zoom_json:
json.dump({"enabled": False}, zoom_json, sort_keys=True, indent=4)
await ctx.tick() await ctx.tick()
@conquest_set.command(name="zoom") @conquest_set.command(name="zoom")
async def _conquest_set_zoom(self, ctx: commands.Context, x: int, y: int, zoom: float): async def _conquest_set_zoom(self, ctx: Context, x: int, y: int, zoom: float):
""" """
Set the zoom level and position of the current map Set the zoom level and position of the current map
@ -462,7 +433,7 @@ class Conquest(commands.Cog):
y: positive integer y: positive integer
zoom: float greater than or equal to 1 zoom: float greater than or equal to 1
""" """
if self.current_map is None: if self.current_games[ctx.guild.id] is None:
await ctx.maybe_send_embed("No map is currently set. See `[p]conquest set map`") await ctx.maybe_send_embed("No map is currently set. See `[p]conquest set map`")
return return
@ -470,21 +441,12 @@ class Conquest(commands.Cog):
await ctx.send_help() await ctx.send_help()
return return
zoom_json_path = await self._get_current_map_path() / "settings.json" await self.current_games[ctx.guild.id].set_zoom(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
with zoom_json_path.open("w+") as zoom_json:
json.dump(zoom_data, zoom_json, sort_keys=True, indent=4)
await ctx.tick() await ctx.tick()
@conquest_set.command(name="zoomtest") @conquest_set.command(name="zoomtest")
async def _conquest_set_zoomtest(self, ctx: commands.Context, x: int, y: int, zoom: float): async def _conquest_set_zoomtest(self, ctx: Context, x: int, y: int, zoom: float):
""" """
Test the zoom level and position of the current map Test the zoom level and position of the current map
@ -492,7 +454,7 @@ class Conquest(commands.Cog):
y: positive integer y: positive integer
zoom: float greater than or equal to 1 zoom: float greater than or equal to 1
""" """
if self.current_map is None: if self.current_games[ctx.guild.id] is None:
await ctx.maybe_send_embed("No map is currently set. See `[p]conquest set map`") await ctx.maybe_send_embed("No map is currently set. See `[p]conquest set map`")
return return
@ -500,20 +462,21 @@ class Conquest(commands.Cog):
await ctx.send_help() await ctx.send_help()
return return
map_folder = await self._get_current_map_folder(ctx.guild)
zoomed_path = await self._create_zoomed_map( zoomed_path = await self._create_zoomed_map(
await self._get_current_map_path() / f"current.{self.ext}", x, y, zoom map_folder, map_folder / f"current.{self.ext}", x, y, zoom
) )
await ctx.send(file=discord.File(fp=zoomed_path, filename=f"current_zoomed.{self.ext}")) await ctx.send(file=discord.File(fp=zoomed_path, filename=f"current_zoomed.{self.ext}"))
@conquest_set.command(name="save") @conquest_set.command(name="save")
async def _conquest_set_save(self, ctx: commands.Context, *, save_name): async def _conquest_set_save(self, ctx: Context, *, save_name):
"""Save the current map to be loaded later""" """Save the current map to be loaded later"""
if self.current_map is None: if self.current_map is None:
await ctx.maybe_send_embed("No map is currently set. See `[p]conquest set map`") await ctx.maybe_send_embed("No map is currently set. See `[p]conquest set map`")
return return
current_map_folder = await self._get_current_map_path() current_map_folder = await self._get_current_map_folder()
current_map = current_map_folder / f"current.{self.ext}" current_map = current_map_folder / f"current.{self.ext}"
if not current_map_folder.exists() or not current_map.exists(): if not current_map_folder.exists() or not current_map.exists():
@ -524,13 +487,13 @@ class Conquest(commands.Cog):
await ctx.tick() await ctx.tick()
@conquest_set.command(name="load") @conquest_set.command(name="load")
async def _conquest_set_load(self, ctx: commands.Context, *, save_name): async def _conquest_set_load(self, ctx: Context, *, save_name):
"""Load a saved map to be the current map""" """Load a saved map to be the current map"""
if self.current_map is None: if self.current_map is None:
await ctx.maybe_send_embed("No map is currently set. See `[p]conquest set map`") await ctx.maybe_send_embed("No map is currently set. See `[p]conquest set map`")
return return
current_map_folder = await self._get_current_map_path() current_map_folder = await self._get_current_map_folder()
current_map = current_map_folder / f"current.{self.ext}" current_map = current_map_folder / f"current.{self.ext}"
saved_map = current_map_folder / f"{save_name}.{self.ext}" saved_map = current_map_folder / f"{save_name}.{self.ext}"
@ -543,7 +506,7 @@ class Conquest(commands.Cog):
@conquest_set.command(name="map") @conquest_set.command(name="map")
async def _conquest_set_map( async def _conquest_set_map(
self, ctx: commands.Context, mapname: str, is_custom: bool = False, reset: bool = False self, ctx: Context, mapname: str, is_custom: bool = False, reset: bool = False
): ):
""" """
Select a map from current available maps Select a map from current available maps
@ -566,7 +529,7 @@ class Conquest(commands.Cog):
await self.current_map_load() await self.current_map_load()
current_map_folder = await self._get_current_map_path() current_map_folder = await self._get_current_map_folder()
current_map = current_map_folder / f"current.{self.ext}" current_map = current_map_folder / f"current.{self.ext}"
if not reset and current_map.exists(): if not reset and current_map.exists():
@ -582,7 +545,7 @@ class Conquest(commands.Cog):
await ctx.tick() await ctx.tick()
@conquest.command(name="current") @conquest.command(name="current")
async def _conquest_current(self, ctx: commands.Context): async def _conquest_current(self, ctx: Context):
""" """
Send the current map. Send the current map.
""" """
@ -590,12 +553,12 @@ class Conquest(commands.Cog):
await ctx.maybe_send_embed("No map is currently set. See `[p]conquest set map`") await ctx.maybe_send_embed("No map is currently set. See `[p]conquest set map`")
return return
current_img = await self._get_current_map_path() / f"current.{self.ext}" current_img = await self._get_current_map_folder() / f"current.{self.ext}"
await self._send_maybe_zoomed_map(ctx, current_img, f"current_map.{self.ext}") await self._send_maybe_zoomed_map(ctx, current_img, f"current_map.{self.ext}")
@conquest.command("blank") @conquest.command("blank")
async def _conquest_blank(self, ctx: commands.Context): async def _conquest_blank(self, ctx: Context):
""" """
Print the blank version of the current map, for reference. Print the blank version of the current map, for reference.
""" """
@ -608,7 +571,7 @@ class Conquest(commands.Cog):
await self._send_maybe_zoomed_map(ctx, current_blank_img, f"blank_map.{self.ext}") await self._send_maybe_zoomed_map(ctx, current_blank_img, f"blank_map.{self.ext}")
@conquest.command("numbered") @conquest.command("numbered")
async def _conquest_numbered(self, ctx: commands.Context): async def _conquest_numbered(self, ctx: Context):
""" """
Print the numbered version of the current map, for reference. Print the numbered version of the current map, for reference.
""" """
@ -626,7 +589,7 @@ class Conquest(commands.Cog):
) )
return return
current_map_path = await self._get_current_map_path() current_map_path = await self._get_current_map_folder()
current_map = Image.open(current_map_path / f"current.{self.ext}") current_map = Image.open(current_map_path / f"current.{self.ext}")
numbers = Image.open(numbers_path).convert("L") numbers = Image.open(numbers_path).convert("L")
@ -649,7 +612,7 @@ class Conquest(commands.Cog):
@conquest.command(name="multitake") @conquest.command(name="multitake")
async def _conquest_multitake( async def _conquest_multitake(
self, ctx: commands.Context, start_region: int, end_region: int, color: str self, ctx: Context, start_region: int, end_region: int, color: str
): ):
""" """
Claim all the territories between the two provided region numbers (inclusive) Claim all the territories between the two provided region numbers (inclusive)
@ -677,10 +640,10 @@ class Conquest(commands.Cog):
regions = [r for r in range(start_region, end_region + 1)] regions = [r for r in range(start_region, end_region + 1)]
await self._process_take_regions(color, ctx, regions) await self._process_take_regions(ctx, color, regions)
@conquest.command(name="take") @conquest.command(name="take")
async def _conquest_take(self, ctx: commands.Context, regions: Greedy[int], *, color: str): async def _conquest_take(self, ctx: Context, regions: Greedy[int], *, color: str):
""" """
Claim a territory or list of territories for a specified color Claim a territory or list of territories for a specified color
@ -708,4 +671,4 @@ class Conquest(commands.Cog):
) )
return return
await self._process_take_regions(color, ctx, regions) await self._process_take_regions(ctx, color,regions)

@ -1,13 +1,28 @@
import json
import pathlib import pathlib
from conquest.regioner import ConquestMap import discord
from PIL import Image, ImageColor, ImageOps
from conquest.regioner import ConquestMap, composite_regions
class 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): def __init__(self, map_path: pathlib.Path, game_name: str, custom_map_path: pathlib.Path):
self.blank_map = ConquestMap(map_path) self.source_map = ConquestMap(map_path)
self.game_name = game_name self.game_name = game_name
self.custom_map_path = custom_map_path self.current_map_folder = custom_map_path
self.settings_json = self.current_map_folder / "settings.json"
self.current_map = self.current_map_folder / f"current.{self.ext}"
self.zoomed_map = self.current_map_folder / f"zoomed.{self.ext}"
self.zoom_is_out_of_date = True
async def save_region(self, region): async def save_region(self, region):
if not self.custom: if not self.custom:
@ -16,3 +31,64 @@ class ConquestGame:
async def start_game(self): async def start_game(self):
pass pass
async def _process_take_regions(self, color, regions):
im = Image.open(self.current_map)
out: 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 = True
async def create_zoomed_map(self, x, y, zoom, **kwargs):
if not self.zoom_is_out_of_date:
return self.zoomed_map
current_map = Image.open(self.current_map_folder)
w, h = current_map.size
zoom2 = zoom * 2
zoomed_map = current_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(self.zoomed_map, self.ext_format)
self.zoom_is_out_of_date = False
return self.zoomed_map
async def get_maybe_zoomed_map(self, filename):
zoom_data = {"enabled": False}
if self.settings_json.exists():
with self.settings_json.open() as zoom_json:
zoom_data = json.load(zoom_json)
map_path = self.current_map
if zoom_data["enabled"]:
map_path = await self.create_zoomed_map(**zoom_data) # Send zoomed map instead of current map
return discord.File(fp=map_path, filename=filename)
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)
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
with self.settings_json.open("w+") as zoom_json:
json.dump(zoom_data, zoom_json, sort_keys=True, indent=4)

Loading…
Cancel
Save