init python:
import json
import os
import http.server
import socketserver
import threading
import time
import re
import requests
import hashlib
import hmac
import base64
import urllib.parse
# ==================== 翻译系统 ====================
class TencentTranslator:
def __init__(self):
self.enabled = True
self.cache = {}
self.cache_file = "翻译.json"
self.log_file = "log.txt"
self.translation_count = 0
# 腾讯云API配置
self.secret_id = "这里请填写你的AK"
self.secret_key = "这里请填写你的key"
self.endpoint = "tmt.tencentcloudapi.com"
self.timeout = 5
self.network_available = True
self._init_cache()
self._log("翻译系统启动")
def _init_cache(self):
"""初始化缓存"""
try:
if os.path.exists(self.cache_file):
with open(self.cache_file, "r", encoding="utf-8") as f:
cache_data = json.load(f)
for item in cache_data:
if "id" in item and "英文" in item and "中文" in item:
cache_key = item["id"]
self.cache[cache_key] = item["中文"]
self.translation_count = len(cache_data)
self._log(f"加载 {len(cache_data)} 条翻译记录")
except:
self._save_cache_to_file([])
def translate_text(self, text):
"""翻译文本(保护特殊标记)"""
if not self.enabled:
return text
if not text or len(text.strip()) < 2:
return text
if self._is_chinese(text) or len(text) < 3:
return text
text_id = hashlib.md5(text.encode('utf-8')).hexdigest()
# 检查缓存
if text_id in self.cache:
return self.cache[text_id]
# 分割并保护特殊标记
translated = self._translate_with_markers_protected(text)
if translated and translated != text:
# 保存到缓存
self._save_translation(text_id, text, translated)
self.cache[text_id] = translated
self.translation_count += 1
return translated
return text
def _translate_with_markers_protected(self, text):
"""保护特殊标记的翻译"""
# 匹配特殊标记
patterns = [
r'\[[^\]]*\]', # [角色名]
r'\{[^}]*\}', # {python表达式}
r'\([^)]*\)', # (括号内容)
r'"[^"]*"', # "双引号内容"
r"'[^']*'", # '单引号内容'
]
combined_pattern = '|'.join(patterns)
parts = []
last_end = 0
for match in re.finditer(combined_pattern, text, re.DOTALL):
if match.start() > last_end:
non_mark_text = text[last_end:match.start()]
if non_mark_text.strip():
parts.append(('text', non_mark_text))
mark_text = match.group(0)
parts.append(('mark', mark_text))
last_end = match.end()
if last_end < len(text):
non_mark_text = text[last_end:]
if non_mark_text.strip():
parts.append(('text', non_mark_text))
if not parts:
parts = [('text', text)]
# 只翻译非标记部分
translated_parts = []
for part_type, part_content in parts:
if part_type == 'mark':
translated_parts.append(part_content)
else:
if self._should_translate(part_content):
translated_text = self._call_tencent_api(part_content)
if translated_text:
translated_parts.append(translated_text)
else:
translated_parts.append(part_content)
else:
translated_parts.append(part_content)
result = ''.join(translated_parts)
result = self._safe_escape_renpy_symbols(result)
return result
def _should_translate(self, text):
"""判断是否需要翻译"""
text = text.strip()
if not text:
return False
if self._is_chinese(text):
return False
if text.replace('.', '').replace(',', '').isdigit():
return False
if all(not c.isalnum() for c in text):
return False
if len(text) < 3:
return False
return True
def _safe_escape_renpy_symbols(self, text):
"""安全转义Ren'Py符号"""
escape_pairs = [
('{', '{{'),
('}', '}}'),
('[', '[['),
(']', ']]'),
('%', '%%'),
]
pattern = r'(\[[^\]]*\]|\{[^}]*\}|\([^)]*\)|"[^"]*"|\'[^\']*\')'
parts = re.split(pattern, text)
result_parts = []
for i, part in enumerate(parts):
if i % 2 == 1:
result_parts.append(part)
else:
escaped_part = part
for char, escaped in escape_pairs:
escaped_part = escaped_part.replace(char, escaped)
result_parts.append(escaped_part)
return ''.join(result_parts)
def _call_tencent_api(self, text):
"""调用腾讯云API"""
try:
params = {
'Action': 'TextTranslate',
'Version': '2018-03-21',
'Region': 'ap-guangzhou',
'SecretId': self.secret_id,
'Timestamp': str(int(time.time())),
'Nonce': str(int(time.time() * 1000) % 100000),
'SourceText': text,
'Source': 'en',
'Target': 'zh',
'ProjectId': '0',
'SignatureMethod': 'HmacSHA256'
}
signature = self._make_signature_v1(params)
params['Signature'] = signature
query_string = '&'.join([f"{k}={urllib.parse.quote(str(v))}" for k, v in params.items()])
url = f"https://{self.endpoint}/?{query_string}"
response = requests.get(url, timeout=self.timeout)
if response.status_code == 200:
result = response.json()
if "Response" in result:
resp = result["Response"]
if "Error" not in resp:
translated = resp.get("TargetText", "").strip()
if translated:
return self._clean_translation(translated)
else:
self._log(f"翻译API错误: {response.status_code}")
except requests.exceptions.Timeout:
self._log("翻译API超时")
except requests.exceptions.ConnectionError:
self._log("翻译API连接失败")
self.network_available = False
except Exception as e:
self._log(f"翻译API异常: {e}")
return None
def _make_signature_v1(self, params):
"""生成签名"""
sorted_params = sorted(params.items())
param_list = [f"{k}={v}" for k, v in sorted_params]
param_str = '&'.join(param_list)
http_request_method = "GET"
canonical_uri = "/"
canonical_querystring = param_str
host = self.endpoint
string_to_sign = f"{http_request_method}{host}{canonical_uri}?{canonical_querystring}"
signature = hmac.new(
self.secret_key.encode('utf-8'),
string_to_sign.encode('utf-8'),
hashlib.sha256
).digest()
signature_base64 = base64.b64encode(signature).decode('utf-8')
return signature_base64
def _clean_translation(self, translated):
"""清理翻译结果"""
if not translated:
return ""
unwanted_prefixes = [
"翻译结果:", "译文:", "翻译:",
"结果为:", "中文翻译:",
"Translation:", "Translated:", "Result:"
]
for prefix in unwanted_prefixes:
if translated.startswith(prefix):
translated = translated[len(prefix):].strip()
if (translated.startswith('"') and translated.endswith('"')) or \
(translated.startswith("'") and translated.endswith("'")):
translated = translated[1:-1].strip()
return translated
def _save_translation(self, text_id, original, translated):
"""保存翻译"""
try:
cache_data = []
if os.path.exists(self.cache_file):
with open(self.cache_file, "r", encoding="utf-8") as f:
cache_data = json.load(f)
translation_record = {
"id": text_id,
"英文": original,
"中文": translated,
"timestamp": time.strftime("%Y-%m-%d %H:%M:%S")
}
# 检查是否已存在
exists = False
for i, item in enumerate(cache_data):
if item.get("id") == text_id or item.get("英文") == original:
exists = True
cache_data[i] = translation_record
break
if not exists:
cache_data.append(translation_record)
self._save_cache_to_file(cache_data)
except Exception as e:
self._log(f"保存翻译失败: {e}")
def _save_cache_to_file(self, data):
"""保存数据到文件"""
try:
with open(self.cache_file, "w", encoding="utf-8") as f:
json.dump(data, f, ensure_ascii=False, indent=2)
except Exception as e:
self._log(f"保存文件失败: {e}")
def _is_chinese(self, text):
"""检查是否包含中文"""
for char in text:
if '\u4e00' <= char <= '\u9fff':
return True
return False
def _log(self, message):
"""记录日志"""
try:
timestamp = time.strftime("%Y-%m-%d %H:%M:%S")
with open(self.log_file, "a", encoding="utf-8") as f:
f.write(f"[{timestamp}] {message}\n")
except:
pass
# ==================== 内存监控系统 ====================
class GameMemoryMonitor:
def __init__(self):
self.log_file = "memory_monitor.log"
self.data_file = "memory_data.json"
self.monitored_numbers = {}
self.monitoring_enabled = True
self.last_scan_time = 0
self.scan_interval = 5
self.load_monitored_data()
self.start_web_server()
self._log("内存监控系统启动")
def load_monitored_data(self):
"""加载监控数据"""
try:
if os.path.exists(self.data_file):
with open(self.data_file, 'r', encoding='utf-8') as f:
data = json.load(f)
self.monitored_numbers = data.get("monitored_numbers", {})
self._log(f"加载 {len(self.monitored_numbers)} 个监控项")
except:
pass
def save_monitored_data(self):
"""保存监控数据"""
try:
data = {
"monitored_numbers": self.monitored_numbers,
"last_update": time.time()
}
with open(self.data_file, 'w', encoding='utf-8') as f:
json.dump(data, f, ensure_ascii=False, indent=2)
except Exception as e:
self._log(f"保存数据失败: {e}")
def start_web_server(self):
"""启动Web服务器"""
server_thread = threading.Thread(target=self.run_web_server)
server_thread.daemon = True
server_thread.start()
self._log("Web服务器: http://127.0.0.1:8899")
def run_web_server(self):
"""运行Web服务器"""
class WebHandler(http.server.SimpleHTTPRequestHandler):
monitor = self
def log_message(self, format, *args):
pass
def do_GET(self):
if self.path == '/':
self.send_main_page()
elif self.path == '/api/monitored':
self.send_monitored_numbers()
else:
self.send_response(404)
self.end_headers()
def do_POST(self):
if self.path == '/api/search':
self.handle_search()
elif self.path == '/api/update':
self.handle_update()
elif self.path == '/api/monitor/add':
self.handle_add_monitor()
elif self.path == '/api/monitor/remove':
self.handle_remove_monitor()
else:
self.send_response(404)
self.end_headers()
def send_main_page(self):
"""发送主页面"""
self.send_response(200)
self.send_header('Content-type', 'text/html; charset=utf-8')
self.end_headers()
html = """
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>游戏工具系统</title>
<style>
body { font-family: Arial; padding: 20px; background: #f0f2f5; }
.container { max-width: 800px; margin: 0 auto; }
.header { text-align: center; margin-bottom: 30px; }
.tab-container { margin-bottom: 20px; }
.tab-buttons { display: flex; gap: 10px; margin-bottom: 20px; }
.tab-btn { padding: 10px 20px; background: #ddd; border: none; border-radius: 5px; cursor: pointer; }
.tab-btn.active { background: #3498db; color: white; }
.tab-content { display: none; }
.tab-content.active { display: block; }
.card { background: white; border-radius: 10px; padding: 20px; margin-bottom: 20px; box-shadow: 0 2px 10px rgba(0,0,0,0.1); }
</style>
</head>
<body>
<div class="container">
<div class="header">
<h1>🎮 游戏工具系统</h1>
<p>翻译系统 + 内存监控</p>
</div>
<div class="tab-container">
<div class="tab-buttons">
<button class="tab-btn active" onclick="switchTab('memory')">内存监控</button>
<button class="tab-btn" onclick="switchTab('translation')">翻译系统</button>
</div>
<!-- 内存监控标签 -->
<div id="memory-tab" class="tab-content active">
<div class="card">
<h2>🔍 搜索游戏数字</h2>
<div style="display: flex; gap: 10px; margin-bottom: 20px;">
<input type="number" id="searchNumber" placeholder="输入数字" style="flex:1; padding:10px;">
<button onclick="searchNumber()" style="padding:10px 20px; background:#3498db; color:white; border:none; border-radius:5px;">搜索</button>
</div>
<div id="searchResults"></div>
</div>
<div class="card">
<h2>📊 监控列表</h2>
<div id="monitoredList"></div>
</div>
</div>
<!-- 翻译系统标签 -->
<div id="translation-tab" class="tab-content">
<div class="card">
<h2>🌐 翻译统计</h2>
<p>翻译次数: <span id="translationCount">0</span></p>
<p>网络状态: <span id="translationStatus">在线</span></p>
</div>
</div>
</div>
</div>
<script>
function switchTab(tabName) {
// 隐藏所有标签
document.querySelectorAll('.tab-content').forEach(tab => {
tab.classList.remove('active');
});
document.querySelectorAll('.tab-btn').forEach(btn => {
btn.classList.remove('active');
});
// 显示选中标签
document.getElementById(tabName + '-tab').classList.add('active');
event.target.classList.add('active');
if (tabName === 'memory') {
loadMonitoredNumbers();
} else if (tabName === 'translation') {
loadTranslationStats();
}
}
// 内存监控功能
async function searchNumber() {
const number = document.getElementById('searchNumber').value;
if (!number) return;
try {
const response = await fetch('/api/search', {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({number: parseInt(number)})
});
const data = await response.json();
displaySearchResults(data.results);
} catch (error) {
alert('搜索失败: ' + error.message);
}
}
function displaySearchResults(results) {
const container = document.getElementById('searchResults');
if (!results || results.length === 0) {
container.innerHTML = '<p>未找到该数字</p>';
return;
}
let html = '';
results.forEach(result => {
html += `
<div style="border:1px solid #ddd; padding:10px; margin-bottom:10px; border-radius:5px;">
<p><strong>数字:</strong> ${result.number}</p>
<p><strong>类型:</strong> ${result.type}</p>
<p><strong>位置:</strong> ${result.location}</p>
${result.variable_name ? `
<button onclick="addToMonitor(${result.number}, '${result.type}', '${result.variable_name}')"
style="background:#2ecc71; color:white; border:none; padding:5px 10px; border-radius:3px; margin-right:5px;">
监控
</button>
<button onclick="editNumber('${result.variable_name}', ${result.number})"
style="background:#3498db; color:white; border:none; padding:5px 10px; border-radius:3px;">
修改
</button>
` : ''}
</div>
`;
});
container.innerHTML = html;
}
async function addToMonitor(number, type, variableName) {
try {
await fetch('/api/monitor/add', {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({
number: number,
type: type,
variable_name: variableName
})
});
loadMonitoredNumbers();
alert('已添加到监控');
} catch (error) {
alert('添加失败: ' + error.message);
}
}
async function editNumber(variableName, currentValue) {
const newValue = prompt('输入新值:', currentValue);
if (!newValue || isNaN(newValue)) return;
try {
await fetch('/api/update', {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({
variable_name: variableName,
new_value: parseInt(newValue)
})
});
loadMonitoredNumbers();
alert('修改成功');
} catch (error) {
alert('修改失败: ' + error.message);
}
}
async function loadMonitoredNumbers() {
try {
const response = await fetch('/api/monitored');
const data = await response.json();
displayMonitoredNumbers(data.numbers);
} catch (error) {
console.error('加载失败:', error);
}
}
function displayMonitoredNumbers(numbers) {
const container = document.getElementById('monitoredList');
if (!numbers || Object.keys(numbers).length === 0) {
container.innerHTML = '<p>暂无监控的数字</p>';
return;
}
let html = '';
Object.entries(numbers).forEach(([number, info]) => {
html += `
<div style="border:1px solid #ddd; padding:10px; margin-bottom:10px; border-radius:5px; display:flex; justify-content:space-between;">
<div>
<p><strong>${number}</strong> (${info.type})</p>
<p style="font-size:12px; color:#666;">${info.variable_name || '未命名'}</p>
</div>
<div>
<button onclick="editNumber('${info.variable_name}', ${number})"
style="background:#3498db; color:white; border:none; padding:5px 10px; border-radius:3px; margin-right:5px;">
修改
</button>
<button onclick="removeFromMonitor(${number})"
style="background:#e74c3c; color:white; border:none; padding:5px 10px; border-radius:3px;">
移除
</button>
</div>
</div>
`;
});
container.innerHTML = html;
}
async function removeFromMonitor(number) {
if (!confirm('确定移除?')) return;
try {
await fetch('/api/monitor/remove', {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({number: parseInt(number)})
});
loadMonitoredNumbers();
} catch (error) {
alert('移除失败: ' + error.message);
}
}
// 翻译统计
function loadTranslationStats() {
// 这里可以添加翻译统计的API调用
document.getElementById('translationCount').textContent = '加载中...';
}
// 页面加载时初始化
window.onload = function() {
loadMonitoredNumbers();
setInterval(loadMonitoredNumbers, 10000);
};
</script>
</body>
</html>
"""
self.wfile.write(html.encode('utf-8'))
def send_monitored_numbers(self):
"""发送监控列表"""
self.send_response(200)
self.send_header('Content-type', 'application/json')
self.end_headers()
data = {
"status": "success",
"numbers": self.monitor.monitored_numbers
}
self.wfile.write(json.dumps(data).encode('utf-8'))
def handle_search(self):
"""处理搜索"""
try:
content_length = int(self.headers['Content-Length'])
post_data = json.loads(self.rfile.read(content_length).decode('utf-8'))
number = int(post_data.get("number", 0))
results = self.monitor.search_number_in_game(number)
self.send_response(200)
self.send_header('Content-type', 'application/json')
self.end_headers()
self.wfile.write(json.dumps({"status": "success", "results": results}).encode('utf-8'))
except Exception as e:
self.send_response(500)
self.send_header('Content-type', 'application/json')
self.end_headers()
self.wfile.write(json.dumps({"status": "error", "message": str(e)}).encode('utf-8'))
def handle_update(self):
"""处理更新"""
try:
content_length = int(self.headers['Content-Length'])
post_data = json.loads(self.rfile.read(content_length).decode('utf-8'))
var_name = post_data.get("variable_name")
new_value = int(post_data.get("new_value", 0))
result = self.monitor.update_game_variable(var_name, new_value)
self.send_response(200)
self.send_header('Content-type', 'application/json')
self.end_headers()
self.wfile.write(json.dumps(result).encode('utf-8'))
except Exception as e:
self.send_response(500)
self.send_header('Content-type', 'application/json')
self.end_headers()
self.wfile.write(json.dumps({"status": "error", "message": str(e)}).encode('utf-8'))
def handle_add_monitor(self):
"""处理添加监控"""
try:
content_length = int(self.headers['Content-Length'])
post_data = json.loads(self.rfile.read(content_length).decode('utf-8'))
number = int(post_data.get("number", 0))
num_type = post_data.get("type", "unknown")
var_name = post_data.get("variable_name")
if number not in self.monitor.monitored_numbers:
self.monitor.monitored_numbers[number] = {
"type": num_type,
"variable_name": var_name,
"last_value": number,
"added_time": time.time()
}
self.monitor.save_monitored_data()
self.send_response(200)
self.send_header('Content-type', 'application/json')
self.end_headers()
self.wfile.write(json.dumps({"status": "success"}).encode('utf-8'))
except Exception as e:
self.send_response(500)
self.send_header('Content-type', 'application/json')
self.end_headers()
self.wfile.write(json.dumps({"status": "error", "message": str(e)}).encode('utf-8'))
def handle_remove_monitor(self):
"""处理移除监控"""
try:
content_length = int(self.headers['Content-Length'])
post_data = json.loads(self.rfile.read(content_length).decode('utf-8'))
number = int(post_data.get("number", 0))
if number in self.monitor.monitored_numbers:
del self.monitor.monitored_numbers[number]
self.monitor.save_monitored_data()
self.send_response(200)
self.send_header('Content-type', 'application/json')
self.end_headers()
self.wfile.write(json.dumps({"status": "success"}).encode('utf-8'))
except Exception as e:
self.send_response(500)
self.send_header('Content-type', 'application/json')
self.end_headers()
self.wfile.write(json.dumps({"status": "error", "message": str(e)}).encode('utf-8'))
try:
with socketserver.TCPServer(("127.0.0.1", 8899), WebHandler) as httpd:
httpd.serve_forever()
except Exception as e:
print(f"Web服务器错误: {e}")
def search_number_in_game(self, target_number):
"""搜索数字"""
results = []
try:
import store
for attr_name in dir(store):
if not attr_name.startswith('_'):
try:
attr_value = getattr(store, attr_name)
if isinstance(attr_value, (int, float)):
if attr_value == target_number:
var_type = self.guess_variable_type(attr_name, attr_value)
results.append({
"number": target_number,
"type": var_type,
"status": "已找到",
"location": f"变量: {attr_name}",
"variable_name": attr_name
})
elif isinstance(attr_value, str):
if str(target_number) in attr_value:
results.append({
"number": target_number,
"type": "text_embedded",
"status": "已找到",
"location": f"文本: {attr_name}",
"variable_name": attr_name
})
except:
continue
if not results:
results.append({
"number": target_number,
"type": "unknown",
"status": "未找到",
"location": "未在变量中找到",
"variable_name": None
})
self._log(f"搜索数字 {target_number}: {len(results)} 个结果")
except Exception as e:
self._log(f"搜索失败: {e}")
return results
def guess_variable_type(self, var_name, value):
"""猜测变量类型"""
var_name_lower = var_name.lower()
type_patterns = {
"money": ["money", "cash", "gold", "coin"],
"health": ["health", "hp", "life"],
"energy": ["energy", "mp", "mana"],
"time": ["time", "hour", "minute"]
}
for type_name, patterns in type_patterns.items():
for pattern in patterns:
if pattern in var_name_lower:
return type_name
return "unknown"
def update_game_variable(self, var_name, new_value):
"""修改变量"""
try:
import store
if hasattr(store, var_name):
old_value = getattr(store, var_name)
setattr(store, var_name, new_value)
self._log(f"修改变量: {var_name} = {old_value} -> {new_value}")
return {
"status": "success",
"message": f"已修改 {var_name}",
"old_value": old_value,
"new_value": new_value
}
else:
setattr(store, var_name, new_value)
self._log(f"创建变量: {var_name} = {new_value}")
return {
"status": "success",
"message": f"创建变量 {var_name}",
"old_value": None,
"new_value": new_value
}
except Exception as e:
self._log(f"修改变量失败: {e}")
return {
"status": "error",
"message": str(e)
}
def _log(self, message):
"""记录日志"""
try:
timestamp = time.strftime("%Y-%m-%d %H:%M:%S")
with open(self.log_file, 'a', encoding='utf-8') as f:
f.write(f"[{timestamp}] {message}\n")
except:
print(f"[内存监控] {message}")
# ==================== 创建实例 ====================
# 翻译器实例
translator = TencentTranslator()
# 内存监控实例
memory_monitor = GameMemoryMonitor()
# ==================== 挂钩翻译系统 ====================
init 999 python:
if not hasattr(renpy, '_original_say_saved'):
renpy._original_say_saved = renpy.say
def _combined_translated_say(who, what, *args, **kwargs):
if translator.enabled:
translated_what = translator.translate_text(what)
return renpy._original_say_saved(who, translated_what, *args, **kwargs)
else:
return renpy._original_say_saved(who, what, *args, **kwargs)
renpy.say = _combined_translated_say
translator._log("翻译系统挂钩完成")
# ==================== 游戏界面 ====================
screen combined_system_status():
zorder 999
frame:
xalign 1.0
yalign 0.02
xpadding 10
ypadding 5
background "#000000AA"
vbox:
spacing 2
text "游戏工具系统" size 12 color "#FFFFFF"
text "翻译: {}".format("开启" if translator.enabled else "关闭") size 10 color translator.enabled and "#00FF00" or "#FF9900"
text "监控: {}".format("运行中" if memory_monitor.monitoring_enabled else "暂停") size 10 color "#00FF00"
textbutton "控制面板 (127.0.0.1:8899)":
action OpenURL("http://127.0.0.1:8899")
text_size 10
# ==================== 游戏启动 ====================
label start:
show screen combined_system_status
"🎮 游戏工具系统已启动"
""
"📱 功能说明:"
"• 自动翻译英文对话"
"• 内存数字监控和修改"
""
"🌐 控制面板:"
"在浏览器中打开: http://127.0.0.1:8899"
""
"💬 翻译示例:"
"Hello [hero]! How are you today?"
return