代码库初始化
This commit is contained in:
1 parent
07786ab323
commit
4334694551
851 files changed
+42626
No files matched your search
Binary file not shown.
|
After Width: | Height: | Size: 1.9 KiB |
@@ -0,0 +1,81 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""给 71 个材料 beh json 添加 netease:customtips 描述,清理 lang 无效 .desc 条目"""
|
||||
import csv, os, json
|
||||
|
||||
BASE = r'e:\MCStudioDownload\work\3027246179@qq.com\Cpp\AddOn\309c2d420bc84ee986db9cdd070ff02a'
|
||||
DROP = {'box_of_nails', 'box_of_paperclips', 'box_of_screws', 'gunpowder_bottle', 'rope'}
|
||||
|
||||
SPECIAL = {
|
||||
'dirty_water_bottle': '饮用可能引起饥饿',
|
||||
'generator_manual': '学习手册并完成实践训练以操作汽油发电机。',
|
||||
'matchbox': '点燃方块和火焰',
|
||||
'sterilized_rags': '清洁医用布。使用后返还脏抹布',
|
||||
'jerry_can': '用于储存液体:右键液体源收集,Shift+右键倒出',
|
||||
'saw_blade': '锯子部件,用于制作工具',
|
||||
'money': '战利品货币',
|
||||
'money_bundle': '一捆货币',
|
||||
'blank': '空白物品',
|
||||
}
|
||||
META = ('ashen_steel_ingot', 'ashen_steel_mixture', 'ashen_steel_nugget', 'ashen_steel_rod', 'metal_pipe',
|
||||
'metal_sheet', 'small_metal_sheet', 'scrap_nugget', 'diamond_nugget', 'netherite_nugget')
|
||||
FABRIC = ('cloth', 'dirty_rags', 'dish_towel', 'fabric_patch', 'fiber_fabric', 'polyester',
|
||||
'rags', 'sterilized_rags', 'kevlar', 'leather_strip')
|
||||
THREAD = ('thread', 'kevlar_thread', 'polyester_thread', 'copper_wire', 'insulated_copper_wire', 'wire')
|
||||
FASTENER = ('nails', 'screws', 'box_of_nails', 'box_of_screws', 'box_of_paperclips', 'paperclip')
|
||||
SCRAP = ('metal_scrap', 'electric_scrap', 'scrap_wood')
|
||||
PLASTIC = ('plastic', 'plastic_bag', 'plastic_plate', 'cardboard')
|
||||
ADHESIVE = ('glue', 'medical_adhesive', 'adhesive_tape', 'duct_tape')
|
||||
|
||||
def desc(name):
|
||||
if name in SPECIAL:
|
||||
return SPECIAL[name]
|
||||
if name in META:
|
||||
return '用于锻造与回收的金属材料。'
|
||||
if name in SCRAP:
|
||||
return '可回收利用的材料。'
|
||||
if name in FABRIC:
|
||||
return '用于缝制、修复与回收的织物材料。'
|
||||
if name in THREAD:
|
||||
return '用于制作与缝合的线材。'
|
||||
if name in FASTENER:
|
||||
return '用于组装的紧固件。'
|
||||
if name in PLASTIC:
|
||||
return '可用于制作物品的塑料材料。'
|
||||
if name in ADHESIVE:
|
||||
return '修复与组装的粘合材料。'
|
||||
if name in ('battery', 'camera', 'cellphone', 'classic_watch', 'falsh_lights'):
|
||||
return '可拆解的电子元件。'
|
||||
if name in ('sulfur', 'sulfur_dust', 'charcoal_dust'):
|
||||
return '可用于制作的化学材料。'
|
||||
if name in ('empty_can', 'dented_can', 'tin_can', 'empty_glass_bottle'):
|
||||
return '空容器,可回收利用。'
|
||||
if name in ('water_bottle', 'water_bottle2', 'alcohol', 'rubbing_alcohol', 'cleaning_liquid',
|
||||
'hair_gel', 'fermented_mash', 'gasoline_bucket'):
|
||||
return '装有液体的容器。'
|
||||
if name == 'lunch_bag':
|
||||
return '存放食物的袋子。'
|
||||
return '合成与回收材料。'
|
||||
|
||||
mats = []
|
||||
with open(os.path.join(BASE, '_sa_materials.csv'), encoding='utf-8-sig') as f:
|
||||
for row in csv.reader(f):
|
||||
if row and row[1].endswith('.png') and row[0].isdigit() and row[1][:-4] not in DROP:
|
||||
mats.append(row[1][:-4])
|
||||
|
||||
updated = 0
|
||||
for m in mats:
|
||||
p = os.path.join(BASE, 'behavior_pack_kcH4M5u0/netease_items_beh/dn_sa_%s.json' % m)
|
||||
d = json.load(open(p, encoding='utf-8'))
|
||||
d['minecraft:item']['components']['netease:customtips'] = {'value': desc(m)}
|
||||
json.dump(d, open(p, 'w', encoding='utf-8'), ensure_ascii=False, indent=4)
|
||||
updated += 1
|
||||
print('beh json 添加 customtips 描述:', updated)
|
||||
|
||||
LP = os.path.join(BASE, 'resource_pack_t7eJjrxY/texts/zh_CN.lang')
|
||||
lines = open(LP, encoding='utf-8').read().splitlines()
|
||||
keep = [l for l in lines if not (l.startswith('item.dn_sa:') and '.desc=' in l)]
|
||||
open(LP, 'w', encoding='utf-8').write('\n'.join(keep) + ('\n' if keep else ''))
|
||||
print('lang 清理 .desc 无效条目:', len(lines) - len(keep), '| 剩余行:', len(keep))
|
||||
|
||||
p = os.path.join(BASE, 'behavior_pack_kcH4M5u0/netease_items_beh/dn_sa_metal_scrap.json')
|
||||
print('示例 metal_scrap components:', json.dumps(json.load(open(p, encoding='utf-8'))['minecraft:item']['components'], ensure_ascii=False))
|
||||
@@ -0,0 +1,29 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""给可饮用液体材料添加饮用功能:beh food 组件 + res drink 动画"""
|
||||
import os, json
|
||||
|
||||
BASE = r'e:\MCStudioDownload\work\3027246179@qq.com\Cpp\AddOn\309c2d420bc84ee986db9cdd070ff02a'
|
||||
DRINKS = ['alcohol', 'rubbing_alcohol', 'cleaning_liquid', 'hair_gel', 'fermented_mash']
|
||||
|
||||
for m in DRINKS:
|
||||
# beh json
|
||||
p = os.path.join(BASE, 'behavior_pack_kcH4M5u0/netease_items_beh/dn_sa_%s.json' % m)
|
||||
d = json.load(open(p, encoding='utf-8'))
|
||||
c = d['minecraft:item']['components']
|
||||
c['minecraft:use_duration'] = 32
|
||||
c['minecraft:food'] = {
|
||||
'nutrition': 2,
|
||||
'saturation_modifier': 'low',
|
||||
'can_always_eat': True
|
||||
}
|
||||
json.dump(d, open(p, 'w', encoding='utf-8'), ensure_ascii=False, indent=4)
|
||||
# res json
|
||||
rp = os.path.join(BASE, 'resource_pack_t7eJjrxY/netease_items_res/dn_sa_%s.json' % m)
|
||||
r = json.load(open(rp, encoding='utf-8'))
|
||||
r['minecraft:item']['components']['minecraft:use_animation'] = 'drink'
|
||||
json.dump(r, open(rp, 'w', encoding='utf-8'), ensure_ascii=False, indent=4)
|
||||
print('已添加饮用功能:', m)
|
||||
|
||||
# 验证
|
||||
p = os.path.join(BASE, 'behavior_pack_kcH4M5u0/netease_items_beh/dn_sa_alcohol.json')
|
||||
print(json.dumps(json.load(open(p, encoding='utf-8'))['minecraft:item']['components'], ensure_ascii=False, indent=1))
|
||||
@@ -0,0 +1,120 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""把 sa_core 76 个材料做成网易版 AddOn 物品:beh json + res json + item_texture + zh_CN.lang + 贴图"""
|
||||
import csv, os, json, shutil
|
||||
|
||||
BASE = r'e:\MCStudioDownload\work\3027246179@qq.com\Cpp\AddOn\309c2d420bc84ee986db9cdd070ff02a'
|
||||
BEH = os.path.join(BASE, 'behavior_pack_kcH4M5u0', 'netease_items_beh')
|
||||
RES = os.path.join(BASE, 'resource_pack_t7eJjrxY', 'netease_items_res')
|
||||
TEX = os.path.join(BASE, 'resource_pack_t7eJjrxY', 'textures', 'items')
|
||||
SRC_TEX = os.path.join(BASE, '_sa_material_textures')
|
||||
ITEM_TEX = os.path.join(BASE, 'resource_pack_t7eJjrxY', 'textures', 'item_texture.json')
|
||||
LANG = os.path.join(BASE, 'resource_pack_t7eJjrxY', 'texts', 'zh_CN.lang')
|
||||
|
||||
# 读取材料清单(序号,贴图文件,物品ID,中文名,英文名,路径)
|
||||
mats = []
|
||||
with open(os.path.join(BASE, '_sa_materials.csv'), encoding='utf-8-sig') as f:
|
||||
for row in csv.reader(f):
|
||||
if row and row[1].endswith('.png') and row[0].isdigit():
|
||||
mats.append((row[1][:-4], row[3])) # (name, zh)
|
||||
|
||||
# 描述:特判字典 + 关键词兜底
|
||||
SPECIAL = {
|
||||
'dirty_water_bottle': '饮用可能引起饥饿',
|
||||
'generator_manual': '学习手册并完成实践训练以操作汽油发电机。',
|
||||
'matchbox': '点燃方块和火焰',
|
||||
'sterilized_rags': '清洁医用布。使用后返还脏抹布',
|
||||
'rope': '可放置且可攀爬,落上时可防止摔落伤害',
|
||||
'jerry_can': '用于储存液体:右键液体源收集,Shift+右键倒出',
|
||||
'saw_blade': '锯子部件,用于制作工具',
|
||||
'money': '战利品货币',
|
||||
'money_bundle': '一捆货币',
|
||||
'blank': '',
|
||||
}
|
||||
META_KEYS = ('ashen_steel_ingot', 'ashen_steel_mixture', 'ashen_steel_nugget', 'ashen_steel_rod',
|
||||
'metal_pipe', 'metal_sheet', 'small_metal_sheet', 'scrap_nugget',
|
||||
'diamond_nugget', 'netherite_nugget')
|
||||
FABRIC_KEYS = ('cloth', 'dirty_rags', 'dish_towel', 'fabric_patch', 'fiber_fabric', 'polyester',
|
||||
'rags', 'sterilized_rags', 'kevlar', 'leather_strip')
|
||||
THREAD_KEYS = ('thread', 'kevlar_thread', 'polyester_thread', 'copper_wire', 'insulated_copper_wire', 'wire')
|
||||
FASTENER_KEYS = ('nails', 'screws', 'box_of_nails', 'box_of_screws', 'box_of_paperclips', 'paperclip')
|
||||
SCRAP_KEYS = ('metal_scrap', 'electric_scrap', 'scrap_wood')
|
||||
PLASTIC_KEYS = ('plastic', 'plastic_bag', 'plastic_plate', 'cardboard')
|
||||
ADHESIVE_KEYS = ('glue', 'medical_adhesive', 'adhesive_tape', 'duct_tape')
|
||||
|
||||
def make_desc(name, zh):
|
||||
if name in SPECIAL:
|
||||
return SPECIAL[name]
|
||||
if name in META_KEYS:
|
||||
return '用于锻造与回收的金属材料。'
|
||||
if name in SCRAP_KEYS:
|
||||
return '可回收利用的材料。'
|
||||
if name in FABRIC_KEYS:
|
||||
return '用于缝制、修复与回收的织物材料。'
|
||||
if name in THREAD_KEYS:
|
||||
return '用于制作与缝合的线材。'
|
||||
if name in FASTENER_KEYS:
|
||||
return '用于组装的紧固件。'
|
||||
if name in PLASTIC_KEYS:
|
||||
return '可用于制作物品的塑料材料。'
|
||||
if name in ADHESIVE_KEYS:
|
||||
return '修复与组装的粘合材料。'
|
||||
if name in ('battery', 'camera', 'cellphone', 'classic_watch', 'falsh_lights'):
|
||||
return '可拆解的电子元件。'
|
||||
if name in ('sulfur', 'sulfur_dust', 'charcoal_dust', 'gunpowder_bottle'):
|
||||
return '可用于制作的化学材料。'
|
||||
if name in ('empty_can', 'dented_can', 'tin_can', 'empty_glass_bottle'):
|
||||
return '空容器,可回收利用。'
|
||||
if name in ('water_bottle', 'water_bottle2', 'alcohol', 'rubbing_alcohol', 'cleaning_liquid',
|
||||
'hair_gel', 'fermented_mash', 'gasoline_bucket'):
|
||||
return '装有液体的容器。'
|
||||
if name in ('lunch_bag',):
|
||||
return '存放食物的袋子。'
|
||||
return '合成与回收材料。'
|
||||
|
||||
# 1) 生成 beh / res json + 复制贴图
|
||||
beh_tpl = {'format_version': '1.10', 'minecraft:item': {
|
||||
'components': {'minecraft:max_stack_size': 64},
|
||||
'description': {'category': 'dn_sa', 'identifier': 'dn_sa:%s'}}}
|
||||
res_tpl = {'format_version': '1.10', 'minecraft:item': {
|
||||
'components': {'minecraft:icon': 'dn_sa:%s'},
|
||||
'description': {'identifier': 'dn_sa:%s'}}}
|
||||
|
||||
count = 0
|
||||
for name, zh in mats:
|
||||
beh_path = os.path.join(BEH, 'dn_sa_%s.json' % name)
|
||||
res_path = os.path.join(RES, 'dn_sa_%s.json' % name)
|
||||
with open(beh_path, 'w', encoding='utf-8') as f:
|
||||
json.dump(beh_tpl, f, ensure_ascii=False, indent=4)
|
||||
with open(res_path, 'w', encoding='utf-8') as f:
|
||||
json.dump(res_tpl, f, ensure_ascii=False, indent=4)
|
||||
shutil.copy2(os.path.join(SRC_TEX, name + '.png'), os.path.join(TEX, name + '.png'))
|
||||
count += 1
|
||||
print('已生成物品 json + 复制贴图:', count)
|
||||
|
||||
# 2) item_texture.json 追加
|
||||
with open(ITEM_TEX, encoding='utf-8') as f:
|
||||
it = json.load(f)
|
||||
added = 0
|
||||
for name, zh in mats:
|
||||
key = 'dn_sa:%s' % name
|
||||
if key not in it['texture_data']:
|
||||
it['texture_data'][key] = {'textures': 'textures/items/%s' % name}
|
||||
added += 1
|
||||
with open(ITEM_TEX, 'w', encoding='utf-8') as f:
|
||||
json.dump(it, f, ensure_ascii=False, indent=4)
|
||||
print('item_texture.json 新增条目:', added, '| 总数:', len(it['texture_data']))
|
||||
|
||||
# 3) zh_CN.lang 追加 name + desc
|
||||
lang = open(LANG, encoding='utf-8').read()
|
||||
lines_added = 0
|
||||
new_lines = []
|
||||
existing = set(lang.splitlines())
|
||||
for name, zh in mats:
|
||||
nk = 'item.dn_sa:%s.name=%s' % (name, zh)
|
||||
dk = 'item.dn_sa:%s.desc=%s' % (name, make_desc(name, zh))
|
||||
if nk not in existing:
|
||||
new_lines.append(nk); new_lines.append(dk); lines_added += 2
|
||||
if new_lines:
|
||||
with open(LANG, 'a', encoding='utf-8') as f:
|
||||
f.write('\n' + '\n'.join(new_lines) + '\n')
|
||||
print('zh_CN.lang 追加条目:', lines_added)
|
||||
@@ -0,0 +1,33 @@
|
||||
import zipfile, os, subprocess
|
||||
|
||||
jar = r'e:\MCStudioDownload\work\3027246179@qq.com\Cpp\AddOn\309c2d420bc84ee986db9cdd070ff02a\_sa_hanhua_out\sa_decor-forge-1.20.1-1.0.3.jar'
|
||||
out = r'e:\MCStudioDownload\work\3027246179@qq.com\Cpp\AddOn\309c2d420bc84ee986db9cdd070ff02a\_sa_hanhua_out\_tmp\classes'
|
||||
|
||||
targets = [
|
||||
'com/ogaba/sa_decor/command/SADecorLootCommand.class',
|
||||
'com/ogaba/sa_decor/common/loot/DecorLootConfigManager.class',
|
||||
]
|
||||
|
||||
with zipfile.ZipFile(jar) as z:
|
||||
for t in targets:
|
||||
p = os.path.join(out, t.replace('/', os.sep))
|
||||
os.makedirs(os.path.dirname(p), exist_ok=True)
|
||||
with open(p, 'wb') as f:
|
||||
f.write(z.read(t))
|
||||
print('extracted:', t)
|
||||
|
||||
javap = r'D:\我的世界\bin\javap.EXE'
|
||||
for t in targets:
|
||||
cname = t[:-6].replace('/', '.')
|
||||
r = subprocess.run([javap, '-c', '-p', '-classpath', out, cname], capture_output=True, text=True, encoding='utf-8', errors='replace')
|
||||
text = r.stdout if r.returncode == 0 else r.stderr
|
||||
with open(os.path.join(out, cname.replace('.', '_') + '.txt'), 'w', encoding='utf-8') as f:
|
||||
f.write(text)
|
||||
print('\n=====', cname, '=====')
|
||||
# 输出含 Survivor 的行上下文
|
||||
lines = text.splitlines()
|
||||
for i, line in enumerate(lines):
|
||||
if 'Survivor' in line or 'Arsenal' in line:
|
||||
for j in range(max(0, i-2), min(len(lines), i+4)):
|
||||
print(lines[j])
|
||||
print('---')
|
||||
@@ -0,0 +1,18 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from PIL import Image
|
||||
import os
|
||||
base = r"e:\MCStudioDownload\work\3027246179@qq.com\Cpp\AddOn\309c2d420bc84ee986db9cdd070ff02a\resource_pack_t7eJjrxY\textures\items"
|
||||
|
||||
# 打印若干物品贴图尺寸对比
|
||||
for n in ["burrito", "burrito_rotten", "hot_dog", "taco", "jianbing"]:
|
||||
p = os.path.join(base, n + ".png")
|
||||
if os.path.exists(p):
|
||||
im = Image.open(p)
|
||||
print(n, im.size, im.mode, os.path.getsize(p))
|
||||
|
||||
# 校验 jianbing 是否是有效完整PNG且内容是煎饼(采样角点颜色)
|
||||
p = os.path.join(base, "jianbing.png")
|
||||
im = Image.open(p)
|
||||
im.load()
|
||||
print("jianbing corners:", im.getpixel((0,0)), im.getpixel((15,0)), im.getpixel((0,15)), im.getpixel((15,15)))
|
||||
print("jianbing center:", im.getpixel((8,8)))
|
||||
@@ -0,0 +1,21 @@
|
||||
import zipfile
|
||||
|
||||
base = r'e:\MCStudioDownload\work\3027246179@qq.com\Cpp\AddOn\309c2d420bc84ee986db9cdd070ff02a\_sa_hanhua_out'
|
||||
jars = {
|
||||
'essentials': base + r'\sa_essentials-forge-1.20.1-1.0.0.jar',
|
||||
'lib': base + r'\sa_lib-forge-1.20.1-1.0.1.jar',
|
||||
'decor': base + r'\sa_decor-forge-1.20.1-1.0.3.jar',
|
||||
}
|
||||
|
||||
import json
|
||||
for name, jar in jars.items():
|
||||
print('='*30, name, '='*30)
|
||||
with zipfile.ZipFile(jar) as z:
|
||||
for n in z.namelist():
|
||||
if n.startswith('assets/') and n.endswith('/lang/zh_cn.json'):
|
||||
data = json.loads(z.read(n).decode('utf-8'))
|
||||
print('---', n, '---')
|
||||
for k, v in data.items():
|
||||
if 'mod' in k or 'arsenal' in k.lower() or 'survivor' in k.lower() or 'creative' in k or 'tab' in k:
|
||||
print(f' {k} = {v}')
|
||||
print()
|
||||
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
Binary file not shown.
BIN
Binary file not shown.
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
Binary file not shown.
BIN
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
Binary file not shown.
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
Binary file not shown.
BIN
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
Binary file not shown.
Binary file not shown.
BIN
Binary file not shown.
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
File diff suppressed because it is too large.
Load diff
+5620
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,175 @@
|
||||
== com.ogaba.sa_combat.client.event.SACombatClientForgeEvents ==
|
||||
item.durability
|
||||
[a-z0-9_.-]+:[a-z0-9_./-]+
|
||||
item.modifiers.mainhand
|
||||
attack damage
|
||||
attack speed
|
||||
attack range
|
||||
entity reach
|
||||
attack knockback
|
||||
dano de ataque
|
||||
velocidade de ataque
|
||||
alcance de ataque
|
||||
repuls
|
||||
knockback
|
||||
when in main hand
|
||||
main hand
|
||||
m?o principal
|
||||
mao principal
|
||||
%.2f
|
||||
������...
|
||||
renderSpyglassOverlay
|
||||
== com.ogaba.sa_combat.client.render.PlayerArmSkinLayer ==
|
||||
root
|
||||
base
|
||||
slim
|
||||
right_hand_wide
|
||||
right_hand_slim
|
||||
left_hand_wide
|
||||
left_hand_slim
|
||||
== com.ogaba.sa_combat.client.render.SAWeaponItemRenderer ==
|
||||
idle_view
|
||||
camera
|
||||
right_hand_wide
|
||||
left_hand_wide
|
||||
right_hand_slim
|
||||
left_hand_slim
|
||||
spyglass
|
||||
== com.ogaba.sa_combat.client.render.SpecialGrenadeItemRenderer ==
|
||||
camera
|
||||
idle_view
|
||||
held_item
|
||||
granade
|
||||
right_hand
|
||||
left_hand
|
||||
right_hand_wide
|
||||
left_hand_wide
|
||||
right_hand_slim
|
||||
left_hand_slim
|
||||
item/pipe_bomb_visual
|
||||
item/nail_bomb_visual
|
||||
item/molotov_visual
|
||||
== com.ogaba.sa_combat.client.render.SpecialGrenadePlayerArmSkinLayer ==
|
||||
main
|
||||
right
|
||||
left
|
||||
right_hand
|
||||
left_hand
|
||||
granade
|
||||
camera
|
||||
right_hand_wide
|
||||
right_hand_slim
|
||||
left_hand_wide
|
||||
left_hand_slim
|
||||
slim
|
||||
== com.ogaba.sa_combat.client.tooltip.BlueprintClientTooltipComponent ==
|
||||
tooltip.sa_combat.blueprint.unknown
|
||||
Unknown Unlock
|
||||
tooltip.sa_combat.blueprint.check_data
|
||||
Check blueprint data
|
||||
tooltip.sa_combat.blueprint.unlock
|
||||
Unlock
|
||||
tooltip.sa_combat.blueprint.recipe_unlock
|
||||
Recipe Unlock
|
||||
����
|
||||
tooltip.sa_combat.blueprint.no_abilities
|
||||
No abilities
|
||||
tooltip.sa_combat.blueprint.on_hit
|
||||
On Hit
|
||||
����
|
||||
bettercombat
|
||||
attack_range
|
||||
����
|
||||
����
|
||||
%.1f
|
||||
== com.ogaba.sa_combat.client.tooltip.WeaponClientTooltipComponent ==
|
||||
tooltip.sa_combat.modifier_section
|
||||
tooltip.sa_combat.on_hit
|
||||
tooltip.sa_combat.empty_socket
|
||||
== com.ogaba.sa_combat.event.SACombatForgeEvents ==
|
||||
SA Combat TACZ vest bullet resistance
|
||||
SA Combat weapon upgrade damage
|
||||
SA Combat weapon upgrade speed
|
||||
SA Combat weapon upgrade knockback
|
||||
SA Combat weapon upgrade reach
|
||||
SACombatLastShieldThornsTick
|
||||
SACombatLastShieldThornsTick
|
||||
spiked
|
||||
13a24b02-d971-4ee7-879c-1c7068a6bb71
|
||||
457d3b0c-c7b7-43a4-8395-01f82ec1bdb2
|
||||
df109f67-5b6d-4de4-9a1b-c75443c0f1b2
|
||||
9d46b9e9-46cb-4ab3-b2a0-c0e331cce312
|
||||
11d92754-4e96-4c9e-9b25-d8945bc43b24
|
||||
tacz
|
||||
tacz.bullet_resistance
|
||||
== com.ogaba.sa_survival.client.BackpackGuiKeyHandler ==
|
||||
key.sa_combat.open_backpack_gui
|
||||
key.categories.sa_combat
|
||||
== com.ogaba.sa_survival.client.BackpackInventoryPanelOverlay$SlotVisualState ==
|
||||
NONE
|
||||
ACTIVE
|
||||
LOCKED
|
||||
EMPTY
|
||||
== com.ogaba.sa_survival.client.BackpackInventoryPanelOverlay ==
|
||||
pink
|
||||
blue
|
||||
jeans
|
||||
green
|
||||
yellow
|
||||
desert
|
||||
black
|
||||
camo
|
||||
olive
|
||||
military
|
||||
tactical
|
||||
vest
|
||||
jacket
|
||||
leather
|
||||
brown
|
||||
shirt
|
||||
f_40220_
|
||||
f_40221_
|
||||
[SA Survival] Could not access Slot position fields for modular inventory slots.
|
||||
����
|
||||
�������IJ�λ
|
||||
�˱�����ʹ�õIJ�λ
|
||||
screen.sa_combat.utility_panel.close
|
||||
screen.sa_combat.utility_panel.open
|
||||
== com.ogaba.sa_survival.client.renderer.BackpackCurioRenderer$WeaponMountSide ==
|
||||
RIGHT
|
||||
LEFT
|
||||
== com.ogaba.sa_survival.client.renderer.BackpackCurioRenderer ==
|
||||
SatchelCurioRender
|
||||
Expected 3 double values
|
||||
Expected 3 float values
|
||||
== com.ogaba.sa_survival.client.renderer.FlashlightItemRenderer ==
|
||||
right_hand_wide
|
||||
right_hand_slim
|
||||
left_hand_wide
|
||||
left_hand_slim
|
||||
item/flashlight_emissive
|
||||
== com.ogaba.sa_survival.client.tooltip.ClientBackpackContentsTooltip ==
|
||||
pink
|
||||
yellow
|
||||
desert
|
||||
blue
|
||||
jeans
|
||||
green
|
||||
camo
|
||||
black
|
||||
jacket
|
||||
vest
|
||||
== com.ogaba.sa_survival.event.ExternalEquipmentStorageTooltipEvents ==
|
||||
extra slots
|
||||
��סShift��Ԥ������
|
||||
��סShift��Ԥ������
|
||||
== com.ogaba.sa_survival.item.tooltip.BackpackContentsTooltip ==
|
||||
Items
|
||||
ClothingItems
|
||||
== com.ogaba.sa_survival.item.tooltip.EffectTooltipUtil ==
|
||||
tooltip.sa_combat.effects
|
||||
tooltip.sa_combat.removes_poison
|
||||
tooltip.sa_combat.removes_bleeding
|
||||
tooltip.sa_combat.heals_amount
|
||||
potion.withAmplifier
|
||||
potion.withDuration
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,28 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""剔除 cellphone(手机,带模型)"""
|
||||
import os, json
|
||||
|
||||
BASE = r'e:\MCStudioDownload\work\3027246179@qq.com\Cpp\AddOn\309c2d420bc84ee986db9cdd070ff02a'
|
||||
DROP = ['cellphone']
|
||||
|
||||
for sub in ['behavior_pack_kcH4M5u0/netease_items_beh', 'resource_pack_t7eJjrxY/netease_items_res']:
|
||||
for m in DROP:
|
||||
p = os.path.join(BASE, sub, 'dn_sa_%s.json' % m)
|
||||
if os.path.exists(p):
|
||||
os.remove(p)
|
||||
p = os.path.join(BASE, 'resource_pack_t7eJjrxY/textures/items/cellphone.png')
|
||||
if os.path.exists(p):
|
||||
os.remove(p)
|
||||
|
||||
IP = os.path.join(BASE, 'resource_pack_t7eJjrxY/textures/item_texture.json')
|
||||
it = json.load(open(IP, encoding='utf-8'))
|
||||
it['texture_data'].pop('dn_sa:cellphone', None)
|
||||
json.dump(it, open(IP, 'w', encoding='utf-8'), ensure_ascii=False, indent=4)
|
||||
|
||||
LP = os.path.join(BASE, 'resource_pack_t7eJjrxY/texts/zh_CN.lang')
|
||||
lines = open(LP, encoding='utf-8').read().splitlines()
|
||||
keep = [l for l in lines if not l.startswith('item.dn_sa:cellphone.')]
|
||||
open(LP, 'w', encoding='utf-8').write('\n'.join(keep) + ('\n' if keep else ''))
|
||||
|
||||
beh = [f for f in os.listdir(os.path.join(BASE, 'behavior_pack_kcH4M5u0/netease_items_beh')) if f.endswith('.json')]
|
||||
print('beh json 总数:', len(beh), '| 材料数:', len(beh) - 44)
|
||||
@@ -0,0 +1,28 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""剔除 dirty_water_bottle(脏水瓶,带模型)"""
|
||||
import os, json
|
||||
|
||||
BASE = r'e:\MCStudioDownload\work\3027246179@qq.com\Cpp\AddOn\309c2d420bc84ee986db9cdd070ff02a'
|
||||
DROP = ['dirty_water_bottle']
|
||||
|
||||
for sub in ['behavior_pack_kcH4M5u0/netease_items_beh', 'resource_pack_t7eJjrxY/netease_items_res']:
|
||||
for m in DROP:
|
||||
p = os.path.join(BASE, sub, 'dn_sa_%s.json' % m)
|
||||
if os.path.exists(p):
|
||||
os.remove(p)
|
||||
p = os.path.join(BASE, 'resource_pack_t7eJjrxY/textures/items/dirty_water_bottle.png')
|
||||
if os.path.exists(p):
|
||||
os.remove(p)
|
||||
|
||||
IP = os.path.join(BASE, 'resource_pack_t7eJjrxY/textures/item_texture.json')
|
||||
it = json.load(open(IP, encoding='utf-8'))
|
||||
it['texture_data'].pop('dn_sa:dirty_water_bottle', None)
|
||||
json.dump(it, open(IP, 'w', encoding='utf-8'), ensure_ascii=False, indent=4)
|
||||
|
||||
LP = os.path.join(BASE, 'resource_pack_t7eJjrxY/texts/zh_CN.lang')
|
||||
lines = open(LP, encoding='utf-8').read().splitlines()
|
||||
keep = [l for l in lines if not l.startswith('item.dn_sa:dirty_water_bottle.')]
|
||||
open(LP, 'w', encoding='utf-8').write('\n'.join(keep) + ('\n' if keep else ''))
|
||||
|
||||
beh = [f for f in os.listdir(os.path.join(BASE, 'behavior_pack_kcH4M5u0/netease_items_beh')) if f.endswith('.json')]
|
||||
print('beh json 总数:', len(beh), '| 材料数:', len(beh) - 44)
|
||||
@@ -0,0 +1,28 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""剔除 jerry_can(油桶,带模型)"""
|
||||
import os, json
|
||||
|
||||
BASE = r'e:\MCStudioDownload\work\3027246179@qq.com\Cpp\AddOn\309c2d420bc84ee986db9cdd070ff02a'
|
||||
DROP = ['jerry_can']
|
||||
|
||||
for sub in ['behavior_pack_kcH4M5u0/netease_items_beh', 'resource_pack_t7eJjrxY/netease_items_res']:
|
||||
for m in DROP:
|
||||
p = os.path.join(BASE, sub, 'dn_sa_%s.json' % m)
|
||||
if os.path.exists(p):
|
||||
os.remove(p)
|
||||
p = os.path.join(BASE, 'resource_pack_t7eJjrxY/textures/items/jerry_can.png')
|
||||
if os.path.exists(p):
|
||||
os.remove(p)
|
||||
|
||||
IP = os.path.join(BASE, 'resource_pack_t7eJjrxY/textures/item_texture.json')
|
||||
it = json.load(open(IP, encoding='utf-8'))
|
||||
it['texture_data'].pop('dn_sa:jerry_can', None)
|
||||
json.dump(it, open(IP, 'w', encoding='utf-8'), ensure_ascii=False, indent=4)
|
||||
|
||||
LP = os.path.join(BASE, 'resource_pack_t7eJjrxY/texts/zh_CN.lang')
|
||||
lines = open(LP, encoding='utf-8').read().splitlines()
|
||||
keep = [l for l in lines if not l.startswith('item.dn_sa:jerry_can.')]
|
||||
open(LP, 'w', encoding='utf-8').write('\n'.join(keep) + ('\n' if keep else ''))
|
||||
|
||||
beh = [f for f in os.listdir(os.path.join(BASE, 'behavior_pack_kcH4M5u0/netease_items_beh')) if f.endswith('.json')]
|
||||
print('beh json 总数:', len(beh), '| 材料数:', len(beh) - 44)
|
||||
@@ -0,0 +1,45 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""剔除 water_bottle / water_bottle2 / blank 三个材料(水瓶带模型、空白为占位物品)"""
|
||||
import os, json
|
||||
|
||||
BASE = r'e:\MCStudioDownload\work\3027246179@qq.com\Cpp\AddOn\309c2d420bc84ee986db9cdd070ff02a'
|
||||
DROP = ['water_bottle', 'water_bottle2', 'blank']
|
||||
|
||||
# 1) 删 beh/res json + 贴图
|
||||
for sub in ['behavior_pack_kcH4M5u0/netease_items_beh', 'resource_pack_t7eJjrxY/netease_items_res']:
|
||||
for m in DROP:
|
||||
p = os.path.join(BASE, sub, 'dn_sa_%s.json' % m)
|
||||
if os.path.exists(p):
|
||||
os.remove(p)
|
||||
print('删', sub.split('/')[-1], m)
|
||||
for m in DROP:
|
||||
p = os.path.join(BASE, 'resource_pack_t7eJjrxY/textures/items/%s.png' % m)
|
||||
if os.path.exists(p):
|
||||
os.remove(p)
|
||||
print('删贴图', m)
|
||||
|
||||
# 2) item_texture.json 移除
|
||||
IP = os.path.join(BASE, 'resource_pack_t7eJjrxY/textures/item_texture.json')
|
||||
it = json.load(open(IP, encoding='utf-8'))
|
||||
for m in DROP:
|
||||
it['texture_data'].pop('dn_sa:%s' % m, None)
|
||||
json.dump(it, open(IP, 'w', encoding='utf-8'), ensure_ascii=False, indent=4)
|
||||
print('item_texture 移除后条数:', len(it['texture_data']))
|
||||
|
||||
# 3) zh_CN.lang 移除 name 行
|
||||
LP = os.path.join(BASE, 'resource_pack_t7eJjrxY/texts/zh_CN.lang')
|
||||
lines = open(LP, encoding='utf-8').read().splitlines()
|
||||
keep = []
|
||||
removed = 0
|
||||
for l in lines:
|
||||
if any(('item.dn_sa:%s.' % m) in l for m in DROP):
|
||||
removed += 1
|
||||
continue
|
||||
keep.append(l)
|
||||
open(LP, 'w', encoding='utf-8').write('\n'.join(keep) + ('\n' if keep else ''))
|
||||
print('lang 移除行:', removed, '| 剩余行:', len(keep))
|
||||
|
||||
# 4) 最终数量
|
||||
beh = [f for f in os.listdir(os.path.join(BASE, 'behavior_pack_kcH4M5u0/netease_items_beh')) if f.endswith('.json')]
|
||||
print('beh json 总数:', len(beh))
|
||||
print('材料数:', len(beh) - 44)
|
||||
@@ -0,0 +1,23 @@
|
||||
import zipfile, json, os
|
||||
|
||||
base = r"e:\MCStudioDownload\work\3027246179@qq.com\Cpp\AddOn\309c2d420bc84ee986db9cdd070ff02a\_sa_hanhua_out"
|
||||
jar = os.path.join(base, "sa_decor-forge-1.20.1-1.0.3.jar")
|
||||
|
||||
def load(z, n):
|
||||
return json.loads(z.read(n).decode('utf-8'))
|
||||
|
||||
with zipfile.ZipFile(jar) as z:
|
||||
en = load(z, "assets/sa_decor/lang/en_us.json")
|
||||
pt = load(z, "assets/sa_decor/lang/pt_br.json")
|
||||
zh = load(z, "assets/sa_decor/lang/zh_cn.json")
|
||||
|
||||
keys = sorted(set(en) | set(pt) | set(zh))
|
||||
out = []
|
||||
for k in keys:
|
||||
e = en.get(k, "")
|
||||
p = pt.get(k, "")
|
||||
c = zh.get(k, "")
|
||||
out.append(f"{k}\n EN: {e}\n PT: {p}\n ZH: {c}")
|
||||
with open(os.path.join(base, "_tmp", "decor_lang.txt"), "w", encoding="utf-8") as f:
|
||||
f.write("\n".join(out))
|
||||
f.write(f"\nTOTAL {len(keys)}\n")
|
||||
@@ -0,0 +1,12 @@
|
||||
import zipfile, json, sys, io, os
|
||||
|
||||
base = r"e:\MCStudioDownload\work\3027246179@qq.com\Cpp\AddOn\309c2d420bc84ee986db9cdd070ff02a\_sa_hanhua_out"
|
||||
jars = [f for f in os.listdir(base) if f.endswith('.jar')]
|
||||
|
||||
for j in jars:
|
||||
p = os.path.join(base, j)
|
||||
print("=" * 30, j)
|
||||
with zipfile.ZipFile(p) as z:
|
||||
names = [n for n in z.namelist() if '/lang/' in n]
|
||||
for n in names:
|
||||
print(" ", n)
|
||||
@@ -0,0 +1,25 @@
|
||||
import zipfile, os, subprocess
|
||||
|
||||
jar = r'e:\MCStudioDownload\work\3027246179@qq.com\Cpp\AddOn\309c2d420bc84ee986db9cdd070ff02a\_sa_hanhua_out\sa_essentials-forge-1.20.1-1.0.0.jar'
|
||||
out = r'e:\MCStudioDownload\work\3027246179@qq.com\Cpp\AddOn\309c2d420bc84ee986db9cdd070ff02a\_sa_hanhua_out\_tmp\classes'
|
||||
|
||||
targets = [
|
||||
'com/ogaba/sa_survival/item/tooltip/BackpackContentsTooltip.class',
|
||||
'com/ogaba/sa_survival/event/ExternalEquipmentStorageTooltipEvents.class',
|
||||
'com/ogaba/sa_combat/event/SACombatForgeEvents.class',
|
||||
]
|
||||
|
||||
javap = r'D:\我的世界\bin\javap.EXE'
|
||||
for t in targets:
|
||||
p = os.path.join(out, t.replace('/', os.sep))
|
||||
os.makedirs(os.path.dirname(p), exist_ok=True)
|
||||
with zipfile.ZipFile(jar) as z:
|
||||
with open(p, 'wb') as f:
|
||||
f.write(z.read(t))
|
||||
cname = t[:-6].replace('/', '.')
|
||||
r = subprocess.run([javap, '-c', '-p', '-classpath', out, cname], capture_output=True, text=True, encoding='utf-8', errors='replace')
|
||||
text = r.stdout if r.returncode == 0 else r.stderr
|
||||
fn = r'e:\MCStudioDownload\work\3027246179@qq.com\Cpp\AddOn\309c2d420bc84ee986db9cdd070ff02a\_sa_hanhua_out\_tmp\javap_%s.txt' % cname.rsplit('.',1)[-1]
|
||||
with open(fn, 'w', encoding='utf-8') as f:
|
||||
f.write(text)
|
||||
print('==', cname, 'written:', fn)
|
||||
@@ -0,0 +1,45 @@
|
||||
import zipfile, os, subprocess, shutil
|
||||
|
||||
jar = r'e:\MCStudioDownload\work\3027246179@qq.com\Cpp\AddOn\309c2d420bc84ee986db9cdd070ff02a\_sa_hanhua_out\sa_essentials-forge-1.20.1-1.0.0.jar'
|
||||
out = r'e:\MCStudioDownload\work\3027246179@qq.com\Cpp\AddOn\309c2d420bc84ee986db9cdd070ff02a\_sa_hanhua_out\_tmp\classes'
|
||||
os.makedirs(out, exist_ok=True)
|
||||
|
||||
targets = [
|
||||
'com/ogaba/sa_combat/client/tooltip/BlueprintClientTooltipComponent.class',
|
||||
'com/ogaba/sa_combat/client/tooltip/BlueprintClientTooltipComponent$1.class',
|
||||
'com/ogaba/sa_combat/item/BlueprintTooltipComponent.class',
|
||||
'com/ogaba/sa_combat/item/BlueprintItem.class',
|
||||
'com/ogaba/sa_combat/blueprint/BlueprintDefinitionRegistry$Definition.class',
|
||||
'com/ogaba/sa_combat/blueprint/BlueprintDefinitionRegistry.class',
|
||||
]
|
||||
|
||||
with zipfile.ZipFile(jar) as z:
|
||||
for t in targets:
|
||||
data = z.read(t)
|
||||
p = os.path.join(out, t.replace('/', os.sep))
|
||||
os.makedirs(os.path.dirname(p), exist_ok=True)
|
||||
with open(p, 'wb') as f:
|
||||
f.write(data)
|
||||
print('extracted:', t)
|
||||
|
||||
# javap 反编译查看渲染逻辑
|
||||
javap = shutil.which('javap')
|
||||
if javap is None:
|
||||
# 尝试常见 JDK 路径
|
||||
for cand in [r'C:\Program Files\Java\jdk-17\bin\javap.exe',
|
||||
r'C:\Program Files\Java\jdk-21\bin\javap.exe',
|
||||
r'C:\Program Files\Microsoft\jdk-17.0.11\bin\javap.exe',
|
||||
r'C:\Program Files\Eclipse Adoptium\jdk-17.0.13.11-hotspot\bin\javap.exe']:
|
||||
if os.path.exists(cand):
|
||||
javap = cand
|
||||
break
|
||||
print('javap =', javap)
|
||||
|
||||
if javap:
|
||||
for t in targets:
|
||||
cname = t[:-6].replace('/', '.')
|
||||
r = subprocess.run([javap, '-c', '-p', '-classpath', out, cname], capture_output=True, text=True, encoding='utf-8', errors='replace')
|
||||
print('\n' + '='*20, cname, '='*20)
|
||||
print(r.stdout[:6000] if r.returncode == 0 else r.stderr[:3000])
|
||||
else:
|
||||
print('javap NOT FOUND')
|
||||
@@ -0,0 +1,40 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import zipfile, os, subprocess
|
||||
|
||||
jars = [
|
||||
r"e:\MCStudioDownload\work\3027246179@qq.com\Cpp\AddOn\309c2d420bc84ee986db9cdd070ff02a\_sa_hanhua_out\sa_core-forge-1.20.1-1.0.1.jar",
|
||||
r"e:\MCStudioDownload\work\3027246179@qq.com\Cpp\AddOn\309c2d420bc84ee986db9cdd070ff02a\_sa_hanhua_out\sa_lib-forge-1.20.1-1.0.1.jar",
|
||||
r"e:\MCStudioDownload\work\3027246179@qq.com\Cpp\AddOn\309c2d420bc84ee986db9cdd070ff02a\_sa_hanhua_out\sa_decor-forge-1.20.1-1.0.3.jar",
|
||||
r"e:\MCStudioDownload\work\3027246179@qq.com\Cpp\AddOn\309c2d420bc84ee986db9cdd070ff02a\_sa_hanhua_out\sa_essentials-forge-1.20.1-1.0.0.jar",
|
||||
]
|
||||
|
||||
TARGET = "com/ogaba/sacore/content/item/tool/MatchboxItem.class"
|
||||
OUT = r"C:\Users\30272\AppData\Local\Temp\sa_check\javap_jar\out"
|
||||
|
||||
found = None
|
||||
for j in jars:
|
||||
if os.path.exists(j):
|
||||
try:
|
||||
with zipfile.ZipFile(j) as z:
|
||||
for n in z.namelist():
|
||||
if n.endswith("MatchboxItem.class") and "tool" in n:
|
||||
found = (j, n)
|
||||
print("FOUND in", j, "->", n)
|
||||
break
|
||||
except Exception as e:
|
||||
print("ERR", j, e)
|
||||
|
||||
if found:
|
||||
jar, name = found
|
||||
dstdir = os.path.join(OUT, "com", "ogaba", "sacore", "content", "item", "tool")
|
||||
os.makedirs(dstdir, exist_ok=True)
|
||||
dst = os.path.join(dstdir, "MatchboxItem.class")
|
||||
with zipfile.ZipFile(jar) as z:
|
||||
with z.open(name) as src, open(dst, "wb") as out_f:
|
||||
out_f.write(src.read())
|
||||
print("EXTRACTED to", dst)
|
||||
cfr = r"C:\Users\30272\AppData\Local\Temp\sa_check\javap_jar\cfr.jar"
|
||||
r = subprocess.run(["java", "-jar", cfr, dst, "--outputdir", dstdir],
|
||||
capture_output=True, text=True, timeout=120)
|
||||
print("CFR stdout:", r.stdout[-2000:] if r.stdout else "")
|
||||
print("CFR stderr:", r.stderr[-2000:] if r.stderr else "")
|
||||
@@ -0,0 +1,34 @@
|
||||
import zipfile, re
|
||||
|
||||
base = r'e:\MCStudioDownload\work\3027246179@qq.com\Cpp\AddOn\309c2d420bc84ee986db9cdd070ff02a\_sa_hanhua_out'
|
||||
jars = {
|
||||
'essentials': base + r'\sa_essentials-forge-1.20.1-1.0.0.jar',
|
||||
'lib': base + r'\sa_lib-forge-1.20.1-1.0.1.jar',
|
||||
'decor': base + r'\sa_decor-forge-1.20.1-1.0.3.jar',
|
||||
}
|
||||
|
||||
pat = re.compile(r"Survivors?\s+Arsenal", re.IGNORECASE)
|
||||
for name, jar in jars.items():
|
||||
hits = []
|
||||
with zipfile.ZipFile(jar) as z:
|
||||
for n in z.namelist():
|
||||
if n.endswith('/') or n.endswith('.png'):
|
||||
continue
|
||||
if n.endswith('.class'):
|
||||
try:
|
||||
b = z.read(n)
|
||||
# class 文件只查 ASCII 字符串
|
||||
s = ''.join(chr(c) for c in b if 32 <= c < 127 or c in (9, 10, 13))
|
||||
except Exception:
|
||||
continue
|
||||
else:
|
||||
try:
|
||||
s = z.read(n).decode('utf-8', errors='ignore')
|
||||
except Exception:
|
||||
continue
|
||||
if pat.search(s):
|
||||
hits.append(n)
|
||||
print(f'[{name}] 英文 mod 名残留(除 lang 文件): {len(hits)} 个')
|
||||
for h in hits:
|
||||
if not ('/lang/' in h):
|
||||
print(' ', h)
|
||||
@@ -0,0 +1,31 @@
|
||||
import zipfile, json, os
|
||||
|
||||
base = r"e:\MCStudioDownload\work\3027246179@qq.com\Cpp\AddOn\309c2d420bc84ee986db9cdd070ff02a\_sa_hanhua_out"
|
||||
tokens = ["pastel","coxinha","brigadeiro","pacoquita","wind","chips","cheese_bread",
|
||||
"cereal","cracker","guarana","duff","burger","hot_dog","taco","donut","waffle",
|
||||
"biscuit","toast","burrito","candy","jam","cheese","butter","peanut","granola",
|
||||
"energy","vodka","whiskey","wine","beer","cola","pepsi","fanta","monster","coffee"]
|
||||
|
||||
langs = {
|
||||
"sa_decor-forge-1.20.1-1.0.3.jar": "assets/sa_decor/lang/",
|
||||
"sa_essentials-forge-1.20.1-1.0.0.jar": "assets/sa_combat/lang/",
|
||||
"sa_lib-forge-1.20.1-1.0.1.jar": "assets/sa_core/lang/",
|
||||
}
|
||||
|
||||
lines = []
|
||||
for jar, langdir in langs.items():
|
||||
p = os.path.join(base, jar)
|
||||
with zipfile.ZipFile(p) as z:
|
||||
names = set(z.namelist())
|
||||
en = json.loads(z.read(langdir + "en_us.json").decode('utf-8')) if langdir + "en_us.json" in names else {}
|
||||
pt = json.loads(z.read(langdir + "pt_br.json").decode('utf-8')) if langdir + "pt_br.json" in names else {}
|
||||
zh = json.loads(z.read(langdir + "zh_cn.json").decode('utf-8')) if langdir + "zh_cn.json" in names else {}
|
||||
hits = [k for k in (set(en) | set(pt) | set(zh))
|
||||
if any(t in k.lower() or t in str(en.get(k,'')).lower() or t in str(pt.get(k,'')).lower() for t in tokens)]
|
||||
lines.append("=" * 30 + " " + jar + f" hits={len(hits)}")
|
||||
for k in sorted(hits):
|
||||
lines.append(f"{k}\n EN: {en.get(k,'')}\n PT: {pt.get(k,'')}\n ZH: {zh.get(k,'')}")
|
||||
|
||||
with open(os.path.join(base, "_tmp", "food_all.txt"), "w", encoding="utf-8") as f:
|
||||
f.write("\n".join(lines))
|
||||
print("done")
|
||||
@@ -0,0 +1,16 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import os, glob, shutil
|
||||
d = r"e:\MCStudioDownload\work\3027246179@qq.com\Cpp\AddOn\309c2d420bc84ee986db9cdd070ff02a\resource_pack_t7eJjrxY\textures\items"
|
||||
# listdir 返回磁盘上的真实文件名(保留大小写)
|
||||
names = os.listdir(d)
|
||||
print("all *ianbing* in dir:", [n for n in names if "ianbing" in n.lower() and n.lower().endswith(".png")])
|
||||
target = os.path.join(d, "jianbing.png")
|
||||
for n in names:
|
||||
if n.lower() == "jianbing.png" and n != "jianbing.png":
|
||||
src = os.path.join(d, n)
|
||||
# 复制到小写目标(覆盖),再删除大小写不同的旧名
|
||||
shutil.copyfile(src, target)
|
||||
os.remove(src)
|
||||
print("normalized", n, "->", "jianbing.png")
|
||||
print("final files:", [os.path.basename(x) for x in glob.glob(d + r"\*ianbing*.png")])
|
||||
print("lowercase exists:", os.path.exists(target))
|
||||
@@ -0,0 +1,37 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""对齐 Java 版饮用效果:3 个有毒饮品加中毒+反胃;发胶/发酵糊移除饮用功能"""
|
||||
import os, json
|
||||
|
||||
BASE = r'e:\MCStudioDownload\work\3027246179@qq.com\Cpp\AddOn\309c2d420bc84ee986db9cdd070ff02a'
|
||||
TOXIC = ['alcohol', 'rubbing_alcohol', 'cleaning_liquid']
|
||||
PLAIN = ['hair_gel', 'fermented_mash']
|
||||
|
||||
# 1) 3 个有毒饮品:food 加 effects(中毒 II 10s + 反胃 15s)
|
||||
for m in TOXIC:
|
||||
p = os.path.join(BASE, 'behavior_pack_kcH4M5u0/netease_items_beh/dn_sa_%s.json' % m)
|
||||
d = json.load(open(p, encoding='utf-8'))
|
||||
c = d['minecraft:item']['components']
|
||||
c['minecraft:food']['effects'] = [
|
||||
{'name': 'poison', 'chance': 1.0, 'duration': 10, 'amplifier': 1},
|
||||
{'name': 'nausea', 'chance': 1.0, 'duration': 15, 'amplifier': 0}
|
||||
]
|
||||
json.dump(d, open(p, 'w', encoding='utf-8'), ensure_ascii=False, indent=4)
|
||||
print('加效果:', m)
|
||||
|
||||
# 2) 发胶/发酵糊:移除饮用功能(恢复普通物品)
|
||||
for m in PLAIN:
|
||||
p = os.path.join(BASE, 'behavior_pack_kcH4M5u0/netease_items_beh/dn_sa_%s.json' % m)
|
||||
d = json.load(open(p, encoding='utf-8'))
|
||||
c = d['minecraft:item']['components']
|
||||
c.pop('minecraft:food', None)
|
||||
c.pop('minecraft:use_duration', None)
|
||||
json.dump(d, open(p, 'w', encoding='utf-8'), ensure_ascii=False, indent=4)
|
||||
rp = os.path.join(BASE, 'resource_pack_t7eJjrxY/netease_items_res/dn_sa_%s.json' % m)
|
||||
r = json.load(open(rp, encoding='utf-8'))
|
||||
r['minecraft:item']['components'].pop('minecraft:use_animation', None)
|
||||
json.dump(r, open(rp, 'w', encoding='utf-8'), ensure_ascii=False, indent=4)
|
||||
print('移除饮用:', m)
|
||||
|
||||
# 验证
|
||||
p = os.path.join(BASE, 'behavior_pack_kcH4M5u0/netease_items_beh/dn_sa_alcohol.json')
|
||||
print(json.dumps(json.load(open(p, encoding='utf-8'))['minecraft:item']['components'], ensure_ascii=False))
|
||||
@@ -0,0 +1,34 @@
|
||||
import zipfile, os, re, shutil
|
||||
|
||||
jar = r'e:\MCStudioDownload\work\3027246179@qq.com\Cpp\AddOn\309c2d420bc84ee986db9cdd070ff02a\_sa_hanhua_out\sa_lib-forge-1.20.1-1.0.1.jar'
|
||||
|
||||
with zipfile.ZipFile(jar) as z:
|
||||
infos = z.infolist()
|
||||
data = {i.filename: z.read(i) for i in infos}
|
||||
meta = 'META-INF/mods.toml'
|
||||
text = data[meta].decode('utf-8')
|
||||
|
||||
new_text = re.sub(
|
||||
r"description\s*=\s*'''[\s\S]*?'''",
|
||||
"description='''\n我们所有幸存者军火库模组的公共库。\n'''",
|
||||
text,
|
||||
count=1,
|
||||
)
|
||||
print('changed:', new_text != text)
|
||||
print(new_text[:400])
|
||||
if new_text != text:
|
||||
data[meta] = new_text.encode('utf-8')
|
||||
tmp = jar + '.tmp'
|
||||
with zipfile.ZipFile(tmp, 'w', zipfile.ZIP_DEFLATED) as z:
|
||||
for i in infos:
|
||||
z.writestr(i, data[i.filename])
|
||||
shutil.move(tmp, jar)
|
||||
print('jar updated.')
|
||||
|
||||
# verify
|
||||
with zipfile.ZipFile(jar) as z:
|
||||
t = z.read(meta).decode('utf-8')
|
||||
for line in t.splitlines():
|
||||
if 'displayName' in line or 'description' in line:
|
||||
print('VERIFY:', line.strip())
|
||||
print('entries=', len(z.namelist()), 'testzip=', z.testzip())
|
||||
@@ -0,0 +1,68 @@
|
||||
import zipfile, os, re, shutil
|
||||
|
||||
base = r'e:\MCStudioDownload\work\3027246179@qq.com\Cpp\AddOn\309c2d420bc84ee986db9cdd070ff02a\_sa_hanhua_out'
|
||||
jars = {
|
||||
'essentials': base + r'\sa_essentials-forge-1.20.1-1.0.0.jar',
|
||||
'lib': base + r'\sa_lib-forge-1.20.1-1.0.1.jar',
|
||||
'decor': base + r'\sa_decor-forge-1.20.1-1.0.3.jar',
|
||||
}
|
||||
|
||||
# 每个 jar 的 mods.toml 替换规则:(旧字符串, 新字符串) 或 (正则, 新, is_regex)
|
||||
repls = {
|
||||
'essentials': [
|
||||
('displayName = "Survivors Arsenal: Essentials"',
|
||||
'displayName = "幸存者军火库:基础包"'),
|
||||
('description = "Combat, survival and essential gameplay content for Survivors Arsenal."',
|
||||
'description = "幸存者军火库的战斗、生存与核心玩法内容。"'),
|
||||
],
|
||||
'lib': [
|
||||
('displayName="Survivor\'s Arsenal: Lib"',
|
||||
'displayName="幸存者军火库:核心"'),
|
||||
(r"description\s*=\s*'''[\s\S]*?'''",
|
||||
"description='''\n我们所有幸存者军火库模组的公共库。\n'''"),
|
||||
],
|
||||
'decor': [
|
||||
('displayName="Survivor\'s Arsenal: Loot & Decor"',
|
||||
'displayName="幸存者军火库:战利品与装饰"'),
|
||||
('description="Decoration module for Survivor\'s Arsenal."',
|
||||
'description="幸存者军火库的装饰模块。"'),
|
||||
],
|
||||
}
|
||||
|
||||
for name, jar in jars.items():
|
||||
with zipfile.ZipFile(jar) as z:
|
||||
infos = z.infolist()
|
||||
data = {i.filename: z.read(i) for i in infos}
|
||||
meta = 'META-INF/mods.toml'
|
||||
text = data[meta].decode('utf-8')
|
||||
orig = text
|
||||
for old, new in repls[name]:
|
||||
if text.find(old) != -1:
|
||||
text = text.replace(old, new)
|
||||
print(f'[{name}] replaced: {old[:60]!r}')
|
||||
else:
|
||||
print(f'[{name}] WARN not found: {old[:60]!r}')
|
||||
if text == orig:
|
||||
print(f'[{name}] NO CHANGES!')
|
||||
continue
|
||||
data[meta] = text.encode('utf-8')
|
||||
|
||||
# 重建 jar
|
||||
tmp = jar + '.tmp'
|
||||
with zipfile.ZipFile(tmp, 'w', zipfile.ZIP_DEFLATED) as z:
|
||||
for i in infos:
|
||||
z.writestr(i, data[i.filename])
|
||||
shutil.move(tmp, jar)
|
||||
print(f'[{name}] jar updated.')
|
||||
|
||||
# 验证
|
||||
print('\n===== VERIFY =====')
|
||||
for name, jar in jars.items():
|
||||
with zipfile.ZipFile(jar) as z:
|
||||
t = z.read('META-INF/mods.toml').decode('utf-8')
|
||||
for line in t.splitlines():
|
||||
if 'displayName' in line or 'description' in line:
|
||||
print(f'[{name}] {line.strip()}')
|
||||
# 检查 jar 完好
|
||||
bad = z.testzip()
|
||||
print(f'[{name}] entries={len(z.namelist())} testzip={bad}')
|
||||
@@ -0,0 +1,42 @@
|
||||
import zipfile, os, shutil
|
||||
|
||||
base = r'e:\MCStudioDownload\work\3027246179@qq.com\Cpp\AddOn\309c2d420bc84ee986db9cdd070ff02a\_sa_hanhua_out'
|
||||
jar = base + r'\sa_essentials-forge-1.20.1-1.0.0.jar'
|
||||
target = 'com/ogaba/sa_combat/client/event/SACombatClientForgeEvents.class'
|
||||
|
||||
old_ascii = b'Reloading...' # 11 字节
|
||||
old_pat = b'\x01\x00\x0b' + old_ascii # CONSTANT_Utf8 tag + u2 length(11) + bytes
|
||||
new_utf8 = '换弹中...'.encode('utf-8') # 12 字节 (E6 8D A2 E5 BC B9 E4 B8 AD 2E 2E 2E)
|
||||
new_pat = b'\x01\x00\x0c' + new_utf8
|
||||
print('new bytes:', new_utf8.hex())
|
||||
|
||||
with zipfile.ZipFile(jar) as z:
|
||||
infos = z.infolist()
|
||||
data = {i.filename: z.read(i) for i in infos}
|
||||
|
||||
b = data[target]
|
||||
cnt = b.count(old_pat)
|
||||
print('occurrences of utf8-const pattern:', cnt)
|
||||
if cnt != 1:
|
||||
raise SystemExit('ABORT: expected exactly 1 occurrence')
|
||||
|
||||
nb = b.replace(old_pat, new_pat)
|
||||
print('class size: %d -> %d' % (len(b), len(nb)))
|
||||
|
||||
# 验证替换后不再含旧 ASCII(单独出现可能在其他字段;此处仅验证常量池模式消失)
|
||||
print('old const gone:', nb.count(old_pat) == 0)
|
||||
|
||||
data[target] = nb
|
||||
tmp = jar + '.tmp'
|
||||
with zipfile.ZipFile(tmp, 'w', zipfile.ZIP_DEFLATED) as z:
|
||||
for i in infos:
|
||||
z.writestr(i, data[i.filename])
|
||||
shutil.move(tmp, jar)
|
||||
print('jar updated.')
|
||||
|
||||
# verify
|
||||
with zipfile.ZipFile(jar) as z:
|
||||
nb = z.read(target)
|
||||
print('new const present:', nb.count(new_pat) == 1)
|
||||
print('old ascii anywhere in class:', nb.count(old_ascii))
|
||||
print('entries=', len(z.namelist()), 'testzip=', z.testzip())
|
||||
Loaded 100 of 851 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user