新增材料地图

This commit is contained in:
CMHopeSunshine 2022-09-18 22:20:48 +08:00
parent 0342e220f6
commit f875cf8611
4 changed files with 105 additions and 22 deletions

View File

@ -7,7 +7,7 @@ from LittlePaimon.utils.migration import migrate_database
from LittlePaimon.utils.tool import check_resource
DRIVER = get_driver()
__version__ = '3.0.0beta6'
__version__ = '3.0.0beta7'
try:
SUPERUSERS: List[int] = [int(s) for s in DRIVER.config.superusers]

View File

@ -63,7 +63,7 @@ async def draw_help(plugin_list: List[PluginInfo]):
await img.paste(matcher_card, (40 + 336 * matcher_group.index(matcher), height_now))
await img.text(matcher.pm_usage, 40 + 336 * matcher_group.index(matcher) + 15, height_now + 10, fm.get('SourceHanSansCN-Bold.otf', 24), 'black')
if matcher.pm_description:
await img.text_box(matcher.pm_description, (40 + 336 * matcher_group.index(matcher) + 10, 40 + 336 * matcher_group.index(matcher) + matcher_card.width - 22),
await img.text_box(matcher.pm_description.replace('\n', '^'), (40 + 336 * matcher_group.index(matcher) + 10, 40 + 336 * matcher_group.index(matcher) + matcher_card.width - 22),
(height_now + 44, height_now + max_height - 10), fm.get('SourceHanSansCN-Bold.otf', 18), '#40342d')
height_now += max_height + 10 + 6
elif plugin.usage:

View File

@ -1,19 +1,20 @@
import time
from nonebot import on_regex, on_command
from nonebot.adapters.onebot.v11 import MessageEvent, Message, MessageSegment
from nonebot.adapters.onebot.v11 import MessageEvent, Message, MessageSegment, GroupMessageEvent
from nonebot.adapters.onebot.v11.helpers import HandleCancellation
from nonebot.adapters.onebot.v11.exception import ActionFailed
from nonebot.params import RegexDict, ArgPlainText, CommandArg
from nonebot.params import RegexDict, ArgPlainText, CommandArg, Arg
from nonebot.plugin import PluginMetadata
from nonebot.typing import T_State
from LittlePaimon import NICKNAME, DRIVER
from LittlePaimon.utils.alias import get_match_alias
from LittlePaimon.utils.tool import freq_limiter
from LittlePaimon.utils.message import MessageBuild
from LittlePaimon.database.models import PlayerAlias
from LittlePaimon.config import RESOURCE_BASE_PATH
from .draw_map import init_map, draw_map
from .draw_map import init_map, draw_map, get_full_map
# from .abyss_rate_draw import draw_rate_rank, draw_teams_rate
@ -54,6 +55,12 @@ material_map = on_command('材料图鉴', priority=11, block=True, state={
'pm_usage': '材料图鉴<材料名>[地图]',
'pm_priority': 9
})
material_map_full = on_command('材料地图', priority=11, block=True, state={
'pm_name': '材料地图',
'pm_description': '查看多个材料大地图采集点。\n示例:材料地图 鸣草 鬼兜虫 提瓦特',
'pm_usage': '材料地图<材料名列表>[地图]',
'pm_priority': 10
})
# abyss_rate = on_command('syrate', aliases={'深渊登场率', '深境螺旋登场率', '深渊登场率排行', '深渊排行'}, priority=11, block=True, state={
@ -101,16 +108,20 @@ async def _(event: MessageEvent, regex_dict: dict = RegexDict()):
@material_map.handle()
async def _(event: MessageEvent, state: T_State, msg: Message = CommandArg()):
if params := msg.extract_plain_text().strip().split(' '):
if params := msg.extract_plain_text().strip():
params = params.split(' ')
state['name'] = Message(params[0])
if len(params) > 1:
if params[1] in {'提瓦特', '层岩巨渊', '渊下宫'}:
state['map'] = params[1]
else:
state['map'] = Message('提瓦特')
else:
state['map'] = Message('提瓦特')
@material_map.got('map', prompt='地图名称有误,请在【提瓦特、层岩巨渊、渊下宫】中选择')
@material_map.got('map', prompt='地图名称有误,请在【提瓦特、层岩巨渊、渊下宫】中选择,或回答【取消】退出',
parameterless=[HandleCancellation(f'好吧,有需要再找{NICKNAME}')])
async def _(event: MessageEvent, state: T_State, map_: str = ArgPlainText('map')):
if map_ not in {'提瓦特', '层岩巨渊', '渊下宫'}:
await material_map.reject('地图名称有误,请在【提瓦特、层岩巨渊、渊下宫】中选择')
@ -128,21 +139,34 @@ async def _(event: MessageEvent, map_: str = ArgPlainText('map'), name: str = Ar
await material_map.finish(result, at_sender=True)
@material_map_full.handle()
async def _(event: MessageEvent, state: T_State, msg: Message = CommandArg()):
state['map'] = '提瓦特'
if params := msg.extract_plain_text().strip():
params = params.split(' ')
for p in params.copy():
if p in {'提瓦特', '层岩巨渊', '渊下宫'}:
params.remove(p)
state['map'] = p
state['names'] = params
@material_map_full.got('names', prompt='请输入要查询的材料名称,或回答【取消】退出',
parameterless=[HandleCancellation(f'好吧,有需要再找{NICKNAME}')])
async def _(event: MessageEvent, map_: str = Arg('map'), names=Arg('names')):
if isinstance(names, Message):
names = names.extract_plain_text().split(' ')
if not freq_limiter.check(f'材料地图_{event.group_id if isinstance(event, GroupMessageEvent) else event.user_id}'):
await material_map_full.finish(f'材料地图查询冷却中,剩余{freq_limiter.left(f"材料地图_{event.group_id if isinstance(event, GroupMessageEvent) else event.user_id}")}', at_sender=True)
freq_limiter.start(f'材料地图_{event.group_id if isinstance(event, GroupMessageEvent) else event.user_id}', 15)
await material_map_full.send(MessageBuild.Text(f'开始查找{"".join(names)}的资源点,请稍候...'))
result = await get_full_map(names, map_)
await material_map_full.finish(result, at_sender=True)
DRIVER.on_bot_connect(init_map)
# @abyss_rate.handle()
# async def abyss_rate_handler(event: MessageEvent):
# abyss_img = await draw_rate_rank()
# await abyss_rate.finish(abyss_img)
# @abyss_team.handle()
# async def abyss_team_handler(event: MessageEvent, reGroup=RegexDict()):
# abyss_img = await draw_teams_rate(reGroup['floor'])
# await abyss_team.finish(abyss_img)
def create_wiki_matcher(pattern: str, help_fun: str, help_name: str):
maps = on_regex(pattern, priority=11, block=True, state={
'pm_name': help_fun,
@ -187,7 +211,7 @@ def create_wiki_matcher(pattern: str, help_fun: str, help_name: str):
if isinstance(name, Message):
name = name.extract_plain_text().strip()
if state['type'] == '角色' and (
match_alias := await PlayerAlias.get_or_none(user_id=str(event.user_id), alias=name)):
match_alias := await PlayerAlias.get_or_none(user_id=str(event.user_id), alias=name)):
try:
await maps.finish(MessageSegment.image(state['img_url'].format(match_alias.character)))
except ActionFailed:

View File

@ -1,11 +1,12 @@
import math
from typing import List
from LittlePaimon.config import RESOURCE_BASE_PATH
from LittlePaimon.utils import logger, aiorequests
from LittlePaimon.utils.files import load_image
from LittlePaimon.utils.image import PMImage, font_manager as fm
from LittlePaimon.utils.message import MessageBuild
from .genshinmap import utils, models, request, img
from .genshinmap import utils, models, request, img, XYPoint
from PIL import Image, ImageFile, ImageOps
ImageFile.LOAD_TRUNCATED_IMAGES = True
@ -64,7 +65,7 @@ async def draw_map(name: str, map_: str):
return MessageBuild.Text(f'未查找到材料{name}')
points = await request.get_points(map_id)
if not (points := utils.convert_pos(utils.get_points_by_id(resource.id, points), maps.detail.origin)):
return MessageBuild.Text(f'{map_}未查找到材料{name},请尝试其他地图')
return MessageBuild.Text(f'{map_}未查找到材料{name},请尝试其他地图')
point_icon = await load_image(RESOURCE_BASE_PATH / 'genshin_map' / 'point_icon.png')
if len(points) >= 3:
group_point = img.k_means_points(points, 700)
@ -110,5 +111,63 @@ async def draw_map(name: str, map_: str):
return MessageBuild.Image(total_img, mode='RGB', quality=85)
async def get_full_map(names: List[str], map_: str):
map_id = models.MapID[map_name_reverse[map_]]
maps = await request.get_maps(map_id)
labels = await request.get_labels(map_id)
resources = []
resources_not = []
resources_points = []
childs = [child for label in labels for child in label.children]
for name in names:
if res_filter := list(filter(lambda x: x.name == name, childs)):
resources.append(res_filter[0])
else:
resources_not.append(name)
if not resources:
return MessageBuild.Text(f'未查找到材料{"".join(names)}')
points = await request.get_points(map_id)
for resource in resources:
if points_ := utils.convert_pos(utils.get_points_by_id(resource.id, points), maps.detail.origin):
resources_points.append(points_)
else:
resources_not.append(resource.name)
if not resources_points:
return MessageBuild.Text(f'{map_}未查找到材料{"".join(names)},请尝试其他地图')
map_img = await load_image(RESOURCE_BASE_PATH / 'genshin_map' / 'results' / f'{map_id.name}.png')
box_icon = await load_image(RESOURCE_BASE_PATH / 'genshin_map' / 'point_box.png')
i = 0
max_point = XYPoint(x=0, y=0)
min_point = XYPoint(x=16384, y=12288)
for points in resources_points:
resource_icon = box_icon.copy()
resource_icon.alpha_composite(await aiorequests.get_img(resources[i].icon, size=(90, 90)), (28, 15))
resource_icon = resource_icon.resize((48, 48), Image.ANTIALIAS)
if len(points) >= 3:
group_point = img.k_means_points(points, 16000)
else:
x1_temp = int(points[0].x) - 16000
x2_temp = int(points[0].x) + 16000
y1_temp = int(points[0].y) - 16000
y2_temp = int(points[0].y) + 16000
group_point = [(
models.XYPoint(x1_temp, y1_temp),
models.XYPoint(x2_temp, y2_temp),
points)]
lt_point = group_point[0][0]
rb_point = group_point[0][1]
min_point = XYPoint(x=min(min_point.x, lt_point.x), y=min(min_point.y, lt_point.y))
max_point = XYPoint(x=max(max_point.x, rb_point.x), y=max(max_point.y, rb_point.y))
for point in group_point[0][2]:
point_trans = (int(point.x), int(point.y))
map_img.paste(resource_icon, (point_trans[0] - 24, point_trans[1] - 48), resource_icon)
i += 1
map_img = map_img.crop((int(min_point.x) - 50, int(min_point.y) - 50, int(max_point.x) + 50, int(max_point.y) + 50))
if resources_not:
return MessageBuild.Text(f'{map_}未找到材料{"".join(resources_not)},请尝试其他地图\n') + MessageBuild.Image(map_img)
else:
return MessageBuild.Image(map_img)