mirror of
https://github.com/xuthus83/LittlePaimon.git
synced 2025-04-12 23:29:37 +08:00
✨ 新增材料地图
This commit is contained in:
parent
0342e220f6
commit
f875cf8611
@ -7,7 +7,7 @@ from LittlePaimon.utils.migration import migrate_database
|
|||||||
from LittlePaimon.utils.tool import check_resource
|
from LittlePaimon.utils.tool import check_resource
|
||||||
|
|
||||||
DRIVER = get_driver()
|
DRIVER = get_driver()
|
||||||
__version__ = '3.0.0beta6'
|
__version__ = '3.0.0beta7'
|
||||||
|
|
||||||
try:
|
try:
|
||||||
SUPERUSERS: List[int] = [int(s) for s in DRIVER.config.superusers]
|
SUPERUSERS: List[int] = [int(s) for s in DRIVER.config.superusers]
|
||||||
|
@ -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.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')
|
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:
|
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 + 44, height_now + max_height - 10), fm.get('SourceHanSansCN-Bold.otf', 18), '#40342d')
|
||||||
height_now += max_height + 10 + 6
|
height_now += max_height + 10 + 6
|
||||||
elif plugin.usage:
|
elif plugin.usage:
|
||||||
|
@ -1,19 +1,20 @@
|
|||||||
import time
|
import time
|
||||||
|
|
||||||
from nonebot import on_regex, on_command
|
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.helpers import HandleCancellation
|
||||||
from nonebot.adapters.onebot.v11.exception import ActionFailed
|
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.plugin import PluginMetadata
|
||||||
from nonebot.typing import T_State
|
from nonebot.typing import T_State
|
||||||
|
|
||||||
from LittlePaimon import NICKNAME, DRIVER
|
from LittlePaimon import NICKNAME, DRIVER
|
||||||
from LittlePaimon.utils.alias import get_match_alias
|
from LittlePaimon.utils.alias import get_match_alias
|
||||||
|
from LittlePaimon.utils.tool import freq_limiter
|
||||||
from LittlePaimon.utils.message import MessageBuild
|
from LittlePaimon.utils.message import MessageBuild
|
||||||
from LittlePaimon.database.models import PlayerAlias
|
from LittlePaimon.database.models import PlayerAlias
|
||||||
from LittlePaimon.config import RESOURCE_BASE_PATH
|
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
|
# 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_usage': '材料图鉴<材料名>[地图]',
|
||||||
'pm_priority': 9
|
'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={
|
# 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()
|
@material_map.handle()
|
||||||
async def _(event: MessageEvent, state: T_State, msg: Message = CommandArg()):
|
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])
|
state['name'] = Message(params[0])
|
||||||
if len(params) > 1:
|
if len(params) > 1:
|
||||||
if params[1] in {'提瓦特', '层岩巨渊', '渊下宫'}:
|
if params[1] in {'提瓦特', '层岩巨渊', '渊下宫'}:
|
||||||
state['map'] = params[1]
|
state['map'] = params[1]
|
||||||
else:
|
else:
|
||||||
state['map'] = Message('提瓦特')
|
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')):
|
async def _(event: MessageEvent, state: T_State, map_: str = ArgPlainText('map')):
|
||||||
if map_ not in {'提瓦特', '层岩巨渊', '渊下宫'}:
|
if map_ not in {'提瓦特', '层岩巨渊', '渊下宫'}:
|
||||||
await material_map.reject('地图名称有误,请在【提瓦特、层岩巨渊、渊下宫】中选择')
|
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)
|
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)
|
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):
|
def create_wiki_matcher(pattern: str, help_fun: str, help_name: str):
|
||||||
maps = on_regex(pattern, priority=11, block=True, state={
|
maps = on_regex(pattern, priority=11, block=True, state={
|
||||||
'pm_name': help_fun,
|
'pm_name': help_fun,
|
||||||
@ -187,7 +211,7 @@ def create_wiki_matcher(pattern: str, help_fun: str, help_name: str):
|
|||||||
if isinstance(name, Message):
|
if isinstance(name, Message):
|
||||||
name = name.extract_plain_text().strip()
|
name = name.extract_plain_text().strip()
|
||||||
if state['type'] == '角色' and (
|
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:
|
try:
|
||||||
await maps.finish(MessageSegment.image(state['img_url'].format(match_alias.character)))
|
await maps.finish(MessageSegment.image(state['img_url'].format(match_alias.character)))
|
||||||
except ActionFailed:
|
except ActionFailed:
|
||||||
|
@ -1,11 +1,12 @@
|
|||||||
import math
|
import math
|
||||||
|
from typing import List
|
||||||
from LittlePaimon.config import RESOURCE_BASE_PATH
|
from LittlePaimon.config import RESOURCE_BASE_PATH
|
||||||
from LittlePaimon.utils import logger, aiorequests
|
from LittlePaimon.utils import logger, aiorequests
|
||||||
from LittlePaimon.utils.files import load_image
|
from LittlePaimon.utils.files import load_image
|
||||||
from LittlePaimon.utils.image import PMImage, font_manager as fm
|
from LittlePaimon.utils.image import PMImage, font_manager as fm
|
||||||
from LittlePaimon.utils.message import MessageBuild
|
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
|
from PIL import Image, ImageFile, ImageOps
|
||||||
ImageFile.LOAD_TRUNCATED_IMAGES = True
|
ImageFile.LOAD_TRUNCATED_IMAGES = True
|
||||||
@ -64,7 +65,7 @@ async def draw_map(name: str, map_: str):
|
|||||||
return MessageBuild.Text(f'未查找到材料{name}')
|
return MessageBuild.Text(f'未查找到材料{name}')
|
||||||
points = await request.get_points(map_id)
|
points = await request.get_points(map_id)
|
||||||
if not (points := utils.convert_pos(utils.get_points_by_id(resource.id, points), maps.detail.origin)):
|
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')
|
point_icon = await load_image(RESOURCE_BASE_PATH / 'genshin_map' / 'point_icon.png')
|
||||||
if len(points) >= 3:
|
if len(points) >= 3:
|
||||||
group_point = img.k_means_points(points, 700)
|
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)
|
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)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user