namerena 加上 peek

This commit is contained in:
shenjack 2024-06-22 19:10:53 +08:00
parent ed6af04570
commit 3d338b8ba0
Signed by: shenjack
GPG Key ID: 7B1134A979775551
5 changed files with 290 additions and 19 deletions

View File

@ -1,6 +1,6 @@
# Python 兼容版本 3.8+
from typing import Callable, Tuple, NewType, TYPE_CHECKING, TypeVar, Optional
from typing import Callable, Tuple, NewType, TYPE_CHECKING, TypeVar, Optional, Union
"""
ica.rs
@ -270,6 +270,15 @@ class TailchatClient:
"""向日志中输出警告信息"""
class ReciveMessage(TailchatReciveMessage, IcaNewMessage):
"""
继承了两边的消息
只是用来类型标记, 不能实例化
"""
def reply_with(self, message: str) -> Union["IcaReplyMessage", "TailchatSendingMessage"]: # type: ignore
...
class ConfigData:
def __getitem__(self, key: str):
...

View File

@ -0,0 +1,213 @@
import io
sklname = [
"火球术",
"冰冻术",
"雷击术",
"地裂术",
"吸血攻击",
"投毒",
"连击",
"会心一击",
"瘟疫",
"生命之轮",
"狂暴术",
"魅惑",
"加速术",
"减速术",
"诅咒",
"治愈魔法",
"苏生术",
"净化",
"铁壁",
"蓄力",
"聚气",
"潜行",
"血祭",
"分身",
"幻术",
"防御",
"守护",
"伤害反弹",
"护身符",
"护盾",
"反击",
"吞噬",
"召唤亡灵",
"垂死抗争",
"隐匿",
"sklvoid1",
"sklvoid2",
"sklvoid3",
"sklvoid4",
"sklvoid5",
]
prop_names = [
"HP",
"",
"",
"",
"",
"",
"",
"",
"八维",
]
class Player:
def __init__(self) -> None:
self.name = ""
self.team = ""
self.val = [i for i in range(0, 256)]
self.name_base = [0] * 128
self.name_str = [0] * 256
self.team_str = [0] * 256
self.name_len = 0
self.team_len = 0
self.name_prop = [0] * 8
self.skl_id = [i for i in range(0, 40)]
self.skl_freq = [0] * 40
def load(self, raw_name: str):
if raw_name == "":
print("错误:输入不能为空。")
return False
if raw_name.count("@") > 1:
print("错误:无法分割名字与战队名,请检查输入。")
return False
name_lst = list(raw_name.rpartition("@"))
if len(name_lst[0]) > 256 or len(name_lst[2]) > 256:
print("错误:名字或战队名长度过大。")
return False
if name_lst[1] == "@":
if name_lst[2] == "":
name_lst[2] = name_lst[0]
else:
name_lst[0] = name_lst[2]
name_bytes = name_lst[0].encode()
team_bytes = name_lst[2].encode()
self.name = name_lst[0]
self.team = name_lst[2]
self.name_len = len(name_lst[0])
self.team_len = len(name_lst[2])
for i in range(self.name_len):
self.name_str[i + 1] = name_bytes[i]
for i in range(self.team_len):
self.team_str[i + 1] = team_bytes[i]
self.name_len += 1
self.team_len += 1
s = 0
for i in range(256):
s += self.team_str[i % self.team_len] + self.val[i]
s %= 256
self.val[i], self.val[s] = self.val[s], self.val[i]
for i in range(2):
s = 0
for j in range(256):
s += self.name_str[j % self.name_len] + self.val[j]
s %= 256
self.val[j], self.val[s] = self.val[s], self.val[j]
s = 0
for i in range(256):
m = ((self.val[i] * 181) + 160) % 256
if m >= 89 and m < 217:
self.name_base[s] = m & 63
s += 1
propcnt = 0
r = self.name_base[0:32]
for i in range(10, 31, 3):
r[i : i + 3] = sorted(r[i : i + 3])
self.name_prop[propcnt] = r[i + 1]
propcnt += 1
r[0:10] = sorted(r[0:10])
self.name_prop[propcnt] = 154
propcnt += 1
for i in range(3, 7):
self.name_prop[propcnt - 1] += r[i]
for i in range(7):
self.name_prop[i] += 36
self.skl_id = list(range(0, 40))
self.skl_freq = [0] * 40
a = b = 0
randbase = []
randbase[:] = self.val[:]
def randgen():
def m():
nonlocal a, b, randbase
a = (a + 1) % 256
b = (b + randbase[a]) % 256
randbase[a], randbase[b] = randbase[b], randbase[a]
return randbase[(randbase[a] + randbase[b]) & 255]
return ((m() << 8) | m()) % 40
s = 0
for i in range(2):
for j in range(40):
rand = randgen()
s = (s + rand + self.skl_id[j]) % 40
self.skl_id[j], self.skl_id[s] = self.skl_id[s], self.skl_id[j]
last = -1
j = 0
for i in range(64, 128, 4):
p = (
min(
self.name_base[i],
self.name_base[i + 1],
self.name_base[i + 2],
self.name_base[i + 3],
)
% 256
)
if p > 10 and self.skl_id[j] < 35:
self.skl_freq[j] = p - 10
if self.skl_id[j] < 25:
last = j
j += 1
if last != -1:
self.skl_freq[last] *= 2
if self.skl_freq[14] > 0 and last != 14:
self.skl_freq[14] += min(
self.name_base[60], self.name_base[61], self.skl_freq[14]
)
if self.skl_freq[15] > 0 and last != 15:
self.skl_freq[15] += min(
self.name_base[62], self.name_base[63], self.skl_freq[15]
)
return True
def display(self) -> str:
cache = io.StringIO()
cache.write(f"{self.name}@{self.team}|")
full = sum(self.name_prop[0:7]) + round(self.name_prop[7] / 3)
datas = [
self.name_prop[7],
*self.name_prop[0:7],
full
]
cache.write(
"|".join(
[
f"{prop_names[index]}:{value}"
for index, value in enumerate(datas)
]
)
)
cache.write("\n")
cache.write(
"|".join(
[
f"{sklname[self.skl_id[index]]}:{self.skl_freq[index]}"
for index, value in enumerate(self.skl_freq)
if value > 0
]
)
)
return cache.getvalue()

View File

@ -1,3 +1,5 @@
import io
import sys
import time
import traceback
import subprocess
@ -6,31 +8,67 @@ from pathlib import Path
from typing import TYPE_CHECKING, TypeVar
if str(Path(__file__).parent.absolute()) not in sys.path:
sys.path.append(str(Path(__file__).parent.absolute()))
import name_utils
if TYPE_CHECKING:
from ica_typing import IcaNewMessage, IcaClient, ConfigData
from ica_typing import IcaNewMessage, IcaClient, ConfigData, ReciveMessage, TailchatReciveMessage
CONFIG_DATA: ConfigData
else:
CONFIG_DATA = None # type: ignore
IcaNewMessage = TypeVar("NewMessage")
IcaClient = TypeVar("IcaClient")
ReciveMessage = TypeVar("ReciveMessage")
TailchatReciveMessage = TypeVar("TailchatReciveMessage")
_version_ = "0.4.2"
COMMAND = "/namerena"
_version_ = "0.5.0"
def on_ica_message(msg: IcaNewMessage, client: IcaClient) -> None:
if not msg.content.startswith("/namerena") or msg.is_reply:
return
EVAL_PREFIX = "/namerena"
CONVERT_PREFIX = "/namer-peek"
def convert_name(msg: ReciveMessage, client) -> None:
# 也是多行
if msg.content.find("\n") == -1:
client.send_message(
msg.reply_with(
f"请使用 {COMMAND} 命令,然后换行输入名字,例如:\n{COMMAND}\n张三\n李四\n王五\n"
f"请使用 {CONVERT_PREFIX} 命令,然后换行输入名字,例如:\n{CONVERT_PREFIX}\n张三\n李四\n王五\n"
)
)
return
# 去掉 /name
names = msg.content[len(COMMAND) :]
# 去掉 prefix
names = msg.content[len(CONVERT_PREFIX) :]
# 去掉第一个 \n
names = names[names.find("\n") + 1 :]
cache = io.StringIO()
raw_players = [x for x in names.split("\n") if x != ""]
players = [name_utils.Player() for _ in raw_players]
for i, player in enumerate(players):
if not player.load(raw_players[i]):
cache.write(f"{i+1} {raw_players[i]} 无法解析\n")
raw_players[i] = ""
for i, player in enumerate(players):
if raw_players[i] == "":
continue
cache.write(player.display())
cache.write("\n")
reply = msg.reply_with(f"{cache.getvalue()}版本:{_version_}")
client.send_message(reply)
def eval_fight(msg: ReciveMessage, client) -> None:
if msg.content.find("\n") == -1:
client.send_message(
msg.reply_with(
f"请使用 {EVAL_PREFIX} 命令,然后换行输入名字,例如:\n{EVAL_PREFIX}\n张三\n李四\n王五\n"
)
)
return
# 去掉 prefix
names = msg.content[len(EVAL_PREFIX) :]
# 去掉第一个 \n
names = names[names.find("\n") + 1 :]
@ -64,6 +102,18 @@ def on_ica_message(msg: IcaNewMessage, client: IcaClient) -> None:
reply = msg.reply_with(f"发生错误:{e}\n{traceback.format_exc()}")
client.send_message(reply)
def dispatch_msg(msg: ReciveMessage, client) -> None:
if msg.is_reply or msg.is_from_self:
return
if msg.content.startswith(EVAL_PREFIX):
eval_fight(msg, client)
elif msg.content.startswith(CONVERT_PREFIX):
convert_name(msg, client)
def on_tailchat_message(msg, client) -> None:
on_ica_message(msg, client)
def on_ica_message(msg: IcaNewMessage, client: IcaClient) -> None:
dispatch_msg(msg, client) # type: ignore
def on_tailchat_message(msg: TailchatReciveMessage, client) -> None:
dispatch_msg(msg, client) # type: ignore

View File

@ -1,11 +1,9 @@
use std::path::PathBuf;
use std::sync::Arc;
use pyo3::prelude::*;
use rust_socketio::asynchronous::Client;
use tracing::{event, info, warn, Level};
use crate::data_struct::tailchat::status::BotStatus;
use crate::data_struct::{ica, tailchat};
use crate::error::PyPluginError;
use crate::py::{class, PyPlugin, PyStatus};

View File

@ -79,12 +79,13 @@ impl TryFrom<RawPyPlugin> for PyPlugin {
type Error = PyErr;
fn try_from(value: RawPyPlugin) -> Result<Self, Self::Error> {
let (path, changed_time, content) = value;
let py_module = py_module_from_code(&content, &path);
if let Err(e) = py_module {
let py_module = match py_module_from_code(&content, &path) {
Ok(module) => module,
Err(e) => {
warn!("加载 Python 插件: {:?} 失败", e);
return Err(e);
}
};
let py_module = py_module.unwrap();
Python::with_gil(|py| {
let module = py_module.bind(py);
if let Ok(config_func) = call::get_func(module, "on_config") {